(*
    Tux Commander - UQuickConnect - Quick connection dialog
    Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net>
    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 := LANGFQuickConnect_Caption;
  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('<span size="x-large" weight="ultrabold">%s</span>', [LANGFQuickConnect_TitleLabel_Caption]);
  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('<span weight="ultrabold">%s</span>', [LANGFQuickConnect_ConnectToURILabel_Caption]);
  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
    if TVFSPlugin(PluginList[i]).HandlesNetwork then begin
      MenuItem := TGTKMenuItem.CreateTyped(Self, itImageText);
      MenuItem.Data := PluginList[i];
      MenuItem.SetCaptionPlain(Format('%s [%s]', [TVFSPlugin(PluginList[i]).ModuleName,
                                                  ExtractFileName(TVFSPlugin(PluginList[i]).FullModulePath)]));
      PluginOptionMenu.Items.Add(MenuItem);
    end;

  //  Find last used plugin
  if (Length(Trim(ConfQuickConnectPluginID)) > 0) and (PluginOptionMenu.Items.Count > 0) then
    for i := 0 to PluginOptionMenu.Items.Count - 1 do
      if (PluginOptionMenu.Items[i].Data <> nil) and (TVFSPlugin(PluginOptionMenu.Items[i].Data).ModuleID = ConfQuickConnectPluginID) then begin
        PluginOptionMenu.ItemIndex := i;
        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) and (PluginOptionMenu.Items[PluginOptionMenu.ItemIndex].Data <> nil)
    then ConfQuickConnectPluginID := TVFSPlugin(PluginOptionMenu.Items[PluginOptionMenu.ItemIndex].Data).ModuleID
    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;
    DontShowAgain: boolean;
    res: TMessageButton;
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) and (PluginOptionMenu.Items[PluginOptionMenu.ItemIndex].Data <> nil) then begin
    VFSPlugin := PluginOptionMenu.Items[PluginOptionMenu.ItemIndex].Data;
    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 := 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 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;

  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.


