Solved

Displaying all content in a treeview instead of a treeview listview display

Posted on 2009-05-20
5
321 Views
Last Modified: 2012-05-07
Hello all,
I am using the component WMISet to retrieve the Group Policy of a computer, the component came with a demo showing you how to do it... but it uses a listview in conjunction with a treeview to display the GRoup Policy. And I have been trying to get rid of the listview and keep all the displayed information in the treeview. Rights now the treeview displays the folder structure, and the listview displays the subfolder/file/item info. I want everything to be displayed in the treeview and get rid of the listview ll together.

Reason why, is I want to be able save all the information to an xml file or clientdataset. And I thought it would be easier to do that if I only had to deal with one component instead of two.

Anyways I have not been able to figure out the treeview to get to to display the file/item info in the treeview along with the folder structure. Most of the code is below:

tvCategories = the treeview
lvPolicies = listview

remove the listview completely, and just use the treeview
tia
Frank



procedure TFormMain.LoadGpoData;
var
  vWasCursor: TCursor;
begin
  vWasCursor := Screen.Cursor;
  Screen.Cursor := crHourGlass; 
  try
    LoadCategoryTree;
    LoadLinks;
    UpdateCaption;
    SetButtonStates;
  finally
    Screen.Cursor := vWasCursor;
  end;
end;
 
procedure TFormMain.LoadCategoryTree;
var
  vList: TStringList;
  vPolicy: TNTRegistryPolicy;
  i: integer;
begin
  tvCategories.Items.Clear;
  vList := TStringList.Create;
  try
    GroupPolicy.ListRegistryPolicies(vList);
    FUserPolicies.Clear;
    FMachinePolicies.Clear;
    for i := 0 to vList.Count - 1 do
    begin
      Application.ProcessMessages;
      vPolicy := TNTRegistryPolicy(vList.Objects[i]);
      if vPolicy.Section = secUser then
        FUserPolicies.AddObject(vPolicy.Category, vPolicy)
          else FMachinePolicies.AddObject(vPolicy.Category, vPolicy)
    end;
 
    FMachineRoot := tvCategories.Items.Add(nil, COMPUTER_CONFIG);
    FUserRoot := tvCategories.Items.Add(nil, USER_CONFIG);
    LoadTreeBranch(FMachineRoot, FMachinePolicies);
    LoadTreeBranch(FUserRoot, FUserPolicies);
  finally
    vList.Free;
  end;
end;
 
procedure TFormMain.LoadLinks;
var
  i: integer;
  vItem: TListItem;
  vLink: TNTGpoLink;
begin
  lvLinks.Items.Clear;
  pnlLinksMessage.Visible := GroupPolicy.GpoType <> GPOTypeDS;
  pnlLinks.Visible := not pnlLinksMessage.Visible;
  if GroupPolicy.GpoType = GPOTypeDS then
  for i := 0 to GroupPolicy.GpoLinks.Count - 1 do
  begin
    Application.ProcessMessages;
    vLink := GroupPolicy.GpoLinks[i];
    vItem := lvLinks.Items.Add;
    vItem.Caption := vLink.ContainerName;
    vItem.SubItems.Add(BooleanToStr((vLink.Options and GPOLINK_DISABLED) <> 0));
    vItem.SubItems.Add(BooleanToStr((vLink.Options and GPOLINK_NO_OVERRIDE) <> 0));
  end;
end;
 
procedure TFormMain.UpdateCaption;
begin
  Caption := GROUP_POLICY_EDITOR + ': ' + GroupPolicy.GpoDisplayName;
end;
 
procedure TFormMain.SetButtonStates;
begin
  btnRemoveLink.Enabled  := lvLinks.Selected <> nil;
  btnLinkOptions.Enabled := btnRemoveLink.Enabled;
  //tlbDeleteGroup.Enabled := GroupPolicy.GpoType = GPOTypeDS;
end;
 
procedure TFormMain.LoadTreeBranch(ARoot: TTreeNode; APolicies: TStrings);
var
  i: integer;
  vPolicy: TNTRegistryPolicy;
begin
  for i := 0 to APolicies.Count - 1 do
  begin
    vPolicy := TNTRegistryPolicy(APolicies.Objects[i]);
    FindOrCreateCategoryNode(ARoot, vPolicy.Category);
  end;
 
  for i := 0 to tvCategories.Items.Count - 1 do
  begin
    if tvCategories.Items[i].HasChildren then
    begin
      {$IFDEF Delhi6}
      tvCategories.Items[i].AlphaSort(false);
      {$ELSE}
      tvCategories.Items[i].AlphaSort();
      {$ENDIF}
    end;
  end;
 
  ARoot.Expand(false);
end;
 
function TFormMain.FindOrCreateCategoryNode(ARoot: TTreeNode; ACategoryPath: widestring): TTreeNode;
var
  vChildNode: TTreeNode;
  vTokenizer: TNTStringTokenizer;
  vPathElement: widestring;
begin
  vTokenizer := TNTStringTokenizer.Create(ACategoryPath, PATH_SEPARATOR);
  try
    while not vTokenizer.EndOfString do
    begin
      vPathElement := vTokenizer.NextToken;
      vChildNode := FindOrCreateChildByName(ARoot, vPathElement);
      ARoot := vChildNode;
    end;
    Result := ARoot; 
  finally
    vTokenizer.Free;
  end;
end;
 
function TFormMain.FindOrCreateChildByName(ANode: TTreeNode; AName: widestring): TTreeNode;
var
  i: integer;
begin
  Result := nil;
  for i := 0 to ANode.Count - 1 do
    if ANode[i].Text = AName then
    begin
      Result := ANode[i];
      Break;
    end;
 
  if Result = nil then
  begin
    Result := tvCategories.Items.AddChild(ANode, AName);
  end;
end;
 
procedure TFormMain.tvCategoriesChange(Sender: TObject; Node: TTreeNode);
begin
  if (tvCategories.Selected = FUserRoot) or
     (tvCategories.Selected = FMachineRoot)  then
  begin
    lvPolicies.Items.Clear;
    LoadSubCategoriesForCategory
  end else
  begin
    LoadPoliciesForCategory;
  end;
end;
 
procedure TFormMain.tvCategoriesGetImageIndex(Sender: TObject;
  Node: TTreeNode);
begin
  if Node.Expanded then Node.ImageIndex := IMAGE_INDEX_FOLDER_OPEN
    else Node.ImageIndex := IMAGE_INDEX_FOLDER_OPEN;
  Node.SelectedIndex := Node.ImageIndex;
end;
 
procedure TFormMain.LoadSubCategoriesForCategory;
var
  i: integer;
  vItem     : TListItem;
  vNode,xNode     : TTreeNode;
begin
    vNode := tvCategories.Selected;
    for i := 0 to vNode.Count - 1 do
    begin
      vItem := lvPolicies.Items.Add;
      vItem.Caption := vNode.Item[i].Text;
    end;
end;
 
procedure TFormMain.LoadPoliciesForCategory;
var
  vCategory : widestring;
  vSection  : TNTPolicySection;
  vList     : TStrings;
  vPolicy   : TNTRegistryPolicy;
  i: integer;
  vItem     : TListItem;
 
begin
  lvPolicies.Items.Clear;
  GetSelectedCategory(vCategory, vSection);
  if vCategory <> '' then
  begin
    // 1) load sub categories
    LoadSubCategoriesForCategory;
    // 2) Load policies
 
    vList := GetPoliciesForSection(vSection);
    for i := 0 to vList.Count - 1 do
    begin
      vPolicy := TNTRegistryPolicy(vList.Objects[i]);
      if vPolicy.Category = vCategory then
      begin
        vItem := lvPolicies.Items.Add;
 
        vItem.Caption := vPolicy.PolicyName;
        GroupPolicy.RegistryPolicy.PolicyName := vPolicy.PolicyName;
        vItem.SubItems.Add(PolicyStatusToString(GroupPolicy.RegistryPolicy.Status))
      end;
    end;
  end;
end;
 
function TFormMain.GetPoliciesForSection(ASection: TNTPolicySection): TStrings;
begin
  if ASection = secUser then Result := FUserPolicies
    else Result := FMachinePolicies;
end;
 
procedure TFormMain.GetSelectedCategory(out ACategory: widestring;
                                         out ASection: TNTPolicySection);
var
  vNode: TTreeNode;
begin
  ACategory := '';
  ASection  := secUser;
 
  if tvCategories.Selected <> nil then
  begin
    vNode := tvCategories.Selected;
    while vNode.Parent <> nil do
    begin
      if ACategory <> '' then ACategory := '\' + ACategory;
      ACategory := vNode.Text + ACategory;
      vNode := vNode.Parent;
    end;
    if vNode = FUserRoot then ASection := secUser
      else ASection := secMachine;
  end;
 
end;
 
procedure TFormMain.lvPoliciesChange(Sender: TObject; Item: TListItem;
  Change: TItemChange);
var
  vPolicy: TNTRegistryPolicy;
begin
  memHelp.Lines.Clear;
  vPolicy := FindPolicy(lvPolicies.Selected);
  if vPolicy <> nil then
  begin
    memHelp.Lines.Text := FormatHelpString(vPolicy.HelpString);
  end;
end;
procedure TFormMain.lvPoliciesDblClick(Sender: TObject);
begin
  if IsPolicy(lvPolicies.Selected) then EditSelectedPolicy else
  if IsCategory(lvPolicies.Selected) then NavigateToSelectedCategory;
end;
procedure TFormMain.lvPoliciesGetImageIndex(Sender: TObject;
  Item: TListItem);
var
  vIndex: integer;
begin
  if Item.SubItems.Count = 0 then
    vIndex := IMAGE_INDEX_FOLDER_CLOSED
    else vIndex := IMAGE_INDEX_POLICY;
 
  if Item.ImageIndex <> vIndex then
    Item.ImageIndex := vIndex
end;
 
function TFormMain.FindPolicy(AItem: TListItem): TNTRegistryPolicy;
var
  vCategory : widestring;
  vSection  : TNTPolicySection;
  vList     : TStrings;
begin
  Result := nil;
  if AItem <> nil then
  begin
    GetSelectedCategory(vCategory, vSection);
    vList  := GetPoliciesForSection(vSection);
    Result := FindRegistryPolicyByName(vList, AItem.Caption);
  end;  
end;
 
function TFormMain.FindRegistryPolicyByName(AList: TStrings; AName: widestring): TNTRegistryPolicy;
var
  i: integer;
  vPolicy: TNTRegistryPolicy;
begin
  Result := nil;
  for i := 0 to AList.Count - 1 do
  begin
    vPolicy := TNTRegistryPolicy(AList.Objects[i]);
    if vPolicy.PolicyName = AName then
    begin
      Result := vPolicy;
      Exit;
    end;
  end;
end;
 
function TFormMain.FormatHelpString(AString: string): string;
var
  vPos: integer;
begin
  vPos := Pos('\n', AString);
  while vPos > 0 do
  begin
    AString[vPos] := #$0D;
    AString[vPos + 1] := #$0A;
    vPos := Pos('\n', AString);
  end;
  Result := AString;
end;
 
function TFormMain.IsPolicy(AItem: TListItem): boolean;
begin
  Result := (AItem <> nil) and (AItem.SubItems.Count > 0);
end;
 
function TFormMain.IsCategory(AItem: TListItem): boolean;
begin
  Result := (AItem <> nil) and (AItem.SubItems.Count = 0);
end;
 
procedure TFormMain.EditSelectedPolicy;
{var
  vDlg: TFrmEditPolicyDialog;
  vCategory: widestring;
  vSection: TNTPolicySection;}
begin
  {GetSelectedCategory(vCategory, vSection);
  GroupPolicy.RegistryPolicy.Section := vSection;
  GroupPolicy.RegistryPolicy.PolicyName := lvPolicies.Selected.Caption;
  vDlg := TFrmEditPolicyDialog.Create(GroupPolicy);
  try
    if vDlg.ShowModal = mrOk then RefreshPolicies;
  finally
    vDlg.Free;
  end; }
end;
 
{procedure TFormMain.RefreshPolicies;
var
  i: integer;
begin
  GroupPolicy.RegistryPolicy.Refresh;
  for i := 0 to lvPolicies.Items.Count - 1 do
  begin
    if isPolicy(lvPolicies.Items[i]) then
    begin
      GroupPolicy.RegistryPolicy.PolicyName := lvPolicies.Items[i].Caption;
      lvPolicies.Items[i].SubItems[0] := PolicyStatusToString(GroupPolicy.RegistryPolicy.Status);
    end;
  end;
end;  }
 
procedure TFormMain.NavigateToSelectedCategory;
var
  i: integer;
begin
  if (tvCategories.Selected <> nil) and (lvPolicies.Selected <> nil) then
    for i := 0 to tvCategories.Selected.Count - 1 do
      if tvCategories.Selected.Item[i].Text = lvPolicies.Selected.Caption then
      begin
        tvCategories.Selected := tvCategories.Selected.Item[i];
        Exit;
      end;
end;

Open in new window

tv-lv.jpg
0
Comment
Question by:LMuadDIb
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 14

Accepted Solution

by:
SteveBay earned 500 total points
ID: 24436088
It seem like it should be as simple as just creating tree nodes instead of ListView items for the policies. Though it's a little tricky because you will still have to make a distinction between tree node that represent SubCategories and and tree nodes that represent Policies.  
When you consider that, you may find that it is less complicated to change your save/load strategy than it is to change your display strategy.
Why do you think that it will simplify storage to have it all presented in one component? The way I see it, your data structure remains the same no matter how you display it.

0
 
LVL 4

Author Comment

by:LMuadDIb
ID: 24436459
hmmmmm
you got me thinking,  theres plenty of code for exporting a treeview out as as xml, and parsing xml seems alot easier (for me anyways) to do then actually trying to parse the treeview and listview at the same time.

maybe I should be looking at it in a different way like you said.
maybe create an xml doc or cds at the same time the data is being inserted into the treeview/listview, and load the data into the xml doc/cds and NOT after the fact. But at the same time.

0
 
LVL 4

Author Comment

by:LMuadDIb
ID: 24454296
SteveBay
Thank you for you answer, it led me to a better approach than what I was thinking previously.
Sense you didnt  answer my question but did help me,  can I give some points (partial-100) and have this this question closed?
0
 
LVL 14

Expert Comment

by:SteveBay
ID: 24454501
You are free to do as you believe is best.
People come to EE for solutions and you have found one. I could have answered your question but would that actually have been the best solution? That's for you to decide. I don't particiapate here because of point's I do it because It helps me expand my skills so it certainly won't ruin my day if you decide to discount this question/solution.

0
 
LVL 4

Author Comment

by:LMuadDIb
ID: 24456153
Your post changed the whole way I looked at my project, and I thank you again.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Multiple image collision 13 111
Delphi problems to abort a printjob 9 51
shape, triangle, dbctrlgrid 3 47
Connect to SQL 2008 r2 server over the Internet 4 85
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question