Lazarus

Miscellaneous => Suggestions => LCL => Topic started by: kormoran on April 04, 2015, 03:51:48 pm

Title: add a column to TshellListView?
Post by: kormoran on April 04, 2015, 03:51:48 pm
Hello, I need to calc a value for each file in a directory and show it.

TShellListView would be perfect, IF I could add another column to it... but I can't find a way. Can this be (easily) done or do I need to derive from TCustomShellListView and make my own?

Thanks  :)

(edit: OOPS wrong board... plz move to Lazarus->Programming->LCL)
Title: Re: add a column to TshellListView?
Post by: typo on April 04, 2015, 07:40:44 pm
Code: [Select]
  ShellListView1.Columns.Add;
  ShellListView1.Column[ShellListView1.ColumnCount - 1].Caption := 'abc';   

You need to derive from TShellListView or TCustomShellListView and make property Columns public. Or make a Feature Request in BugTracker in order to make it public on TCustomListView source (since Column and ColumnCount are public too).
Title: Re: add a column to TshellListView?
Post by: howardpc on April 04, 2015, 08:23:45 pm
Here's an example of one way to achieve this.

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, ShellCtrls, ComCtrls;

type

  { TShellListViewEx }

  TShellListViewEx = class(TShellListView)
  private
    FNewColumn: TListColumn;
    FNewColumnCaption: string;
    function FileStringFunction(const aFilePath: string): string; // supply your file processing logic here
    procedure PopulateWithRootEx;
  public
    constructor CreateEx(AOwner: TComponent; const anExtraColumn: string);
    property ExColumnCaption: string read FNewColumnCaption;
  end;

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    slvEx: TShellListViewEx;
  end;

var
  Form1: TForm1;

implementation

uses LazLogger;

{$R *.lfm}

{ TShellListViewEx }

function TShellListViewEx.FileStringFunction(const aFilePath: string): string;
begin
  if FileIsReadOnly(aFilePath) then
    Result:='ReadOnly'
  else Result:='Writeable';
end;

procedure TShellListViewEx.PopulateWithRootEx;
var
  Files: TStringList;
  i: integer;
  li: TListItem;
  curFilePath, filePath: string;
begin
  inherited PopulateWithRoot;
  if (csDesigning in ComponentState) then Exit;
  if Trim(Root) = '' then Exit;

  Files := TStringList.Create;
  try
    TCustomShellTreeView.GetFilesInDir(Root, Mask, ObjectTypes, Files);
    curFilePath:=IncludeTrailingPathDelimiter(Root);
    for i := 0 to Files.Count - 1 do
    begin
      li:=Items.FindCaption(0,Files[i],False,True,true);
      if (li <> nil) then begin
        filePath:=curFilePath + Files[i];
        li.SubItems.Add(FileStringFunction(filePath));
      end
      else DebugLn('Filename %s was not in items list',[Files[i]]);
    end;
  finally
    Files.Free;
  end;
end;

constructor TShellListViewEx.CreateEx(AOwner: TComponent;
  const anExtraColumn: string);
begin
  inherited Create(AOwner);
  FNewColumn:=Columns.Add;
  FNewColumn.Caption:=anExtraColumn;
  Root:='C:\';                      // customise these properties appropriately
  Mask:='*.*';
  ObjectTypes:=[otFolders, otNonFolders];
  PopulateWithRootEx;
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  slvEx:=TShellListViewEx.CreateEx(Self, 'Readonly attribute');
  slvEx.Align:=alClient;
  slvEx.Parent:=Self;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(slvEx);
end;

end.
Title: Re: add a column to TshellListView?
Post by: kormoran on April 04, 2015, 11:05:09 pm
Thank you guys, excellent answers.

(Sorry for posting in the wrong place)
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 12:02:01 am
Making a Feature Request should result, see TCustomListView source:

Code: [Select]
TShellListView = class(TCustomShellListView)
  published
    { TCustomListView properties
      The same as TListView excluding data properties }
    property Align;
    property Anchors;
    property BorderSpacing;
    property BorderStyle;
    property BorderWidth;
//    property Checkboxes;
    property Color default clWindow;
//    property Columns;

All they need to do is uncomment that line.
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 12:17:57 am
http://bugs.freepascal.org/view.php?id=27786
Title: Re: add a column to TshellListView?
Post by: Bart on April 05, 2015, 12:42:32 am
There is a reason why it is not published.
(See bugreport).

Bart
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 12:49:45 am
Surely there is a reasonable reason why he/she should not delete the first 3 columns.
Title: Re: add a column to TshellListView?
Post by: Bart on April 05, 2015, 12:52:32 am
Yes, and we like to not "help" people to shoot in their own foot (we're not C).

Bart
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 02:02:35 am
Blocking access to Colums property does not seem a very smart solution. Maybe a block to the first 3 would be better.
Title: Re: add a column to TshellListView?
Post by: Timewarp on April 05, 2015, 09:19:02 am
If all needed is to publish columns, just add this to project:
Code: [Select]
type
  TShellListView = class(ShellCtrls.TShellListView)
    published property Columns;
  end;
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 09:46:20 am
I agree.
Title: Re: add a column to TshellListView?
Post by: Bart on April 05, 2015, 10:58:54 am
Blocking access to Colums property does not seem a very smart solution. Maybe a block to the first 3 would be better.

Yes.
Not sure how to do that though.
Any ideas?

Bart
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 11:04:40 am
First idea:

Code: [Select]
    procedure AddColumn(ACaption :string);
    procedure DeleteColumn(AIndex :integer);

{...}

procedure TCustomShellListView.AddColumn(ACaption :string);
begin
  Columns.Add;
  Column[ColumnCount - 1].Caption := ACaption;
end;

procedure TCustomShellListView.DeleteColumn(AIndex :integer);
begin
  if AIndex > 2 then
    Columns.Delete(AIndex);
end;               
Title: Re: add a column to TshellListView?
Post by: Bart on April 05, 2015, 11:24:21 am
Still leaves the possibility to do
Code: [Select]
  ShellListView1.Columns.Delete(0);

(If Columns were to be published.)

While it is possible to replace TTreeNode with a subclass (which I have done), such a mechanisme is not provided for columns.

But just introducing AddColumn and DeleteColumn might be a feasible idea.

Bart
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 11:27:42 am
Still leaves the possibility to do
Code: [Select]
  ShellListView1.Columns.Delete(0);

(If Columns were to be published.)

In this case don't publish them. No need to do so if AddColumn and DeleteColumn are used.
Title: Re: add a column to TshellListView?
Post by: Bart on April 05, 2015, 11:31:08 am
Does anybody know if Delphi publishes TShellListView.Columns?
If not, do they have a method of adding/deleting columns?
If yes, can you delete all columns?

While our implementation is far from D compatible, if we implement such a thing, we might try to follow (black box aproach) the Greek.

Bart
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 01:55:19 pm
I only found this in C++:

http://godcom.googlecode.com/svn/trunk/ShellControls/ShellCtrls.hpp

And it publics Columns.

Code: [Select]
public:
__fastcall virtual TCustomShellListView(Classes::TComponent* AOwner);
__fastcall virtual ~TCustomShellListView(void);
void __fastcall Back(void);
HIDESBASE void __fastcall Refresh(void);
TShellFolder* __fastcall SelectedFolder(void);
__property TShellFolder* Folders[int Index] = {read=GetFolder};
__property TShellFolder* RootFolder = {read=FRootFolder};
__property Items;
__property Columns;

I also found this unit, apparently from Delphi, and it does not public Columns.

https://github.com/Baltimore99/delphi-drag-drop/blob/master/Demos/DetailedDemo/Extra/ShellCtrls.pas
Title: Re: add a column to TshellListView?
Post by: taazz on April 05, 2015, 04:06:50 pm
Oh wow, it seems that from delphi 2009 onwards the tshellxxx controls are not part of the default installation and are now published on their sourceforge project as samples on how to create controls that interact with windows shell. http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RadStudio_XE6/Object%20Pascal/VCL/ShellControls/ (http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RadStudio_XE6/Object%20Pascal/VCL/ShellControls/)


EDIT: sorry forgot that the columns seem to be public.
Title: Re: add a column to TshellListView?
Post by: typo on April 05, 2015, 04:23:27 pm
Code: [Select]
public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Back;
    procedure Refresh;
    function SelectedFolder: TShellFolder;
    property Folders[Index: Integer]: TShellFolder read GetFolder;
    property RootFolder: TShellFolder read FRootFolder;
    property Items;
    property Columns;

Yes, thanks.

So, yes, Delphi publics Columns.
Title: Re: add a column to TshellListView?
Post by: Bart on April 05, 2015, 06:45:08 pm
So, yes, Delphi publics Columns.

I made them public.

Bart