瀏覽代碼

ADD: Primitive realization of Group-Paired Tab Sets

meteu 9 年之前
父節點
當前提交
e0703efcfc
共有 10 個文件被更改,包括 313 次插入65 次删除
  1. 5 5
      src/doublecmd.lpi
  2. 1 1
      src/doublecmd.lpr
  3. 61 39
      src/fmain.lfm
  4. 6 0
      src/fmain.lrt
  5. 138 11
      src/fmain.pas
  6. 1 1
      src/fviewer.lfm
  7. 6 1
      src/ufileviewnotebook.pas
  8. 5 1
      src/uglobs.pas
  9. 5 0
      src/ulng.pas
  10. 85 6
      src/umaincommands.pas

+ 5 - 5
src/doublecmd.lpi

@@ -37,7 +37,7 @@
             <Filename Value="..\doublecmd"/>
           </Target>
           <SearchPaths>
-            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk;..\units"/>
+            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk"/>
             <OtherUnitFiles Value="platform;platform\$(SrcOS);..\sdk;frames;fileviews;filesources;filesources\filesystem;filesources\multiarchive;filesources\multilist;filesources\searchresult;filesources\tempfilesystem;filesources\vfs;filesources\wcxarchive;filesources\wfxplugin;filesources\winnet;platform\unix\glib;platform\unix\mime;filesources\gio"/>
             <UnitOutputDirectory Value="..\units\$(TargetCPU)-$(TargetOS)-$(LCLWidgetType)"/>
             <SrcPath Value="$(LazarusDir)\lcl;$(LazarusDir)\lcl\interfaces\$(LCLWidgetType);$(fpcsrcdir)\packages\fcl-base\src"/>
@@ -80,7 +80,7 @@
             <Filename Value="..\doublecmd"/>
           </Target>
           <SearchPaths>
-            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk;..\units"/>
+            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk"/>
             <OtherUnitFiles Value="platform;platform\$(SrcOS);..\sdk;frames;fileviews;filesources;filesources\filesystem;filesources\multiarchive;filesources\multilist;filesources\searchresult;filesources\tempfilesystem;filesources\vfs;filesources\wcxarchive;filesources\wfxplugin;filesources\winnet;platform\unix\glib;platform\unix\mime;filesources\gio"/>
             <UnitOutputDirectory Value="..\units\$(TargetCPU)-$(TargetOS)-$(LCLWidgetType)"/>
             <SrcPath Value="$(LazarusDir)\lcl;$(LazarusDir)\lcl\interfaces\$(LCLWidgetType);$(fpcsrcdir)\packages\fcl-base\src"/>
@@ -119,7 +119,7 @@
             <Filename Value="..\doublecmd"/>
           </Target>
           <SearchPaths>
-            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk;..\units"/>
+            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk"/>
             <OtherUnitFiles Value="platform;platform\$(SrcOS);..\sdk;frames;fileviews;filesources;filesources\filesystem;filesources\multiarchive;filesources\multilist;filesources\searchresult;filesources\tempfilesystem;filesources\vfs;filesources\wcxarchive;filesources\wfxplugin;filesources\winnet;platform\unix\glib;platform\unix\mime;filesources\gio"/>
             <UnitOutputDirectory Value="..\units\$(TargetCPU)-$(TargetOS)-$(LCLWidgetType)"/>
             <SrcPath Value="$(LazarusDir)\lcl;$(LazarusDir)\lcl\interfaces\$(LCLWidgetType);$(fpcsrcdir)\packages\fcl-base\src"/>
@@ -161,7 +161,7 @@
             <Filename Value="..\doublecmd"/>
           </Target>
           <SearchPaths>
-            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk;..\units"/>
+            <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk"/>
             <OtherUnitFiles Value="platform;platform\$(SrcOS);..\sdk;frames;fileviews;filesources;filesources\filesystem;filesources\multiarchive;filesources\multilist;filesources\searchresult;filesources\tempfilesystem;filesources\vfs;filesources\wcxarchive;filesources\wfxplugin;filesources\winnet;platform\unix\glib;platform\unix\mime;filesources\gio"/>
             <UnitOutputDirectory Value="..\units\$(TargetCPU)-$(TargetOS)-$(LCLWidgetType)"/>
             <SrcPath Value="$(LazarusDir)\lcl;$(LazarusDir)\lcl\interfaces\$(LCLWidgetType);$(fpcsrcdir)\packages\fcl-base\src"/>
@@ -1610,7 +1610,7 @@ end;"/>
       <Filename Value="..\doublecmd"/>
     </Target>
     <SearchPaths>
-      <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk;..\units"/>
+      <IncludeFiles Value="$(LazarusDir)\ide;$(ProjOutDir);..\sdk"/>
       <OtherUnitFiles Value="platform;platform\$(SrcOS);..\sdk;frames;fileviews;filesources;filesources\filesystem;filesources\multiarchive;filesources\multilist;filesources\searchresult;filesources\tempfilesystem;filesources\vfs;filesources\wcxarchive;filesources\wfxplugin;filesources\winnet;platform\unix\glib;platform\unix\mime;filesources\gio"/>
       <UnitOutputDirectory Value="..\units\$(TargetCPU)-$(TargetOS)-$(LCLWidgetType)"/>
       <SrcPath Value="$(LazarusDir)\lcl;$(LazarusDir)\lcl\interfaces\$(LCLWidgetType);$(fpcsrcdir)\packages\fcl-base\src"/>

+ 1 - 1
src/doublecmd.lpr

@@ -127,7 +127,7 @@ begin
   DCDebug('Double Commander ' + dcVersion);
   DCDebug('Revision: ' + dcRevision);
   DCDebug('Build: ' + dcBuildDate);
-  DCDebug('Lazarus: ' + GetLazarusVersion);
+  DCDebug('Lazarus: ' + lazVersion + '-' + lazRevision);
   DCDebug('Free Pascal: ' + fpcVersion);
   DCDebug('Platform: ' + TargetCPU + '-' + TargetOS + '-' + TargetWS);
   DCDebug('System: ' + OSVersion);

+ 61 - 39
src/fmain.lfm

@@ -46,7 +46,7 @@ object frmMain: TfrmMain
   end
   object TreePanel: TPanel
     Left = 0
-    Height = 194
+    Height = 191
     Top = 20
     Width = 121
     Align = alLeft
@@ -55,18 +55,18 @@ object frmMain: TfrmMain
   end
   object TreeSplitter: TSplitter
     Left = 121
-    Height = 194
+    Height = 191
     Top = 20
     Width = 5
   end
   object pnlMain: TPanel
     Left = 126
-    Height = 194
+    Height = 191
     Top = 20
     Width = 634
     Align = alClient
     BevelOuter = bvNone
-    ClientHeight = 194
+    ClientHeight = 191
     ClientWidth = 634
     TabOrder = 5
     object pnlDisk: TPanel
@@ -150,24 +150,24 @@ object frmMain: TfrmMain
     end
     object pnlNotebooks: TPanel
       Left = 0
-      Height = 170
+      Height = 167
       Top = 24
       Width = 634
       Align = alClient
       BevelOuter = bvNone
-      ClientHeight = 170
+      ClientHeight = 167
       ClientWidth = 634
       FullRepaint = False
       TabOrder = 1
       OnResize = pnlNotebooksResize
       object pnlLeft: TPanel
         Left = 0
-        Height = 170
+        Height = 167
         Top = 0
         Width = 511
         Align = alLeft
         BevelOuter = bvNone
-        ClientHeight = 170
+        ClientHeight = 167
         ClientWidth = 511
         TabOrder = 0
         OnDblClick = pnlLeftRightDblClick
@@ -288,12 +288,12 @@ object frmMain: TfrmMain
       end
       object pnlRight: TPanel
         Left = 511
-        Height = 170
+        Height = 167
         Top = 0
         Width = 123
         Align = alClient
         BevelOuter = bvNone
-        ClientHeight = 170
+        ClientHeight = 167
         ClientWidth = 123
         TabOrder = 1
         OnDblClick = pnlLeftRightDblClick
@@ -429,7 +429,7 @@ object frmMain: TfrmMain
   object PanelAllProgress: TPanel
     Left = 0
     Height = 0
-    Top = 214
+    Top = 211
     Width = 760
     Align = alBottom
     AutoSize = True
@@ -440,7 +440,7 @@ object frmMain: TfrmMain
     Cursor = crVSplit
     Left = 0
     Height = 3
-    Top = 214
+    Top = 211
     Width = 760
     Align = alBottom
     AutoSnap = False
@@ -451,35 +451,35 @@ object frmMain: TfrmMain
   object pnlCommand: TPanel
     AnchorSideBottom.Control = LogSplitter
     Left = 0
-    Height = 78
-    Top = 217
+    Height = 81
+    Top = 214
     Width = 760
     Align = alBottom
     AutoSize = True
     BevelOuter = bvNone
-    ClientHeight = 78
+    ClientHeight = 81
     ClientWidth = 760
     FullRepaint = False
     TabOrder = 8
     object pnlCmdLine: TPanel
       Left = 0
-      Height = 24
+      Height = 27
       Top = 54
       Width = 760
       Align = alClient
       AutoSize = True
       BevelOuter = bvNone
       ChildSizing.TopBottomSpacing = 2
-      ClientHeight = 24
+      ClientHeight = 27
       ClientWidth = 760
       TabOrder = 1
       object lblCommandPath: TLabel
         AnchorSideTop.Control = edtCommand
         AnchorSideTop.Side = asrCenter
         Left = 0
-        Height = 14
-        Top = 5
-        Width = 28
+        Height = 15
+        Top = 6
+        Width = 24
         Caption = 'Path'
         ParentColor = False
         ShowAccelChar = False
@@ -490,13 +490,13 @@ object frmMain: TfrmMain
         AnchorSideTop.Control = pnlCmdLine
         AnchorSideRight.Control = pnlCmdLine
         AnchorSideRight.Side = asrBottom
-        Left = 32
-        Height = 20
+        Left = 28
+        Height = 23
         Top = 2
-        Width = 728
+        Width = 732
         Anchors = [akTop, akLeft, akRight]
         BorderSpacing.Left = 4
-        ItemHeight = 14
+        ItemHeight = 15
         OnExit = edtCommandExit
         OnKeyDown = edtCommandKeyDown
         TabOrder = 0
@@ -924,67 +924,67 @@ object frmMain: TfrmMain
       Left = 0
       Height = 20
       Top = 0
-      Width = 88
+      Width = 89
       Action = actView
       Flat = True
     end
     object btnF4: TSpeedButton
-      Left = 88
+      Left = 89
       Height = 20
       Top = 0
-      Width = 83
+      Width = 84
       Action = actEdit
       Flat = True
     end
     object btnF5: TSpeedButton
-      Left = 171
+      Left = 173
       Height = 20
       Top = 0
-      Width = 91
+      Width = 92
       Action = actCopy
       Flat = True
     end
     object btnF6: TSpeedButton
-      Left = 262
+      Left = 265
       Height = 20
       Top = 0
-      Width = 91
+      Width = 94
       Action = actRename
       Flat = True
     end
     object btnF7: TSpeedButton
-      Left = 353
+      Left = 359
       Height = 20
       Top = 0
-      Width = 117
+      Width = 112
       Action = actMakeDir
       Caption = 'Directory'
       Flat = True
     end
     object btnF8: TSpeedButton
-      Left = 470
+      Left = 471
       Height = 20
       Top = 0
-      Width = 100
+      Width = 97
       Caption = 'Delete'
       Flat = True
       OnClick = btnF8Click
       OnMouseDown = btnF8MouseDown
     end
     object btnF9: TSpeedButton
-      Left = 570
+      Left = 568
       Height = 20
       Top = 0
-      Width = 110
+      Width = 111
       Action = actRunTerm
       Caption = 'Terminal'
       Flat = True
     end
     object btnF10: TSpeedButton
-      Left = 680
+      Left = 679
       Height = 20
       Top = 0
-      Width = 80
+      Width = 81
       Action = actExit
       Caption = 'Exit'
       Flat = True
@@ -1236,6 +1236,20 @@ object frmMain: TfrmMain
         Action = actLoadTabs
       end
     end
+    object mnuGroups: TMenuItem
+      Caption = 'Groups'
+      object mnuNewGroup: TMenuItem
+        Action = actNewGroup
+        Caption = 'New Group'
+      end
+      object mnuRestoreActiveGroup: TMenuItem
+        Action = actRestoreActiveGroup
+        Caption = 'Restore Active Group'
+      end
+      object miLine34: TMenuItem
+        Caption = '-'
+      end
+    end
     object mnuShow: TMenuItem
       Caption = '&Show'
       object mnuBriefView: TMenuItem
@@ -2386,6 +2400,14 @@ object frmMain: TfrmMain
       Caption = 'Close Duplicate Tabs'
       OnExecute = actExecute
     end
+    object actNewGroup: TAction
+      Caption = 'actNewGroup'
+      OnExecute = actExecute
+    end
+    object actRestoreActiveGroup: TAction
+      Caption = 'actRestoreActiveGroup'
+      OnExecute = actExecute
+    end
   end
   object pmHotList: TPopupMenu
     Images = imgLstDirectoryHotlist

+ 6 - 0
src/fmain.lrt

@@ -41,6 +41,10 @@ TFRMMAIN.MILINE16.CAPTION=-
 TFRMMAIN.MNUTABOPTIONS.CAPTION=&Options
 TFRMMAIN.MILINE17.CAPTION=-
 TFRMMAIN.MILINE38.CAPTION=-
+TFRMMAIN.MNUGROUPS.CAPTION=Groups
+TFRMMAIN.MNUNEWGROUP.CAPTION=New Group
+TFRMMAIN.MNURESTOREACTIVEGROUP.CAPTION=Restore Active Group
+TFRMMAIN.MILINE34.CAPTION=-
 TFRMMAIN.MNUSHOW.CAPTION=&Show
 TFRMMAIN.MILINE33.CAPTION=-
 TFRMMAIN.MILINE32.CAPTION=-
@@ -225,6 +229,8 @@ TFRMMAIN.ACTCOUNTDIRCONTENT.CAPTION=Sho&w Occupied Space
 TFRMMAIN.ACTTOGGLEFULLSCREENCONSOLE.CAPTION=Toggle fullscreen mode console
 TFRMMAIN.ACTTREEVIEW.CAPTION=&Tree View Panel
 TFRMMAIN.ACTCLOSEDUPLICATETABS.CAPTION=Close Duplicate Tabs
+TFRMMAIN.ACTNEWGROUP.CAPTION=actNewGroup
+TFRMMAIN.ACTRESTOREACTIVEGROUP.CAPTION=actRestoreActiveGroup
 TFRMMAIN.TBEDIT.CAPTION=Edit
 TFRMMAIN.TBDELETE.CAPTION=Delete
 TFRMMAIN.TBCHANGEDIR.CAPTION=CD

+ 138 - 11
src/fmain.pas

@@ -98,6 +98,8 @@ type
     actCopyPathNoSepOfFilesToClip: TAction;
     actDoAnyCmCommand: TAction;
     actCloseDuplicateTabs: TAction;
+    actNewGroup: TAction;
+    actRestoreActiveGroup: TAction;
     actTreeView: TAction;
     actToggleFullscreenConsole: TAction;
     actSrcOpenDrives: TAction;
@@ -203,6 +205,11 @@ type
     lblRightDriveInfo: TLabel;
     lblLeftDriveInfo: TLabel;
     lblCommandPath: TLabel;
+    miLine34: TMenuItem;
+
+    mnuRestoreActiveGroup: TMenuItem;
+    mnuNewGroup: TMenuItem;
+    mnuGroups: TMenuItem;
     mnuCloseDuplicateTabs: TMenuItem;
     miCloseDuplicateTabs: TMenuItem;
     mnuTreeView: TMenuItem;
@@ -466,6 +473,7 @@ type
       Shift: TShiftState; X, Y: Integer);
     procedure FormKeyUp( Sender: TObject; var Key: Word; Shift: TShiftState) ;
     function MainToolBarToolItemShortcutsHint(ToolItem: TKASNormalItem): String;
+    procedure mnuGroupNameTabsClick(Sender: TObject);
     procedure mnuAllOperStartClick(Sender: TObject);
     procedure mnuAllOperStopClick(Sender: TObject);
     procedure mnuAllOperPauseClick(Sender: TObject);
@@ -658,6 +666,8 @@ type
     procedure SetDragCursor(Shift: TShiftState);
 
   public
+    LastActiveGroup:string; // name of groups user last clicked
+
     constructor Create(TheOwner: TComponent); override;
     Function ActiveFrame: TFileView;  // get Active frame
     Function NotActiveFrame: TFileView; // get NotActive frame :)
@@ -720,8 +730,13 @@ type
     procedure AssignEvents(AFileView: TFileView);
     function RemovePage(ANoteBook: TFileViewNotebook; iPageIndex:Integer; CloseLocked: Boolean = True): LongInt;
     procedure LoadTabsIni(ANoteBook: TFileViewNotebook);
-    procedure LoadTabsXml(AConfig: TXmlConfig; ANoteBook: TFileViewNotebook);
-    procedure SaveTabsXml(AConfig: TXmlConfig; ANoteBook: TFileViewNotebook);
+    procedure LoadTabsXml(AConfig: TXmlConfig; ABrunch:string; ANoteBook: TFileViewNotebook);
+    procedure SaveTabsXml(AConfig: TXmlConfig; ABrunch:string; ANoteBook: TFileViewNotebook);
+
+    procedure LoadGroupXml(AConfig: TXmlConfig; AGroupName: string);
+    procedure SaveGroupXml(AConfig: TXmlConfig; AGroupName: string);
+
+    procedure CreateGroupsMainMenuItems; // add menu items on FormCreate if file 'groups.xml' is exists
     procedure ToggleConsole;
     procedure UpdateWindowView;
     procedure MinimizeWindow;
@@ -982,6 +997,7 @@ begin
 {$ENDIF}
 
   LoadTabs;
+  CreateGroupsMainMenuItems;
 
   // Update selected drive and free space before main form is shown,
   // otherwise there is a bit of delay.
@@ -1330,6 +1346,17 @@ begin
   Result := ShortcutsToText(TfrmOptionsToolbar.GetShortcuts(ToolItem));
 end;
 
+procedure TfrmMain.mnuGroupNameTabsClick(Sender: TObject);
+var
+  AConfig:TXmlConfig;
+  AGroupName: string;
+begin
+  AGroupName := (Sender as TMenuItem).Name;
+  LastActiveGroup := Copy(AGroupName, 11, Length(AGroupName) - 4);
+  Commands.Commands.ExecuteCommand('cm_RestoreActiveGroup', []);
+end;
+
+
 procedure TfrmMain.miLogMenuClick(Sender: TObject);
 begin
   case (Sender as TMenuItem).Tag of
@@ -4185,7 +4212,10 @@ begin
     ANoteBook.PageIndex := iActiveTab;
 end;
 
-procedure TfrmMain.LoadTabsXml(AConfig: TXmlConfig; ANoteBook: TFileViewNotebook);
+
+
+procedure TfrmMain.LoadTabsXml(AConfig: TXmlConfig; ABrunch:string; ANoteBook: TFileViewNotebook);
+// default was ABrunch: 'Tabs/OpenedTabs/'
 var
   sPath, sViewType: String;
   iActiveTab: Integer;
@@ -4196,9 +4226,9 @@ var
   RootNode, TabNode, ViewNode: TXmlNode;
 begin
   if ANoteBook = nbLeft then
-    RootNode := AConfig.FindNode(AConfig.RootNode, 'Tabs/OpenedTabs/Left')
+    RootNode := AConfig.FindNode(AConfig.RootNode,ABrunch+ '/Left')
   else
-    RootNode := AConfig.FindNode(AConfig.RootNode, 'Tabs/OpenedTabs/Right');
+    RootNode := AConfig.FindNode(AConfig.RootNode,ABrunch+ '/Right');
 
   if Assigned(RootNode) then
   begin
@@ -4284,14 +4314,16 @@ begin
   end;
 end;
 
-procedure TfrmMain.SaveTabsXml(AConfig: TXmlConfig; ANoteBook: TFileViewNotebook);
+
+procedure TfrmMain.SaveTabsXml(AConfig: TXmlConfig;ABrunch:string; ANoteBook: TFileViewNotebook);
+// brunch was: 'Tabs/OpenedTabs'
 var
   I: Integer;
   TabsSection: String;
   Page: TFileViewPage;
   RootNode, TabNode, ViewNode: TXmlNode;
 begin
-  RootNode := AConfig.FindNode(AConfig.RootNode, 'Tabs/OpenedTabs', True);
+  RootNode := AConfig.FindNode(AConfig.RootNode, ABrunch, True);
   if ANoteBook = nbLeft then
     TabsSection := 'Left'
   else
@@ -4312,6 +4344,101 @@ begin
     end;
 end;
 
+
+procedure TfrmMain.CreateGroupsMainMenuItems;
+var
+  i,cnt:integer;
+  mitNewGroup:TMenuItem;
+  AConfig: TXmlConfig;
+  sNewGroup:string;
+  aParentNode:TXmlNode;
+begin
+
+  if not FileExists('groups.xml') then exit;
+
+  try
+    AConfig:= TXmlConfig.Create('groups.xml',True);
+
+    try
+      AConfig.Load;
+      aParentNode:=AConfig.FindNode(AConfig.RootNode, 'GroupsNameBank/');
+
+      i:=0;
+      cnt:=aParentNode.ChildNodes.Count;
+      while(i<cnt)do
+      begin
+        sNewGroup:=aParentNode.ChildNodes[i].NodeName;
+
+        mitNewGroup:=TMenuItem.Create(frmMain.mnuMain);
+        mitNewGroup.Caption:=sNewGroup;
+        mitNewGroup.Name:='miGrpName_'+sNewGroup;
+        mitNewGroup.OnClick:=@mnuGroupNameTabsClick;
+
+        mnuGroups.Add(mitNewGroup);
+      inc(i);
+      end;
+
+    finally
+      AConfig.Free;
+    end;
+  except
+    on E: Exception do
+      msgError(E.Message);
+  end;
+
+end;
+
+
+procedure TfrmMain.LoadGroupXml(AConfig: TXmlConfig;
+  AGroupName: string);
+var
+  sPath, sViewType: String;
+  iActiveTab: Integer;
+  Page: TFileViewPage;
+  AFileView: TFileView;
+  AFileViewFlags: TFileViewFlags;
+  aFileSource: IFileSource;
+  aParentNode,RootNode, TabNode, ViewNode: TXmlNode;
+begin
+
+  // 1) Verify - is the AGroupName exist in brunch GroupsNameBank?
+
+  aParentNode:=AConfig.FindNode(AConfig.RootNode, 'GroupsNameBank/'+AGroupName);
+  if aParentNode= nil then exit;
+
+  // Load left tabs of group in XML Node: Groups/<GroupName>/Left
+
+  // 2) Save current active group data to brunch 'Groups/<AGroupName>'
+
+  LeftTabs.DestroyAllPages;
+  LoadTabsXml(AConfig,'Groups/'+AGroupName,nbLeft);
+
+  RightTabs.DestroyAllPages;
+  LoadTabsXml(AConfig,'Groups/'+AGroupName,nbRight);
+
+end;
+
+procedure TfrmMain.SaveGroupXml(AConfig: TXmlConfig;
+  AGroupName: string);
+var
+  I: Integer;
+  TabsSection: String;
+  Page: TFileViewPage;
+  ParentNode,RootNode, TabNode, ViewNode: TXmlNode;
+begin
+
+  // 1) Write New group name to brunch GroupsNameBank
+
+  ParentNode := AConfig.FindNode(AConfig.RootNode, 'GroupsNameBank', True);
+  AConfig.AddNode(ParentNode,AGroupName);
+
+  // 2) Save current active group data to brunch 'Groups/<AGroupName>'
+
+  SaveTabsXml(AConfig,'Groups/'+AGroupName,nbLeft);
+  SaveTabsXml(AConfig,'Groups/'+AGroupName,nbRight);
+
+end;
+
 procedure TfrmMain.ToggleConsole;
 begin
   if gTermWindow then
@@ -5045,8 +5172,8 @@ begin
   end
   else
   begin
-    LoadTabsXml(gConfig, nbLeft);
-    LoadTabsXml(gConfig, nbRight);
+    LoadTabsXml(gConfig,'Tabs/OpenedTabs/', nbLeft);
+    LoadTabsXml(gConfig,'Tabs/OpenedTabs/', nbRight);
   end;
 
   LoadTabsCommandLine(CommandLineParams);
@@ -5155,8 +5282,8 @@ var
   ANode: TXmlNode;
 begin
   (* Save all tabs *)
-  SaveTabsXml(gConfig, nbLeft);
-  SaveTabsXml(gConfig, nbRight);
+  LoadTabsXml(gConfig,'Tabs/OpenedTabs/', nbLeft);
+  LoadTabsXml(gConfig,'Tabs/OpenedTabs/', nbRight);
 
   (* Save window bounds and state *)
   ANode := gConfig.FindNode(gConfig.RootNode, 'MainWindow/Position', True);

+ 1 - 1
src/fviewer.lfm

@@ -1,5 +1,5 @@
 object frmViewer: TfrmViewer
-  Left = 292
+  Left = 275
   Height = 480
   Top = 46
   Width = 640

+ 6 - 1
src/ufileviewnotebook.pas

@@ -523,9 +523,14 @@ begin
 end;
 
 procedure TFileViewNotebook.DestroyAllPages;
+var
+   tPage:TFileViewPage;
 begin
   while PageCount > 0 do
-    Page[0].Free;
+  begin
+    tPage:=Page[0];
+    if tPage<>nil then FreeAndNil(tPage);
+  end;
 end;
 
 procedure TFileViewNotebook.ActivatePrevTab;

+ 5 - 1
src/uglobs.pas

@@ -79,7 +79,7 @@ type
   TExternalToolsOptions = array[TExternalTool] of TExternalToolOptions;
   TResultingFramePositionAfterCompare = (rfpacActiveOnLeft, rfpacLeftOnLeft);
 
-  TDCFont = (dcfMain, dcfViewer, dcfEditor, dcfLog, dcfViewerBook, dcfConsole, dcfFileSearchResults);
+  TDCFont = (dcfMain, dcfViewer, dcfEditor, dcfLog, dcfViewerBook, dcfConsole, dcfFileSearchResults, dcFileViewHeader);
   TDCFontOptions = record
     Name: String;
     Size: Integer;
@@ -151,6 +151,10 @@ const
   MAX_FONT_SIZE_FILE_SEARCH_RESULTS=70;
   MIN_FONT_SIZE_FILE_SEARCH_RESULTS=6;
 
+  MAX_FONT_SIZE_FILEVIEWHEADER=20;
+  MIN_FONT_SIZE_FILEVIEWHEADER=8;
+
+
 
 var
   { For localization }

+ 5 - 0
src/ulng.pas

@@ -509,6 +509,11 @@ resourcestring
   rsZeroReplacement = 'No replacement took place.';
   rsXReplacements = 'Number of replacement: %d';
 
+  // Groups
+  rsGroupNewGroup = 'Creating new group';
+  rsGroupNewGroupName = 'Group name:';
+
+
   // Options editors
   rsOptionsEditorArchivers = 'Archivers';
   rsOptionsEditorAutoRefresh = 'Auto refresh';

+ 85 - 6
src/umaincommands.pas

@@ -29,7 +29,7 @@ interface
 
 uses
   Classes, SysUtils, ActnList, uFileView, uFileViewNotebook, uFileSourceOperation,
-  uGlobs, uFileFunctions, uFormCommands, uFileSorting, uShellContextMenu;
+  uGlobs, uFileFunctions, uFormCommands, uFileSorting, uShellContextMenu, Menus;
 
 type
 
@@ -183,6 +183,15 @@ type
    procedure cm_PrevTab(const Params: array of string);
    procedure cm_SaveTabs(const Params: array of string);
    procedure cm_LoadTabs(const Params: array of string);
+
+   procedure cm_NewGroup(const Params: array of string);
+   procedure cm_RestoreActiveGroup(const Params: array of string);
+   procedure cm_SaveGroup(const Params: array of string);
+   procedure cm_LoadGroup(const Params: array of string);
+
+
+
+
    procedure cm_SetTabOptionNormal(const Params: array of string);
    procedure cm_SetTabOptionPathLocked(const Params: array of string);
    procedure cm_SetTabOptionPathResets(const Params: array of string);
@@ -1479,9 +1488,10 @@ begin
     Config:= TXmlConfig.Create(dmComData.SaveDialog.FileName);
     with frmMain do
     try
-      SaveTabsXml(Config, LeftTabs);
-      SaveTabsXml(Config, RightTabs);
-      Config.Save;
+      SaveTabsXml(Config, 'Tabs/OpenedTabs', LeftTabs);
+      SaveTabsXml(Config, 'Tabs/OpenedTabs', RightTabs);
+//      Config.Save;
+      Config.WriteToFile(dmComData.SaveDialog.FileName);
     finally
       Config.Free;
     end;
@@ -1503,11 +1513,45 @@ begin
     with frmMain do
     try
       LeftTabs.DestroyAllPages;
-      LoadTabsXml(Config, LeftTabs);
+      LoadTabsXml(Config,'Tabs/OpenedTabs/', LeftTabs);
       FrameLeft.Flags:= FrameLeft.Flags - [fvfDelayLoadingFiles];
       RightTabs.DestroyAllPages;
-      LoadTabsXml(Config, RightTabs);
+      LoadTabsXml(Config,'Tabs/OpenedTabs/', RightTabs);
       FrameRight.Flags:= FrameRight.Flags - [fvfDelayLoadingFiles];
+
+    finally
+      Config.Free;
+    end;
+  except
+    on E: Exception do
+      msgError(E.Message);
+  end;
+end;
+
+
+
+procedure TMainCommands.cm_NewGroup(const Params: array of string);
+var
+  miGroup,miNewGroup:TMenuItem;
+  Config: TXmlConfig;
+  sNewGroup:string;
+begin
+
+  if not InputQuery(rsGroupNewGroup, rsGroupNewGroupName, sNewGroup) then Exit;
+
+  try
+    Config:= TXmlConfig.Create('groups.xml',True);
+    with frmMain do
+    try
+      SaveGroupXml(Config,sNewGroup);
+      Config.WriteToFile('groups.xml');
+
+      miNewGroup:=TMenuItem.Create(frmMain.mnuMain);
+      miNewGroup.Caption:=sNewGroup;
+      miNewGroup.Name:='miGrpName_'+sNewGroup;
+      miNewGroup.OnClick:=@mnuGroupNameTabsClick;
+      mnuGroups.Add(miNewGroup);
+
     finally
       Config.Free;
     end;
@@ -1515,6 +1559,41 @@ begin
     on E: Exception do
       msgError(E.Message);
   end;
+
+end;
+
+procedure TMainCommands.cm_RestoreActiveGroup(const Params: array of string);
+var
+  AFileName:string;
+  Config: TXmlConfig;
+begin
+
+  AFileName:= 'groups.xml';
+  try
+    Config:= TXmlConfig.Create(AFileName, True);
+    with frmMain do
+    try
+      LoadGroupXml(Config,LastActiveGroup);
+      FrameLeft.Flags:= FrameLeft.Flags - [fvfDelayLoadingFiles];
+      FrameRight.Flags:= FrameRight.Flags - [fvfDelayLoadingFiles];
+    finally
+      Config.Free;
+    end;
+  except
+    on E: Exception do
+      msgError(E.Message);
+  end;
+end;
+
+
+procedure TMainCommands.cm_SaveGroup(const Params: array of string);
+begin
+
+end;
+
+procedure TMainCommands.cm_LoadGroup(const Params: array of string);
+begin
+
 end;
 
 procedure TMainCommands.cm_SetTabOptionNormal(const Params: array of string);