From 6c77cc430b1e78bd3d0acf1cc078e60775647956 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Mon, 17 Nov 2008 19:16:43 +0100 Subject: Implement Quick Connect feature --- UConnectionManager.pas | 237 +++++++++++++++++++++++++++++-------------------- 1 file changed, 140 insertions(+), 97 deletions(-) (limited to 'UConnectionManager.pas') diff --git a/UConnectionManager.pas b/UConnectionManager.pas index 3703b02..2b39a51 100644 --- a/UConnectionManager.pas +++ b/UConnectionManager.pas @@ -24,7 +24,7 @@ interface uses glib2, gdk2, gtk2, pango, SysUtils, Types, Classes, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts, GTKView, GTKUtils, GTKDialogs, GTKPixbuf, GTKClasses, - UCore, UCoreClasses, UVFSCore, UEngines, URemoteWait; + UCore, UCoreClasses, UVFSCore, UEngines; type TFConnectionManager = class(TGTKDialog) @@ -37,11 +37,14 @@ type ListViewScrolledWindow: TGTKScrolledWindow; ListViewTable: TGTKTable; AddConnectionButton, EditButton, RemoveButton: TGTKImageButton; + QuickConnectButton: TGTKImageButton; ButtonBox: TGTKVButtonBox; ActionButtonBox: TGTKHButtonBox; - ConnectButton, CloseButton: TGTKButton; + ConnectButton, StopButton, CloseButton: TGTKButton; DoNotSavePasswordsCheckBox, DoNotSynchronizeKeyringCheckBox: TGTKCheckButton; procedure FormCreate(Sender: TObject); override; + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormResponse(Sender: TObject; const ResponseID: integer); procedure ListViewSelectionChanged(Sender: TObject); procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); procedure AddConnectionButtonClick(Sender: TObject); @@ -51,16 +54,17 @@ type procedure ListViewKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); procedure CloseButtonClick(Sender: TObject); procedure ConnectButtonClick(Sender: TObject); + procedure StopButtonClick(Sender: TObject); + procedure QuickConnectButtonClick(Sender: TObject); private - FSilenceError: boolean; - AFRemoteWait: TFRemoteWait; - FActiveConnInfo: TConnMgrItem; - FVFSAskPasswordTry: integer; procedure FillList; procedure DoConnect; public + FSilenceError: boolean; + Thread: TOpenConnectionThread; SourcePanelEngine: TPanelEngine; ConnectedEngine: TVFSEngine; + function DoConnectInternal(const URI: string; Engine: TVFSEngine; VFSDialogsParentWindow: PGtkWidget): boolean; end; var @@ -68,12 +72,13 @@ var implementation -uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, uVFSprototypes; +uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, UQuickConnect; procedure TFConnectionManager.FormCreate(Sender: TObject); var Column: TGTKTreeViewColumn; begin + Thread := nil; ConnectedEngine := nil; SetDefaultSize(650, 500); Caption := LANGConnMgr_Caption; @@ -84,6 +89,9 @@ begin ConnectButton.Caption := LANGConnMgr_ConnectButton; // ConnectButton.Default := True; CloseButton := TGTKButton.CreateFromStock(Self, GTK_STOCK_CLOSE); + StopButton := TGTKButton.CreateFromStock(Self, GTK_STOCK_STOP); + StopButton.Visible := False; + StopButton.Enabled := False; // Default := ConnectButton; ActionButtonBox := TGTKHButtonBox.Create(Self); ActionButtonBox.Layout := blEnd; @@ -91,6 +99,7 @@ begin ActionButtonBox.BorderWidth := 0; ActionButtonBox.AddControlEnd(CloseButton); ActionButtonBox.AddControlEnd(ConnectButton); + ActionButtonBox.AddControlEnd(StopButton); ActionArea.AddControlEx(ActionButtonBox, False, False, 0); @@ -159,26 +168,30 @@ begin RemoveButton.Caption := LANGConnMgr_RemoveButtonCaption; RemoveButton.UseUnderline := True; RemoveButton.Tooltip := LANGConnMgr_RemoveButtonTooltip; - + + QuickConnectButton := TGTKImageButton.Create(Self); + QuickConnectButton.SetFromStock('gtk-connect', isSmallToolbar); + QuickConnectButton.Caption := LANGmiQuickConnectCaption; + QuickConnectButton.UseUnderline := True; + ButtonBox := TGTKVButtonBox.Create(Self); ButtonBox.Spacing := 10; + ButtonBox.AddControl(QuickConnectButton); +// ButtonBox.AddControl(TGTKHSeparator.Create(Self)); + ButtonBox.AddControl(TGTKEventBox.Create(Self)); ButtonBox.AddControl(AddConnectionButton); ButtonBox.AddControl(EditButton); ButtonBox.AddControl(RemoveButton); DoNotSavePasswordsCheckBox := TGTKCheckButton.CreateWithLabel(Self, '_Do not store passwords internally (but still use gnome-keyring)'); DoNotSavePasswordsCheckBox.Tooltip := 'By checking this option on, Tux Commander will never save passwords into its connection list. Due to the GVFS nature, gnome-keyring will still be used to retrieve stored passwords from your desktop session.'; - DoNotSynchronizeKeyringCheckBox := TGTKCheckButton.CreateWithLabel(Self, 'Do not synchronize passwords to _gnome-keyring'); + DoNotSynchronizeKeyringCheckBox := TGTKCheckButton.CreateWithLabel(Self, 'Do not synchronize passwords to gnome-_keyring'); DoNotSynchronizeKeyringCheckBox.Tooltip := 'Don''t tell gnome-keyring to save any passwords.'; ListViewTable.AddControlEx(0, 1, 3, 5, ListViewScrolledWindow, [taoExpand, taoFill], [taoExpand, taoFill], 0, 5); ListViewTable.AddControlEx(0, 6, 3, 1, DoNotSavePasswordsCheckBox, [taoExpand, taoFill], [taoShrink], 10, 0); ListViewTable.AddControlEx(0, 7, 3, 1, DoNotSynchronizeKeyringCheckBox, [taoExpand, taoFill], [taoShrink], 10, 2); ListViewTable.AddControlEx(3, 2, 1, 3, ButtonBox, [taoShrink, taoFill], [taoShrink], 5, 5); -{ ListViewTable.AddControlEx(3, 2, 1, 1, AddConnectionButton, [taoShrink, taoFill], [taoShrink], 5, 5); - ListViewTable.AddControlEx(3, 3, 1, 1, EditButton, [taoShrink, taoFill], [taoShrink], 5, 5); - ListViewTable.AddControlEx(3, 4, 1, 1, RemoveButton, [taoShrink, taoFill], [taoShrink], 5, 5); } -// ListViewTable.AddControlEx(3, 1, 1, 1, TGTKLabel.Create(Self), [taoShrink, taoFill], [taoExpand, taoFill], 0, 2); ListViewTable.AddControlEx(3, 5, 1, 1, TGTKLabel.Create(Self), [taoShrink, taoFill], [taoExpand, taoFill], 0, 2); @@ -193,7 +206,11 @@ begin RemoveButton.OnClick := RemoveButtonClick; CloseButton.OnClick := CloseButtonClick; ConnectButton.OnClick := ConnectButtonClick; + StopButton.OnClick := StopButtonClick; + QuickConnectButton.OnClick := QuickConnectButtonClick; OnKeyDown := FormKeyDown; + OnClose := FormClose; + OnResponse := FormResponse; end; procedure TFConnectionManager.ListViewSelectionChanged(Sender: TObject); @@ -208,8 +225,13 @@ end; procedure TFConnectionManager.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); begin case Key of - GDK_RETURN, GDK_KP_ENTER: if Assigned(ListView.Selected) then DoConnect; - GDK_ESCAPE: ModalResult := mbCancel; + GDK_RETURN, GDK_KP_ENTER: if StopButton.Visible then StopButtonClick(Sender) else + if Assigned(ListView.Selected) then DoConnect; + GDK_ESCAPE: begin + Accept := False; + if StopButton.Visible then StopButtonClick(Sender) + else ModalResult := mbCancel; + end; end; end; @@ -225,6 +247,20 @@ begin end; end; +procedure TFConnectionManager.FormClose(Sender: TObject; var Action: TCloseAction); +begin + if ListView.Selected <> nil then ConfConnMgrActiveItem := ListView.Selected.Index; + ConfConnMgrDoNotSavePasswords := DoNotSavePasswordsCheckBox.Checked; + ConfConnMgrDoNotSynchronizeKeyring := DoNotSynchronizeKeyringCheckBox.Checked; +end; + +procedure TFConnectionManager.FormResponse(Sender: TObject; const ResponseID: integer); +var Action: TCloseAction; +begin + FormClose(Sender, Action); +end; + + (********************************************************************************************************************************) (********************************************************************************************************************************) procedure TFConnectionManager.AddConnectionButtonClick(Sender: TObject); @@ -324,8 +360,6 @@ var i: integer; Item: TGTKListItem; ConnMgrItem: TConnMgrItem; begin - ReadConnections; - if ConnectionMgrList.Count > 0 then for i := 0 to ConnectionMgrList.Count - 1 do begin ConnMgrItem := ConnectionMgrList[i]; @@ -353,88 +387,36 @@ begin DoConnect; end; -procedure vfs_ask_question_callback(const AMessage: PChar; const Choices: PPChar; choice: PInteger; cancel_choice: Integer; user_data: Pointer); cdecl; -var ConnMgr: TFConnectionManager; - DialogParent: PGtkWidget; +procedure TFConnectionManager.StopButtonClick(Sender: TObject); begin - ConnMgr := user_data; - DialogParent := nil; -// DebugMsg(['******* vfs_ask_question_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); - if ConnMgr is TFConnectionManager then begin - if ConnMgr.AFRemoteWait <> nil then DialogParent := ConnMgr.AFRemoteWait.FWidget - else DialogParent := ConnMgr.FWidget; - end; - HandleVFSAskQuestionCallback(DialogParent, AMessage, Choices, choice); - if ConnMgr is TFConnectionManager then begin - if choice <> nil then ConnMgr.FSilenceError := (choice^ < 0) or (choice^ = cancel_choice); - end; + if Thread <> nil then Thread.FCancelRequested := True; end; -function vfs_ask_password_callback(const AMessage: PChar; const default_user: PChar; const default_domain: PChar; const default_password: PChar; flags: TVFSAskPasswordFlags; - username, password: PPChar; anonymous: PInteger; domain: PPChar; password_save: PVFSPasswordSave; - user_data: Pointer): LongBool; cdecl; -var ConnMgr: TFConnectionManager; - DialogParent: PGtkWidget; +procedure TFConnectionManager.QuickConnectButtonClick(Sender: TObject); +var AFQuickConnect: TFQuickConnect; begin - ConnMgr := user_data; - DialogParent := nil; -// DebugMsg(['******* vfs_ask_password_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); - if ConnMgr is TFConnectionManager then begin - Inc(ConnMgr.FVFSAskPasswordTry); - if ConnMgr.AFRemoteWait <> nil then DialogParent := ConnMgr.AFRemoteWait.FWidget - else DialogParent := ConnMgr.FWidget; - - if not ConnMgr.DoNotSavePasswordsCheckBox.Checked then - flags := flags or VFS_ASK_PASSWORD_SAVE_INTERNAL; - - // Disable password saving if requested - if ConnMgr.DoNotSynchronizeKeyringCheckBox.Checked then begin - flags := flags and (not VFS_ASK_PASSWORD_SAVING_SUPPORTED); - if password_save <> nil then password_save^ := VFS_PASSWORD_SAVE_NEVER; - end; - end; - - // First pass, supply stored password if we have one - if (ConnMgr is TFConnectionManager) and (ConnMgr.FVFSAskPasswordTry = 1) and (password <> nil) and - ((flags and VFS_ASK_PASSWORD_NEED_PASSWORD) = VFS_ASK_PASSWORD_NEED_PASSWORD) and ((flags and VFS_ASK_PASSWORD_NEED_USERNAME) = 0) and - (ConnMgr.FActiveConnInfo <> nil) and (Length(ConnMgr.FActiveConnInfo.Password) > 0) then - begin - DebugMsg(['(II) vfs_ask_password_callback: Supplying stored password from Connection Manager']); - Result := True; - password^ := g_strdup(PChar(ConnMgr.FActiveConnInfo.Password)); - if password_save <> nil then - if ConnMgr.DoNotSynchronizeKeyringCheckBox.Checked - then password_save^ := VFS_PASSWORD_SAVE_NEVER - else password_save^ := VFS_PASSWORD_SAVE_PERMANENTLY; - end else begin - // Show password dialog and continue in loop - Result := HandleVFSAskPasswordCallback(DialogParent, AMessage, default_user, default_domain, default_password, flags, username, password, anonymous, domain, password_save); - if ConnMgr is TFConnectionManager then begin - ConnMgr.FSilenceError := Result = False; - // Save password back to Connection Manager - if Result and (password_save <> nil) and (password_save^ = VFS_PASSWORD_SAVE_PERMANENTLY) and - (ConnMgr.FActiveConnInfo <> nil) and (password <> nil) and (strlen(password^) > 0) and - (not ConnMgr.DoNotSavePasswordsCheckBox.Checked) then - begin - DebugMsg(['(II) vfs_ask_password_callback: Saving password to Connection Manager']); - ConnMgr.FActiveConnInfo.Password := password^; - end; + ConfConnMgrDoNotSavePasswords := DoNotSavePasswordsCheckBox.Checked; + ConfConnMgrDoNotSynchronizeKeyring := DoNotSynchronizeKeyringCheckBox.Checked; + try + AFQuickConnect := TFQuickConnect.Create(Self); + AFQuickConnect.SourcePanelEngine := SourcePanelEngine; + AFQuickConnect.ConnectionManager := Self; + if (AFQuickConnect.Run = mbOK) and (AFQuickConnect.ConnectedEngine <> nil) then begin + ConnectedEngine := AFQuickConnect.ConnectedEngine; + ModalResult := mbOK; end; + finally + AFQuickConnect.Free; end; - - // Strip password saving if requested - if (ConnMgr is TFConnectionManager) and ConnMgr.DoNotSynchronizeKeyringCheckBox.Checked and (password_save <> nil) then - password_save^ := VFS_PASSWORD_SAVE_NEVER; end; +(********************************************************************************************************************************) procedure TFConnectionManager.DoConnect; var Engine: TVFSEngine; i, j: integer; VFSPlugin: TVFSPlugin; - b: boolean; + FActiveConnInfo: TConnMgrItem; begin - FSilenceError := False; - FActiveConnInfo := nil; if ListView.Selected <> nil then FActiveConnInfo := ListView.Selected.AsPointer(0); if FActiveConnInfo = nil then Exit; @@ -467,30 +449,91 @@ begin if (SourcePanelEngine is TVFSEngine) and (Application.MessageBox(PGtkWindow(FWidget), LANGCloseOpenConnection, [mbYes, mbNo], mbWarning, mbYes, mbNo) <> mbYes) then Exit; + ListViewTable.Enabled := False; + CloseButton.Enabled := False; + ConnectButton.Enabled := False; + ConnectButton.Visible := False; + StopButton.Enabled := True; + StopButton.Visible := True; + StopButton.Default := True; + StopButton.SetFocus; + + ConfConnMgrDoNotSavePasswords := DoNotSavePasswordsCheckBox.Checked; + ConfConnMgrDoNotSynchronizeKeyring := DoNotSynchronizeKeyringCheckBox.Checked; + // Construct the VFS Engine and try to open the connection Engine := TVFSEngine.Create(VFSPlugin); Engine.ParentEngine := SourcePanelEngine; Engine.SavePath := SourcePanelEngine.Path; + Engine.Password := FActiveConnInfo.Password; + Engine.PasswordUsed := False; - AFRemoteWait := TFRemoteWait.Create(Application); - AFRemoteWait.ParentForm := FConnectionManager; - AFRemoteWait.ShowModal; - Application.ProcessMessages; - - FVFSAskPasswordTry := 0; - b := Engine.VFSOpenURI(UTF8ToStr(FActiveConnInfo.GetURI(False)), @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self); - - AFRemoteWait.Free; - AFRemoteWait := nil; - if not b then begin + if not DoConnectInternal(UTF8ToStr(FActiveConnInfo.GetURI(False)), Engine, FWidget) then begin if not FSilenceError then Application.MessageBox(PGtkWindow(FWidget), LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK); + ListViewTable.Enabled := True; + CloseButton.Enabled := True; + ConnectButton.Enabled := True; + ConnectButton.Visible := True; + StopButton.Visible := False; + StopButton.Enabled := False; + ListView.SetFocus; + Engine.Free; Exit; end; + if not DoNotSavePasswordsCheckBox.Checked then FActiveConnInfo.Password := Engine.Password; + Engine.Password := ''; // Security precaution + StopButton.Enabled := False; ConnectedEngine := Engine; ModalResult := mbOK; end; +function TFConnectionManager.DoConnectInternal(const URI: string; Engine: TVFSEngine; VFSDialogsParentWindow: PGtkWidget): boolean; +begin + Result := False; + FSilenceError := False; + Thread := TOpenConnectionThread.Create; + try + Thread.VFSConnectionManagerMode := VFSDialogsParentWindow = FWidget; + Thread.VFSDialogsParentWindow := VFSDialogsParentWindow; + Thread.AEngine := Engine; + Thread.URI := URI; + Thread.Resume; + repeat + Sleep(ConstInternalProgressTimer); + Application.ProcessMessages; + if Thread.VFSAskQuestion_Display then begin + Thread.VFSAskQuestion_Display := False; + DebugMsg(['Main thread: displaying question dialog']); + HandleVFSAskQuestionCallback(FWidget, Thread.VFSAskQuestion_Message, Thread.VFSAskQuestion_Choices, Thread.VFSAskQuestion_Choice); + Thread.VFSCallbackEvent.SetEvent; + end; + if Thread.VFSAskPassword_Display then begin + Thread.VFSAskPassword_Display := False; + DebugMsg(['Main thread: displaying password prompt']); + Thread.VFSAskPassword_Result := HandleVFSAskPasswordCallback(FWidget, + Thread.VFSAskPassword_Message, + Thread.VFSAskPassword_default_user, + Thread.VFSAskPassword_default_domain, + Thread.VFSAskPassword_default_password, + Thread.VFSAskPassword_flags, + Thread.VFSAskPassword_username, + Thread.VFSAskPassword_password, + Thread.VFSAskPassword_anonymous, + Thread.VFSAskPassword_domain, + Thread.VFSAskPassword_password_save); + Thread.VFSCallbackEvent.SetEvent; + end; + until Thread.Finished; + Result := Thread.OpenResult; + FSilenceError := Thread.VFSCallbackCancelled; + Thread.Free; + Thread := nil; + except + on E: Exception do DebugMsg(['*** Exception raised in TFConnectionManager.DoConnect (', E.ClassName, '): ', E.Message]); + end; +end; + end. -- cgit v1.2.3