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 --- UCore.pas | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 19 deletions(-) (limited to 'UCore.pas') diff --git a/UCore.pas b/UCore.pas index b7f3067..afe8b10 100644 --- a/UCore.pas +++ b/UCore.pas @@ -20,7 +20,7 @@ unit UCore; interface -uses glib2, SyncObjs, Classes, GTKForms, GTKView, ULibc, UEngines, UCoreUtils, UProgress, UVFSCore, uVFSprototypes; +uses glib2, gtk2, SyncObjs, Classes, GTKForms, GTKView, ULibc, UEngines, UCoreUtils, UProgress, UVFSCore, uVFSprototypes; function FillPanel(List: TList; ListView: TGTKListView; Engine: TPanelEngine; LeftPanel: boolean): boolean; @@ -59,6 +59,11 @@ type TVFSCallbackThread = class(TThread) VFSCallbackCancelled: boolean; + VFSConnectionManagerMode: boolean; + VFSDialogsParentWindow: PGtkWidget; + + FCancelRequested: boolean; + constructor Create(CreateSuspended: boolean); destructor Destroy; override; end; @@ -100,7 +105,6 @@ type TVFSCallbackThread = class(TThread) FCallbackLockEvent: TSimpleEvent; - // Parameters ProgressForm: TFProgress; Engine, SrcEngine, DestEngine: TPanelEngine; @@ -169,11 +173,23 @@ type TVFSCallbackThread = class(TThread) Finished, CancelIt: boolean; RunningTime: Int64; AFullPath, AHighlightItem: string; + constructor Create; + destructor Destroy; override; + end; + TOpenConnectionThread = class(TVFSCallbackThread) + private + protected + procedure Execute; override; + public + URI: string; + Finished: boolean; + OpenResult: boolean; constructor Create; destructor Destroy; override; end; + // Thread aware functions (also half-thread-safe) without any piece of GTK code procedure DeleteFilesWorker(SenderThread: TWorkerThread); procedure CopyFilesWorker(SenderThread: TWorkerThread); @@ -237,6 +253,7 @@ var LeftLocalEngine, RightLocalEngine: TPanelEngine; FMainEscPressed: boolean; UsedTempPaths: TStringList; SelectHistory, SearchHistory: TStringList; + QuickConnectHistory: TStringList; (********************************************************************************************************************************) implementation @@ -258,6 +275,9 @@ begin VFSAskQuestion_Display := False; VFSAskPassword_Display := False; VFSCallbackCancelled := False; + VFSConnectionManagerMode := False; + VFSDialogsParentWindow := FMain.FWidget; + FCancelRequested := False; end; destructor TVFSCallbackThread.Destroy; @@ -282,9 +302,16 @@ begin Exit; end; + if Thread.FCancelRequested then begin + DebugMsg(['!! (WARNING): vfs_ask_question_callback: FCancelRequested.']); + if (choice <> nil) then choice^ := -1; + Thread.VFSCallbackCancelled := True; + Exit; + end; + if pthread_self = Application.ThreadID then begin - DebugMsg(['!! (WARNING): vfs_ask_question_callback called from the main thread, expected spawn from a OpenDirThread']); - HandleVFSAskQuestionCallback(FMain.FWidget, AMessage, Choices, choice); + DebugMsg(['!! (WARNING): vfs_ask_question_callback called from the main thread, expected spawn from a TVFSCallbackThread']); + HandleVFSAskQuestionCallback(Thread.VFSDialogsParentWindow, AMessage, Choices, choice); if (choice <> nil) then Thread.VFSCallbackCancelled := (choice^ < 0) or (choice^ = cancel_choice); Exit; end; @@ -302,8 +329,8 @@ begin Exit; end; - DebugMsg(['!! (ERROR): vfs_ask_question_callback spawned neither from the main thread nor from active OpenDirThread, dropping the callback to prevent data corruption.']); - DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', OpenDirThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); + DebugMsg(['!! (ERROR): vfs_ask_question_callback spawned neither from the main thread nor from active TVFSCallbackThread, dropping the callback to prevent data corruption.']); + DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', TVFSCallbackThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); end; function vfs_ask_password_callback(const AMessage: PChar; const default_user: PChar; const default_domain: PChar; const default_password: PChar; flags: TVFSAskPasswordFlags; @@ -319,6 +346,13 @@ begin Exit; end; + if Thread.FCancelRequested then begin + DebugMsg(['!! (WARNING): vfs_ask_password_callback: FCancelRequested.']); + Result := False; + Thread.VFSCallbackCancelled := True; + Exit; + end; + def_pass := default_password; // Disable password saving if requested @@ -326,27 +360,33 @@ begin flags := flags and (not VFS_ASK_PASSWORD_SAVING_SUPPORTED); if password_save <> nil then password_save^ := VFS_PASSWORD_SAVE_NEVER; end; - if ConfConnMgrDoNotSavePasswords then - flags := flags and (not VFS_ASK_PASSWORD_SAVE_INTERNAL); + if ConfConnMgrDoNotSavePasswords then flags := flags and (not VFS_ASK_PASSWORD_SAVE_INTERNAL) else + if Thread.VFSConnectionManagerMode then flags := flags or VFS_ASK_PASSWORD_SAVE_INTERNAL; + // Use stored password, if previously set - if ((flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE) and (password <> nil) and - (Thread.AEngine is TVFSEngine) and (Length((Thread.AEngine as TVFSEngine).Password) > 0) then + if (((flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE) or Thread.VFSConnectionManagerMode) and + (password <> nil) and (Thread.AEngine is TVFSEngine) and (Length((Thread.AEngine as TVFSEngine).Password) > 0) then begin if not (Thread.AEngine as TVFSEngine).PasswordUsed then begin DebugMsg([' (II) vfs_ask_password_callback: reusing manually set password']); password^ := g_strdup(PChar((Thread.AEngine as TVFSEngine).Password)); (Thread.AEngine as TVFSEngine).PasswordUsed := True; - Result := True; + if (password_save <> nil) and Thread.VFSConnectionManagerMode then + if ConfConnMgrDoNotSynchronizeKeyring then password_save^ := VFS_PASSWORD_SAVE_NEVER + else password_save^ := VFS_PASSWORD_SAVE_PERMANENTLY; Thread.VFSCallbackCancelled := False; + Result := True; Exit; - end else def_pass := PChar((Thread.AEngine as TVFSEngine).Password); + end else + if (flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE then + def_pass := PChar((Thread.AEngine as TVFSEngine).Password); end; // Ask for password if pthread_self = Application.ThreadID then begin - DebugMsg(['!! (WARNING): vfs_ask_password_callback called from the main thread, expected spawn from a OpenDirThread']); - Result := HandleVFSAskPasswordCallback(FMain.FWidget, AMessage, default_user, default_domain, def_pass, flags, username, password, anonymous, domain, password_save); + DebugMsg(['!! (WARNING): vfs_ask_password_callback called from the main thread, expected spawn from a TVFSCallbackThread']); + Result := HandleVFSAskPasswordCallback(Thread.VFSDialogsParentWindow, AMessage, default_user, default_domain, def_pass, flags, username, password, anonymous, domain, password_save); Thread.VFSCallbackCancelled := Result = False; end else if pthread_self = Thread.FThreadID then begin @@ -370,14 +410,14 @@ begin Thread.VFSCallbackCancelled := Result = False; end else begin - DebugMsg(['!! (ERROR): vfs_ask_password_callback spawned neither from the main thread nor from active OpenDirThread, dropping the callback to prevent data corruption.']); - DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', OpenDirThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); + DebugMsg(['!! (ERROR): vfs_ask_password_callback spawned neither from the main thread nor from active TVFSCallbackThread, dropping the callback to prevent data corruption.']); + DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', TVFSCallbackThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); end; // Save password back to the engine - if ((flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE) and - Result and (password <> nil) and (strlen(password^) > 0) and - (Thread.AEngine is TVFSEngine) then + if Result and (password <> nil) and (strlen(password^) > 0) and (Thread.AEngine is TVFSEngine) and + (((flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE) or + (Thread.VFSConnectionManagerMode and (password_save <> nil) and (password_save^ = VFS_PASSWORD_SAVE_PERMANENTLY))) then begin (Thread.AEngine as TVFSEngine).Password := string(password^); (Thread.AEngine as TVFSEngine).PasswordUsed := True; @@ -2903,6 +2943,32 @@ begin end; end; + +(********************************************************************************************************************************) +(********************************************************************************************************************************) +constructor TOpenConnectionThread.Create; +begin + inherited Create(True); + FreeOnTerminate := False; + Finished := False; + OpenResult := False; +end; + +destructor TOpenConnectionThread.Destroy; +begin + inherited Destroy; +end; + +procedure TOpenConnectionThread.Execute; +begin + PrepareExecute; + try + OpenResult := (AEngine as TVFSEngine).VFSOpenURI(URI, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self); + finally + Finished := True; + end; +end; + (********************************************************************************************************************************) (********************************************************************************************************************************) function PurgeDirectory(APath: string): boolean; -- cgit v1.2.3