(* Tux Commander - UQuickConnect - Quick connection dialog Copyright (C) 2008 Tomas Bzatek Check for updates on tuxcmd.sourceforge.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) unit UQuickConnect; interface uses SysUtils, Classes, lazglib2, lazgdk3, lazgtk3, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKPixbuf, UCore, UVFSCore, UEngines, UConnectionManager; type TFQuickConnect = class(TGTKDialog) TitleFrame: TGTKFrame; TitleLabel: TGTKLabel; TitleEventBox: TGTKEventBox; TitleIcon: TGTKImage; TitleHBox: TGTKHBox; Grid: TGTKGrid; ActionButtonBox: TGTKHButtonBox; ConnectButton, StopButton, CloseButton: TGTKButton; Label1, Label2: TGTKLabel; URIComboBox: TGTKComboBoxEntry; PluginComboBox: TGTKComboBoxText; procedure FormCreate(Sender: TObject); override; procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormResponse(Sender: TObject; const ResponseID: integer); procedure CloseButtonClick(Sender: TObject); procedure ConnectButtonClick(Sender: TObject); procedure StopButtonClick(Sender: TObject); procedure ComboBoxKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); procedure ComboBoxChanged(Sender: TObject); private AFConnectionManager: TFConnectionManager; SavedData: string; procedure DoConnect; public SourcePanelEngine: TPanelEngine; ConnectedEngine: TVFSEngine; ConnectionManager: TFConnectionManager; end; var FQuickConnect: TFQuickConnect; implementation uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, UError; procedure TFQuickConnect.FormCreate(Sender: TObject); var i: integer; begin SavedData := ''; ConnectedEngine := nil; ConnectionManager := nil; AFConnectionManager := nil; SetDefaultSize(435, 200); Caption := LANGFQuickConnect_Caption; Buttons := []; ConnectButton := TGTKButton.Create(Self); ConnectButton.Caption := LANGConnMgr_ConnectButton; // ConnectButton.Default := True; CloseButton := TGTKButton.CreateFromIconName(Self, 'gtk-close'); CloseButton.Caption := 'Close'; StopButton := TGTKButton.CreateFromIconName(Self, 'gtk-stop'); StopButton.Caption := 'Stop'; StopButton.Visible := False; StopButton.Enabled := False; // Default := ConnectButton; ActionButtonBox := TGTKHButtonBox.Create(Self); ActionButtonBox.Layout := blEnd; ActionButtonBox.Spacing := 10; ActionButtonBox.BorderWidth := 0; ActionButtonBox.AddControlEnd(CloseButton); ActionButtonBox.AddControlEnd(ConnectButton); ActionButtonBox.AddControlEnd(StopButton); ActionArea.AddControlEx(ActionButtonBox, False, False, 0); TitleEventBox := TGTKEventBox.Create(Self); TitleLabel := TGTKLabel.Create(Self); TitleLabel.Caption := Format('%s', [LANGFQuickConnect_TitleLabel_Caption]); TitleLabel.UseMarkup := True; TitleLabel.XAlign := 0; TitleLabel.MarginStart := 0; TitleLabel.MarginEnd := 0; TitleLabel.MarginTop := 3; TitleLabel.MarginBottom := 3; TitleEventBox.ControlState := csPrelight; TitleFrame := TGTKFrame.CreateWithoutLabel(Self); TitleFrame.ShadowType := stShadowOut; TitleIcon := TGTKImage.Create(Self); TitleIcon.SetFromIconName('gtk-connect', isLargeToolbar); TitleHBox := TGTKHBox.Create(Self); TitleHBox.Homogeneous := False; TitleHBox.AddControlEx(TGTKEventBox.Create(Self), False, False, 5); TitleHBox.AddControlEx(TitleIcon, False, False, 0); TitleHBox.AddControlEx(TitleLabel, True, True, 10); TitleEventBox.AddControl(TitleHBox); TitleFrame.AddControl(TitleEventBox); ClientArea.AddControlEx(TitleFrame, False, True, 0); Grid := TGTKGrid.Create(Self); Grid.BorderWidth := 25; ClientArea.AddControlEx(Grid, True, True, 0); URIComboBox := TGtkComboBoxEntry.Create(Self); URIComboBox.MarginTop := 5; URIComboBox.MarginBottom := 5; PluginComboBox := TGTKComboBoxText.Create(Self); PluginComboBox.MarginTop := 5; PluginComboBox.MarginBottom := 5; Label1 := TGTKLabel.Create(Self); Label1.Caption := Format('%s', [LANGFQuickConnect_ConnectToURILabel_Caption]); Label1.FocusControl := URIComboBox.Entry; Label1.UseMarkup := True; Label1.UseUnderline := True; Label1.XAlign := 0; Label1.MarginTop := 2; Label1.MarginBottom := 2; Label2 := TGTKLabel.Create(Self); Label2.Caption := LANGConnProp_VFSModule; Label2.FocusControl := PluginComboBox; Label2.UseUnderline := True; Label2.XAlign := 0; Label2.MarginStart := 10; Label2.MarginEnd := 10; Label2.MarginTop := 5; Label2.MarginBottom := 5; if QuickConnectHistory.Count > 0 then for i := 0 to QuickConnectHistory.Count - 1 do URIComboBox.AppendItem(QuickConnectHistory[i]); URIComboBox.Entry.Text := ''; // Fill the plugins menu PluginComboBox.AppendItem(LANGConnProp_MenuItemCaption); for i := 0 to PluginList.Count - 1 do if TVFSPlugin(PluginList[i]).HandlesNetwork then PluginComboBox.AppendItemID(TVFSPlugin(PluginList[i]).ModuleID, Format('%s [%s]', [TVFSPlugin(PluginList[i]).ModuleName, ExtractFileName(TVFSPlugin(PluginList[i]).FullModulePath)])); // Find last used plugin if (Length(Trim(ConfQuickConnectPluginID)) > 0) and (PluginList.Count > 0) then PluginComboBox.ItemID := ConfQuickConnectPluginID else PluginComboBox.ItemIndex := 0; // Grid.AddControlEx(1, 1, 2, 1, TGTKEventBox.Create(Self), [taoExpand, taoFill], [taoShrink], 0, 2); Grid.AddControl(0, 0, 2, 1, Label1); Grid.AddControl(0, 1, 2, 1, URIComboBox); Grid.AddControl(0, 2, 1, 1, Label2); Grid.AddControl(1, 2, 1, 1, PluginComboBox); CloseButton.OnClick := @CloseButtonClick; ConnectButton.OnClick := @ConnectButtonClick; StopButton.OnClick := @StopButtonClick; OnKeyDown := @FormKeyDown; OnClose := @FormClose; OnResponse := @FormResponse; URIComboBox.Entry.OnKeyDown := @ComboBoxKeyDown; URIComboBox.Entry.OnChanged := @ComboBoxChanged; ComboBoxChanged(Sender); end; procedure TFQuickConnect.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); begin case Key of GDK_KEY_Return, GDK_KEY_KP_Enter: if StopButton.Visible then StopButtonClick(Sender) else if ConnectButton.Enabled then DoConnect; GDK_KEY_Escape: begin Accept := False; if StopButton.Visible then StopButtonClick(Sender) else ModalResult := mbCancel; end; end; end; procedure TFQuickConnect.ComboBoxKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); var Orig, s: string; i: integer; begin case Key of GDK_KEY_Up, GDK_KEY_Down: if Shift = [] then begin Accept := False; if QuickConnectHistory.Count > 0 then begin Orig := Trim(URIComboBox.Entry.Text); i := QuickConnectHistory.IndexOf(Orig); if Key = GDK_KEY_Down then begin if i < 0 then begin SavedData := Orig; i := 0; end else if QuickConnectHistory.Count > i + 1 then Inc(i); s := QuickConnectHistory[i]; end else begin if i < 0 then Exit else if i = 0 then begin s := SavedData; SavedData := ''; end else if QuickConnectHistory.Count > i then s := QuickConnectHistory[i - 1]; end; URIComboBox.Entry.Text := s; URIComboBox.Entry.SetFocus; URIComboBox.Entry.SelectAll; end; end; end; end; procedure TFQuickConnect.ComboBoxChanged(Sender: TObject); begin ConnectButton.Enabled := Length(Trim(URIComboBox.Entry.Text)) > 0; end; procedure TFQuickConnect.FormClose(Sender: TObject; var Action: TCloseAction); begin if Length(Trim(URIComboBox.Entry.Text)) > 0 then SaveItemToHistory(URIComboBox.Entry.Text, QuickConnectHistory); ConfQuickConnectPluginID := PluginComboBox.ItemID; end; procedure TFQuickConnect.FormResponse(Sender: TObject; const ResponseID: integer); var Action: TCloseAction; begin FormClose(Sender, Action); end; (********************************************************************************************************************************) procedure TFQuickConnect.CloseButtonClick(Sender: TObject); begin ModalResult := mbCancel; end; procedure TFQuickConnect.ConnectButtonClick(Sender: TObject); begin DoConnect; end; procedure TFQuickConnect.StopButtonClick(Sender: TObject); begin if (AFConnectionManager <> nil) and (AFConnectionManager.Thread <> nil) then AFConnectionManager.Thread.FCancelled := True; end; procedure TFQuickConnect.DoConnect; var Engine: TVFSEngine; i, j: integer; VFSPlugin: TVFSPlugin; URI, Scheme: string; DontShowAgain: boolean; res: TMessageButton; Error: PGError; begin if ConnectionManager <> nil then AFConnectionManager := ConnectionManager else AFConnectionManager := TFConnectionManager.Create(Self); if PluginList.Count = 0 then begin Application.MessageBox(PGtkWindow(FWidget), LANGThereIsNoModuleAvailable, [mbOK], mbError, mbOK, mbOK); Exit; end; // Find VFS module to use for this connection VFSPlugin := nil; if Length(PluginComboBox.ItemID) > 0 then begin VFSPlugin := LookupVFSPlugin(PluginComboBox.ItemID); ConfQuickConnectPluginID := VFSPlugin.ModuleID; end else ConfQuickConnectPluginID := ''; if VFSPlugin = nil then begin Scheme := ''; if Pos('://', URIComboBox.Entry.Text) > 0 then Scheme := Copy(URIComboBox.Entry.Text, 1, Pos('://', URIComboBox.Entry.Text) - 1); for i := 0 to PluginList.Count - 1 do begin if Length(TVFSPlugin(PluginList[i]).Services) > 0 then for j := 0 to Length(TVFSPlugin(PluginList[i]).Services) - 1 do if WideCompareText(TVFSPlugin(PluginList[i]).Services[j], Scheme) = 0 then begin VFSPlugin := TVFSPlugin(PluginList[i]); Break; end; if VFSPlugin <> nil then Break; end; if VFSPlugin = nil then VFSPlugin := TVFSPlugin(PluginList[0]); // Fallback in hope some other plugin can handle it end; if (SourcePanelEngine is TVFSEngine) and ConfReplaceConnectionWarning then begin DontShowAgain := False; res := MessageBoxShowOnce(PGtkWindow(FWidget), LANGCloseOpenConnection, LANGDontShowAgain, DontShowAgain, [mbYes, mbNo], mbWarning, mbYes, mbNo); if DontShowAgain then begin ConfReplaceConnectionWarning := False; WriteMainGUISettings; end; if res <> mbYes then Exit; end; Grid.Enabled := False; CloseButton.Enabled := False; ConnectButton.Enabled := False; ConnectButton.Visible := False; StopButton.Enabled := True; StopButton.Visible := True; StopButton.Default := True; StopButton.SetFocus; // Construct the VFS Engine and try to open the connection Engine := TVFSEngine.Create(VFSPlugin); Engine.ParentEngine := SourcePanelEngine; Engine.SavePath := SourcePanelEngine.Path; Engine.OpenedFromQuickConnect := True; Engine.CustomPluginIDSave := ConfQuickConnectPluginID; URI := URIComboBox.Entry.Text; Engine.Password := URIRipPassword(URI, True); Error := nil; if not AFConnectionManager.DoConnectInternal(URI, Engine, Self, True, @Error) then begin if not AFConnectionManager.FSilenceError then ShowError(Self, 'Couldn''t open the URI specified', Error); Grid.Enabled := True; CloseButton.Enabled := True; ConnectButton.Enabled := True; ConnectButton.Visible := True; StopButton.Visible := False; StopButton.Enabled := False; URIComboBox.Entry.SetFocus; Engine.Free; if Error <> nil then g_error_free(Error); Exit; end; Engine.Password := ''; // Security precaution StopButton.Enabled := False; ConnectedEngine := Engine; if ConnectionManager = nil then AFConnectionManager.Free; ModalResult := mbOK; end; end.