unit _TemplateFileList; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, _TemplateFile, StdCtrls, ExtCtrls, Menus, Buttons, ComCtrls, TypeDefs, VirtualTrees; type TNewFileSelectingEvent = procedure(FileInfo: TFileInfo; var allowed: Boolean) of object; TForm_TemplateFileList = class(TForm_TemplateFile) panel_files: TPanel; splitter_content: TSplitter; panel_content: TPanel; filepopup: TPopupMenu; popup_separator2: TMenuItem; popup_linkshere: TMenuItem; popup_separator: TMenuItem; popup_import: TMenuItem; popup_export: TMenuItem; importd: TOpenDialog; exportd: TSaveDialog; FilePages: TPageControl; tab_files: TTabSheet; panel_extension: TPanel; label_sort2: TLabel; label_sort1: TLabel; label_extension: TLabel; btn_sort_id_asc: TSpeedButton; btn_sort_id_desc: TSpeedButton; btn_sort_name_asc: TSpeedButton; btn_sort_name_desc: TSpeedButton; btn_sort_ext_asc: TSpeedButton; btn_sort_ext_desc: TSpeedButton; combo_extension: TComboBox; check_zerobyte: TCheckBox; edit_filtername: TEdit; check_filtername: TCheckBox; filelist: TListBox; tab_meta: TTabSheet; filelist_meta: TVirtualStringTree; procedure NewCon(ID: Integer); procedure check_filternameClick(Sender: TObject); procedure check_zerobyteClick(Sender: TObject); procedure combo_extensionClick(Sender: TObject); procedure btn_sortClick(Sender: TObject); procedure listClick(Sender: TObject); procedure listMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure popup_importClick(Sender: TObject); procedure popup_exportClick(Sender: TObject); procedure popup_opentool(Sender: TObject); procedure popup_linkshereClick(Sender: TObject); procedure filepopupPopup(Sender: TObject); procedure filelist_metaGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); procedure filelist_metaInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal); procedure filelist_metaPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType); procedure filelist_metaFocusChanging(Sender: TBaseVirtualTree; OldNode, NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex; var Allowed: Boolean); procedure filelist_metaFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); private FSortBy: TSortType; FAllowedExts: String; FAllowMultiSelect: Boolean; FOnNewFileSelecting: TNewFileSelectingEvent; procedure SetAllowedExts(exts: String); procedure SetMultiSelect(allow: Boolean); public constructor Create(AOwner: TComponent); override; procedure RecreateExtList; procedure LoadFileNames; procedure SetFileFilters(pattern, extension: String; zerobytes: Boolean); property AllowedExts: String read FAllowedExts write SetAllowedExts; property AllowMultiSelect: Boolean read FAllowMultiSelect write SetMultiSelect; property OnNewFileSelecting: TNewFileSelectingEvent read FOnNewFileSelecting write FOnNewFileSelecting; end; implementation {$R *.dfm} uses ConnectionManager, Exporters, Functions, StrUtils, WhatLinksHere, Main, _BaseTemplate, _MetaTypes, Data, _MetaManager, _FileTypes; type PNodeData = ^TNodeData; TNodeData = record Field: TObject; end; function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode; ARecord: TNodeData): PVirtualNode; var Data: PNodeData; begin Result := AVST.AddChild(ANode); Data := AVST.GetNodeData(Result); AVST.ValidateNode(Result, False); Data^ := ARecord; end; procedure TForm_TemplateFileList.RecreateExtList; var i: Integer; exts: TStrings; begin combo_extension.Items.Clear; if FConnectionID > -1 then begin combo_extension.Items.Add('_All files_ (' + IntToStr(ConManager.Connection[FConnectionID].GetFileCount) + ')'); exts := nil; exts := ConManager.Connection[FConnectionID].GetExtensionsList(EF_ExtCount); for i := 0 to exts.Count - 1 do if Length(FAllowedExts) > 0 then begin if Pos(MidStr(exts.Strings[i],1,4), FAllowedExts) > 0 then combo_extension.Items.Add(exts.Strings[i]); end else combo_extension.Items.Add(exts.Strings[i]); combo_extension.ItemIndex := 0; combo_extensionClick(Self); exts.Free; end; end; procedure TForm_TemplateFileList.LoadFileNames; var Extension: String; no_zero_bytes: Boolean; pattern: String; files: TStrings; root: TExtensions; i: Integer; data: TNodeData; node: PVirtualNode; begin if FConnectionID > -1 then begin Extension := MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex], 1, 4); no_zero_bytes := not check_zerobyte.Checked; pattern := ''; if check_filtername.Checked then pattern := edit_filtername.Text; if Extension = '_All' then if Length(FAllowedExts) > 0 then Extension := FAllowedExts else Extension := ''; files := nil; files := ConManager.Connection[FConnectionID].GetFilesList(extension, pattern, no_zero_bytes, FSortBy); filelist.Visible := False; filelist.Items.Clear; if files.Count > 0 then filelist.Items.AddStrings(files); filelist.Visible := True; //VST filelist_meta.Clear; filelist_meta.BeginUpdate; { root := ConManager.Connection[FConnectionID].MetaData.Root; for i := 0 to High(root) do begin data.Field := root[i]; node := AddVSTEntry(filelist_meta, nil, data); filelist_meta.HasChildren[node] := True; end; filelist_meta.EndUpdate; } end; end; procedure TForm_TemplateFileList.NewCon(ID: Integer); begin RecreateExtList; end; procedure TForm_TemplateFileList.popup_exportClick(Sender: TObject); var id: Integer; ext: String; begin id := ConManager.Connection[FConnectionID].ExtractFileIDOfName(filelist.Items.Strings[filelist.ItemIndex]); ext := RightStr(filelist.Items.Strings[filelist.ItemIndex], 4); exportd.Filter := 'Files of matching extension (*.' + ext + ')|*.' + ext + '|All files|*.*'; exportd.DefaultExt := ext; if exportd.Execute then ExportDatFile(FConnectionID, id, exportd.FileName); end; procedure TForm_TemplateFileList.popup_importClick(Sender: TObject); var id: Integer; finfo: TFileInfo; fs: TFileStream; begin if CR_EditDat in ConManager.Connection[FConnectionID].ChangeRights then begin id := ConManager.Connection[FConnectionID].ExtractFileIDOfName(filelist.Items.Strings[filelist.ItemIndex]); finfo := ConManager.Connection[FConnectionID].GetFileInfo(id); importd.Filter := 'Files of matching extension (*.' + finfo.Extension + ')|*.' + finfo.Extension + '|All files|*.*'; if importd.Execute then begin fs := TFileStream.Create(importd.FileName, fmOpenRead); if fs.Size <> finfo.Size then begin if not (CR_ResizeDat in ConManager.Connection[FConnectionID].ChangeRights) then begin ShowMessage('Can''t import ' + ExtractFilename(importd.FileName) + ', file has to have same size as file in .dat with this backend.' + CrLf + 'Size of file in .dat: ' + FormatFileSize(finfo.Size) + CrLf + 'Size of chosen file: ' + FormatFileSize(fs.Size)); Exit; end else begin if MessageBox(Self.Handle, PChar('File has different size from the file in the .dat.' + CrLf + 'Size of file in .dat: ' + FormatFileSize(finfo.Size) + CrLf + 'Size of chosen file: ' + FormatFileSize(fs.Size) + CrLf + 'Replace anyway?'), PChar('Different size'), MB_YESNO + MB_ICONWARNING) = ID_NO then begin Exit; end; end; end; ConManager.Connection[FConnectionID].UpdateDatFile(id, fs); Self.listClick(Self); fs.Free; end; end else begin ShowMessage('Editing .dat-contents not allowed with this backend.'); end; end; procedure TForm_TemplateFileList.popup_linkshereClick(Sender: TObject); begin Form_WhatLinksHere.ConID := FConnectionID; Form_WhatLinksHere.FileID := FSelectedFile.ID; Form_WhatLinksHere.SenderForm := Self; Form_WhatLinksHere.Show; end; procedure TForm_TemplateFileList.popup_opentool(Sender: TObject); var sender_name, context: String; id: Integer; begin sender_name := TComponent(Sender).Name; id := ConManager.Connection[FConnectionID].ExtractFileIDOfName(filelist.Items.Strings[filelist.ItemIndex]); context := MidStr(sender_name, Pos('_', sender_name) + 1, Length(sender_name) - Pos('_', sender_name)); Form_Main.open_child(context, FConnectionID, id); end; procedure TForm_TemplateFileList.filepopupPopup(Sender: TObject); var ext: String; i: Integer; begin ext := RightStr(filelist.Items.Strings[filelist.ItemIndex], 4); for i := 0 to High(ToolList) do begin filepopup.Items.Items[i].Enabled := True; if Length(ToolList[i].exts) > 0 then if Pos(ext, ToolList[i].exts) = 0 then filepopup.Items.Items[i].Enabled := False; end; end; procedure TForm_TemplateFileList.check_zerobyteClick(Sender: TObject); begin LoadFileNames; end; procedure TForm_TemplateFileList.btn_sortClick(Sender: TObject); begin if btn_sort_id_asc.Down then FSortBy := ST_IDAsc else if btn_sort_id_desc.Down then FSortBy := ST_IDDesc else if btn_sort_name_asc.Down then FSortBy := ST_NameAsc else if btn_sort_name_desc.Down then FSortBy := ST_NameDesc else if btn_sort_ext_asc.Down then FSortBy := ST_ExtAsc else if btn_sort_ext_desc.Down then FSortBy := ST_ExtDesc; LoadFileNames; end; procedure TForm_TemplateFileList.check_filternameClick(Sender: TObject); begin edit_filtername.Enabled := not check_filtername.Checked; LoadFileNames; end; procedure TForm_TemplateFileList.combo_extensionClick(Sender: TObject); begin LoadFileNames; end; procedure TForm_TemplateFileList.listClick(Sender: TObject); var fileid: Integer; begin if filelist.ItemIndex > -1 then begin fileid := ConManager.Connection[FConnectionID].ExtractFileIDOfName( filelist.Items.Strings[filelist.ItemIndex]); FSelectedFile := ConManager.Connection[FConnectionID].GetFileInfo(fileid); if Assigned(FOnNewFileSelected) then FOnNewFileSelected(FSelectedFile); end; end; procedure TForm_TemplateFileList.listMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var pt: TPoint; begin pt.X := x; pt.Y := y; if Shift = [ssRight] then begin filelist.ItemIndex := filelist.ItemAtPos(pt, true); Self.listClick(Self); end; end; procedure TForm_TemplateFileList.SetAllowedExts(exts: String); begin FAllowedExts := exts; RecreateExtList; end; procedure TForm_TemplateFileList.SetFileFilters(pattern, extension: String; zerobytes: Boolean); var i: Integer; begin if Length(pattern) > 0 then Self.edit_filtername.Text := pattern; Self.check_filtername.Checked := Length(pattern) > 0; if Length(extension) > 0 then begin for i := 0 to Self.combo_extension.Items.Count - 1 do if Pos(extension, Self.combo_extension.Items.Strings[i]) > 0 then Break; if i < Self.combo_extension.Items.Count then Self.combo_extension.ItemIndex := i else Self.combo_extension.ItemIndex := -1; end; Self.check_zerobyte.Checked := zerobytes; Self.LoadFileNames; end; procedure TForm_TemplateFileList.SetMultiSelect(allow: Boolean); begin FAllowMultiSelect := allow; filelist.MultiSelect := allow; end; constructor TForm_TemplateFileList.Create(AOwner: TComponent); var i: Integer; item: TMenuItem; begin inherited; filelist_meta.NodeDataSize := SizeOf(TNodeData); filelist_meta.Font.Charset := AppSettings.CharSet; filelist_meta.Clear; FAllowedExts := ''; FAllowMultiSelect := False; FOnNewConnection := NewCon; UpdateConList; if Length(ToolList) > 0 then begin for i := 0 to High(ToolList) do begin item := TMenuItem.Create(filepopup); item.Name := 'popup_' + ToolList[i].context; item.Caption := 'Open with ' + ToolList[i].name; item.OnClick := Self.popup_opentool; filepopup.Items.Insert(i, item); end; end; end; procedure TForm_TemplateFileList.filelist_metaFocusChanged( Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); var data: PNodeData; begin inherited; data := Sender.GetNodeData(Node); if data.Field is TResource then begin if Assigned(FOnNewFileSelected) then begin FOnNewFileSelected(TResource(data.Field).FileInfo); end; end; end; procedure TForm_TemplateFileList.filelist_metaFocusChanging( Sender: TBaseVirtualTree; OldNode, NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex; var Allowed: Boolean); var data: PNodeData; begin inherited; data := Sender.GetNodeData(NewNode); if data.Field is TResource then begin if Assigned(FOnNewFileSelecting) then begin FOnNewFileSelecting(TResource(data.Field).FileInfo, Allowed); end; end; end; procedure TForm_TemplateFileList.filelist_metaGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var data: PNodeData; begin inherited; { data := Sender.GetNodeData(Node); if data.Field is TExtension then begin CellText := TExtension(data.Field).Ext; end; if data.Field is TFile then begin if TFile(data.Field).FileInfo.Name = '' then CellText := TFile(data.Field).FileInfo.Extension + ' (unnamed)' else CellText := TFile(data.Field).FileInfo.Extension + ': ' + TFile(data.Field).FileInfo.Name; end; }end; procedure TForm_TemplateFileList.filelist_metaInitChildren( Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal); var data: PNodeData; i: Integer; newdata: TNodeData; newnode: PVirtualNode; id: Integer; begin inherited; data := Sender.GetNodeData(Node); Self.Cursor := crHourGlass; Application.ProcessMessages; { if data.Field is TExtension then begin if TExtension(data.Field).FileCount = 0 then TExtension(data.Field).InitList; for i := 0 to TExtension(data.Field).FileCount - 1 do begin id := TExtension(data.Field).Files[i]; ConManager.Connection[FConnectionID].MetaData.InitFile(id); newdata.Field := ConManager.Connection[FConnectionID].MetaData.FileById[id]; newnode := AddVSTEntry(filelist_meta, Node, newdata); if ConManager.Connection[FConnectionID].MetaData.FileById[id].ChildCount > 0 then filelist_meta.HasChildren[newnode] := True; ChildCount := filelist_meta.ChildCount[node]; end; end; if data.Field is TFile then begin for i := 0 to TFile(data.Field).ChildCount - 1 do begin id := TFile(data.Field).LinkByIndex[i].DestID; ConManager.Connection[FConnectionID].MetaData.InitFile(id); newdata.Field := ConManager.Connection[FConnectionID].MetaData.FileById[id]; newnode := AddVSTEntry(filelist_meta, Node, newdata); if ConManager.Connection[FConnectionID].MetaData.FileById[id].ChildCount > 0 then filelist_meta.HasChildren[newnode] := True; end; ChildCount := filelist_meta.ChildCount[node]; end; } Self.Cursor := crDefault; end; procedure TForm_TemplateFileList.filelist_metaPaintText( Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType); var Data: PNodeData; begin Data := Sender.GetNodeData(Node); if Data.Field is TResource then begin if Length(TResource(Data.Field).FileInfo.Name) = 0 then TargetCanvas.Font.Color := $C06060; if TResource(Data.Field).FileInfo.Size = 0 then TargetCanvas.Font.Color := $2020A0; end; end; end.