(* 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 glib2, gdk2, gtk2, pango, SysUtils, Types, Classes, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts, GTKView, GTKUtils, GTKDialogs, GTKPixbuf, GTKClasses, GTKMenus, UCore, UCoreClasses, UVFSCore, UEngines, UConnectionManager; type TFQuickConnect = class(TGTKDialog) TitleFrame: TGTKFrame; TitleLabel: TGTKLabel; TitleEventBox: TGTKEventBox; TitleIcon: TGTKImage; TitleHBox: TGTKHBox; Table: TGTKTable; ActionButtonBox: TGTKHButtonBox; ConnectButton, StopButton, CloseButton: TGTKButton; Label1, Label2: TGTKLabel; URIComboBox: TGTKCombo; PluginOptionMenu: TGTKOptionMenu; 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, uVFSprototypes; procedure TFQuickConnect.FormCreate(Sender: TObject); var i: integer; MenuItem: TGTKMenuItem; begin SavedData := ''; ConnectedEngine := nil; ConnectionManager := nil; AFConnectionManager := nil; SetDefaultSize(435, 200); Caption := 'Quick connect'; Buttons := []; ShowSeparator := False; ConnectButton := TGTKButton.Create(Self); 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; 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', ['Quick connect']); TitleLabel.UseMarkup := True; TitleLabel.XAlign := 0; TitleLabel.XPadding := 0; TitleLabel.YPadding := 3; TitleEventBox.ControlState := csPrelight; TitleFrame := TGTKFrame.CreateWithoutLabel(Self); TitleFrame.ShadowType := stShadowOut; TitleIcon := TGTKImage.Create(Self); TitleIcon.SetFromStock('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); Table := TGTKTable.Create(Self); Table.BorderWidth := 25; ClientArea.AddControlEx(Table, True, True, 0); URIComboBox := TGtkCombo.Create(Self); URIComboBox.DisableActivate; PluginOptionMenu := TGTKOptionMenu.Create(Self); Label1 := TGTKLabel.Create(Self); Label1.Caption := Format('%s', ['C_onnect to URI:']); Label1.FocusControl := URIComboBox.Entry; Label1.UseMarkup := True; Label1.UseUnderline := True; Label1.XAlign := 0; Label2 := TGTKLabel.Create(Self); Label2.Caption := LANGConnProp_VFSModule; Label2.FocusControl := PluginOptionMenu; Label2.UseUnderline := True; Label2.XAlign := 0; if QuickConnectHistory.Count > 0 then for i := 0 to QuickConnectHistory.Count - 1 do URIComboBox.Items.Append(QuickConnectHistory[i]); URIComboBox.Entry.Text := ''; // Fill the plugins menu MenuItem := TGTKMenuItem.CreateTyped(Self, itLabel); MenuItem.Caption := LANGConnProp_MenuItemCaption; PluginOptionMenu.Items.Add(MenuItem); for i := 0 to PluginList.Count - 1 do begin MenuItem := TGTKMenuItem.CreateTyped(Self, itImageText); MenuItem.SetCaptionPlain(Format('%s [%s]', [TVFSPlugin(PluginList[i]).VFSName, ExtractFileName(TVFSPlugin(PluginList[i]).FullPath)])); PluginOptionMenu.Items.Add(MenuItem); end; // Find last used plugin if Length(Trim(ConfQuickConnectPluginID)) > 0 then for i := 0 to PluginList.Count - 1 do if TVFSPlugin(PluginList[i]).VFSName = ConfQuickConnectPluginID then begin PluginOptionMenu.ItemIndex := i + 1; Break; end; // Table.AddControlEx(1, 1, 2, 1, TGTKEventBox.Create(Self), [taoExpand, taoFill], [taoShrink], 0, 2); Table.AddControlEx(0, 0, 2, 1, Label1, [taoShrink, taoFill], [taoShrink], 0, 2); Table.AddControlEx(0, 1, 2, 1, URIComboBox, [taoExpand, taoFill], [taoShrink], 0, 5); Table.AddControlEx(0, 2, 1, 1, Label2, [taoShrink, taoFill], [taoShrink], 10, 5); Table.AddControlEx(1, 2, 1, 1, PluginOptionMenu, [taoExpand, taoFill], [taoShrink], 0, 5); 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_RETURN, GDK_KP_ENTER: if StopButton.Visible then StopButtonClick(Sender) else if ConnectButton.Enabled then DoConnect; GDK_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_UP, GDK_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_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); if PluginOptionMenu.ItemIndex <> 0 then ConfQuickConnectPluginID := TVFSPlugin(PluginList[PluginOptionMenu.ItemIndex - 1]).VFSName else ConfQuickConnectPluginID := ''; 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.FCancelRequested := True; end; procedure TFQuickConnect.DoConnect; var Engine: TVFSEngine; i, j: integer; VFSPlugin: TVFSPlugin; URI, Scheme: string; 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 PluginOptionMenu.ItemIndex <> 0 then ConfQuickConnectPluginID := TVFSPlugin(PluginList[PluginOptionMenu.ItemIndex - 1]).VFSName else ConfQuickConnectPluginID := ''; if Length(ConfQuickConnectPluginID) > 0 then for i := 0 to PluginList.Count - 1 do if TVFSPlugin(PluginList[i]).VFSName = ConfQuickConnectPluginID then begin VFSPlugin := PluginList[i]; Break; end; 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 := PluginList[i]; Break; end; if VFSPlugin <> nil then Break; end; if VFSPlugin = nil then VFSPlugin := PluginList[0]; // Fallback in hope some other plugin can handle it end; if (SourcePanelEngine is TVFSEngine) and (Application.MessageBox(PGtkWindow(FWidget), LANGCloseOpenConnection, [mbYes, mbNo], mbWarning, mbYes, mbNo) <> mbYes) then Exit; Table.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); if not AFConnectionManager.DoConnectInternal(URI, Engine, FWidget, True) then begin if not AFConnectionManager.FSilenceError then Application.MessageBox(PGtkWindow(FWidget), LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK); Table.Enabled := True; CloseButton.Enabled := True; ConnectButton.Enabled := True; ConnectButton.Visible := True; StopButton.Visible := False; StopButton.Enabled := False; URIComboBox.Entry.SetFocus; Engine.Free; Exit; end; Engine.Password := ''; // Security precaution StopButton.Enabled := False; ConnectedEngine := Engine; if ConnectionManager = nil then AFConnectionManager.Free; ModalResult := mbOK; end; end.