Solved

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

Posted on 2009-05-20
5
310 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
  • 3
  • 2
5 Comments
 
LVL 14

Accepted Solution

by:
SteveBay earned 500 total points
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Your post changed the whole way I looked at my project, and I thank you again.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

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…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now