Solved

For Meikl

Posted on 2001-07-09
15
363 Views
Last Modified: 2010-04-06
Hi, Meikl.

You helped me last week with my question titled "Records" by providing me with a sample program.

I am thinking of adapting the program sample you gave so that i can add the parent nodes in myself when required instead of having them fixed inside the program.

I am hoping that you can help me by showing me how i can adapt the program so as to allow for this.

can you help?
0
Comment
Question by:mi6agent
  • 8
  • 7
15 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6264157
well, i would help you, but i don't know yet, what exactly you mean?

do you mean variable parents?

if so, then just add a secondary file with a structure like
ID : Integer;
Name : String[50];

which is read in the inittree-method?

well, could post this evening a sample,
if you mean this

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6264179
Hi Meikl

What i am looking to do is to start with no parents in the treeview and be able to add/delete a parent node to the treeview when i want.  Then i will be able to add a record under the new parent.

I just can't work out a way to be able to do that and be able to save and reload it all back in when i restart the program.

Hope this explains it better for you

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6264226
well,

sounds like
it could be done,
as i mentioned above

sample follows in ~9 hours

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6264235
thanks Meikl - i shall wait till it suits you.  

speak to you later.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6266498
sorry, got not the time today
(during week is too much todo)

if you are not in hurry, then i post it hopefully tomorrow
otherwise open another q for all

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6267028
That's ok Meikl, i can wait.  I know you will help if you can so i shall wait for you.
0
 

Author Comment

by:mi6agent
ID: 6271000
thought i would increase the points for you since you are kind enough to help me on this one again.
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 27

Expert Comment

by:kretzschmar
ID: 6271797
you do not need to raise the points for me,
have begun yesterday, but not ready yet

this evening it comes :-)

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6271924
Thanks Meikl.  As for the points, your help is worth it.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6273793
well, here it comes

well, its already a one file based app,
i've the typ-field in the record to string,
also the combobox is now at the style-property so adjusted,
that u can type in or select an entry->style csDropDown

the inittree method is canceled,
a new method findparent is introduced,
this method looks up, if a given typ alredady exists in the tree,
and returns the node if found.

the insertnode is changed,
it calls now the findparent-method,
if findparent nothing found,
a root node is ceated with given typ
and the comboboxlist is expanded with the new typ-entry.

so it should be now very dynamic,
the root entrys now depends on that what
you type in the combobox

empty rootnodes will disappear after next appstart

unit r_file_tree3_u;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ExtCtrls;

Type TheRec = Record  //a record
                LastName  : String[100];
                FirstName : String[100];
                //more attributes could stand here
                Typ      : String[100];
                Deleted  : Boolean;
              end;


type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Panel1: TPanel;
    Edit1: TEdit;
    Edit2: TEdit;
    BInsert: TButton;
    BUpdate: TButton;
    BDelete: TButton;
    ComboBox1: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure BInsertClick(Sender: TObject);
    procedure BUpdateClick(Sender: TObject);
    procedure BDeleteClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure FormDestroy(Sender: TObject);
  private
    NodeList : TList;      //Never used
    f : file of TheRec;    // file of this record
    rec : TheRec;   {Buffer} // a memorybuffer for this record
    Currentrecord : LongInt; {FileCursor}  //Points to the current record in the file
    RecordCount : LongInt; {RecordCount} //Holds the amount of records in the file
    Procedure PopulateEdits;
    Procedure PopulateRecord;
    Procedure CleanUpFile_at_Back;  //looks at the last record, if this is deleted, and deletes it
    Procedure CleanUpFile;          //Deletes all records, which are marked for deletion
    Procedure LoadTree;             //adds the level two nodes from files
    Procedure GetRecord(ARecNo : LongInt);  //gets a record
    Procedure UpdateRecord;         //Upsate a Record
    Procedure MarkToDeleteRecord;   //Marks a record for delete
    Procedure InsertNode(AName : String; AType : String; ARecNo : LongInt; DoSelect : Boolean);  //Inserts a Node into the tree
    Procedure AdJustControls(Switch : Boolean);  //Dis-/Enables Buttons
    Procedure InsertRecord;         //Insert a Record
    Function Findparent(AType : String) : TTreeNode;  //Find the Parent by Typ
  public
    { Public-Deklarationen }
  end;



var
  Form1: TForm1;


implementation

{$R *.DFM}

//open the file
procedure TForm1.FormCreate(Sender: TObject);
var I : Integer;
begin
  assignfile(f,'MyFile3.Dat');  //we will work with this file
  if not(fileexists('MyFile3.Dat')) then  //if this file not exists
    rewrite(f)  //create this file
  else
    reset(f);   //open this file
  CurrentRecord := 0;      //
  RecordCount := fileSize(f);
  LoadTree;
end;

Procedure TForm1.InsertRecord;
begin
  PopulateRecord;
  rec.Deleted := False;
  seek(f,RecordCount);  //goto last record
  write(f,rec);
  inc(RecordCount);
  CurrentRecord := RecordCount;
  InsertNode(rec.LastName,rec.typ,CurrentRecord,True);
end;

procedure TForm1.BInsertClick(Sender: TObject);
begin
  InsertRecord;
end;

procedure TForm1.BUpdateClick(Sender: TObject);
begin
  UpdateRecord;
end;

procedure TForm1.UpdateRecord;
var
  ParentSwap : Boolean;
begin
  if CurrentRecord > 0 then
  begin
    //must we Move the ChildeNode
    ParentSwap := rec.typ <> combobox1.Text;
    PopulateRecord;
    seek(f,CurrentRecord-1);
    write(f,rec);
    If ParentSwap then
    begin
      TreeView1.Selected.Delete;
      InsertNode(rec.LastName,rec.typ,CurrentRecord,True);
    end
    else
      TreeView1.Selected.Text := rec.LastName; //Update NodeText
  end;
end;

Procedure TForm1.MarkToDeleteRecord;
Begin
  rec.deleted := true;
  seek(f,CurrentRecord-1);
  write(f,rec);
  treeview1.selected.Delete;
End;


procedure TForm1.BDeleteClick(Sender: TObject);
begin
  MarkToDeleteRecord;
end;


procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  closefile(f);
end;

Procedure TForm1.AdJustControls(Switch : Boolean);
var I : integer;
begin
  BUpdate.Enabled := Switch;
  BDelete.Enabled := Switch;
  If Not(Switch) then
  begin
    combobox1.ItemIndex := -1;
    edit1.text := '';
    edit2.text := '';
  end;
end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin

  If Node.Level > 0 then
  begin
    GetRecord(Integer(node.Data));
    PopulateEdits;
  End;
  AdjustControls(Node.Level > 0);
end;

Procedure TForm1.GetRecord(ARecNo : LongInt);
begin
  If (ARecNo > 0) and (ARecNo <= RecordCount) then
  begin
    try
      seek(f,ARecNo-1);
      read(f,rec);
      CurrentRecord := ARecNo;
    except
      raise;
    end;
  End
  else
    raise exception.create('GetRecord : Recno Out of Bounds');
end;

procedure TForm1.PopulateEdits;
begin
  edit1.text := rec.FirstName;
  edit2.text := rec.LastName;
  //maybe more attributes
  ComboBox1.Text := rec.typ;
end;

procedure TForm1.PopulateRecord;
Begin
  rec.FirstName := edit1.text;
  rec.LastName := edit2.text;
  if comboBox1.Text <> '' then
    rec.Typ := ComboBox1.Text
  else
    raise exception.create('Typ must be set!');
  //maybe more attributes
End;

Procedure TForm1.CleanUpFile_at_Back;
var
  endloop : Boolean;
begin
  if RecordCount > 0 then
  begin
    endloop := False;
    while (not endloop) and (RecordCount > 0) do
    begin
      getrecord(RecordCount);
      if rec.Deleted then
      begin
        seek(f,RecordCount-1);
        truncate(f);
        dec(RecordCount);
      end
      else endloop := true;
    end;
  end;
end;

Procedure TForm1.CleanUpFile;
var
  tmpCurrentRecord : Integer;
Begin
  If RecordCount > 0 then
  begin
    tmpCurrentRecord := 1;
    CleanUpFile_at_Back;  //be sure the last record isn't deleted
    while tmpCurrentRecord < RecordCount do
    begin
      GetRecord(tmpCurrentRecord);
      if rec.Deleted then
      begin
        GetRecord(RecordCount);  //swap records
        seek(f,tmpCurrentRecord-1);
        write(f,rec);
        seek(f,RecordCount-1);
        truncate(f);         //snip
        dec(RecordCount);
        CleanUpFile_at_Back; //be sure the new last record isn't deleted
      end;
      inc(tmpCurrentRecord);
    end;
  end;
  CloseFile(f);  //force physically write
  reset(f);
  CurrentRecord := 0;  //reinit
  If (filesize(f) = RecordCount) then
    RecordCount := FileSize(f)
  else
    raise exception.Create('CleanUp : Something goes wrong');
end;

Function TForm1.Findparent(AType : String) : TTreeNode;
begin
  Result := TreeView1.Items.GetFirstNode;
  While (Result <> NIL) and (Result.Text <> AType) do
    Result := Result.GetNextSibling;
end;


procedure TForm1.InsertNode(AName : String;
                            AType : String;
                            ARecNo : LongInt;
                            DoSelect : Boolean);
var
  ANode : TTreeNode;
  AIndex : Integer;
Begin
  //Search the parentnode
  ANode := FindParent(AType);
  If Anode = Nil then  //Not found
  begin
    Anode := TreeView1.Items.Add(NIL,AType); //Add RootEntry
    ComboBox1.Items.Add(AType);              //Expand Combo
  end;
  ANode := TreeView1.Items.AddChild(ANode,AName); //Create Node
  ANode.Data := Pointer(ARecNo);  //Store recordposition
  If DoSelect Then
  begin
    TreeView1.Selected := ANode;  //Select Node
    ANode.MakeVisible;
  end;
end;

procedure TForm1.LoadTree;
Begin
  CleanUpFile;   //Delete all marked physically
  CurrentRecord := 0;    //load From Beginning
  seek(f,CurrentRecord);
  While not eof(f) do
  begin
    Read(f,rec);
    inc(CurrentRecord);
    InsertNode(rec.LastName,rec.typ,CurrentRecord,False);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  NodeList.Free; //free the list of RootNodes
end;

end.

hope this helps
ask if something unclear

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6274903
Thanks Meikl, you did it again!  I wish i was as good as you at doing all of this.

One question though, what exactly is the purpose of "ParentSwap" i can't seem to figure out what it does.
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 250 total points
ID: 6275832
hi

well if you change the typ-field of a record, then the record-entry must change to another parentnode

for ex.
you have a record AName, which has the typ friend

friend
|-AName
|-AName2
workers
|-Aname3

you change the type to best friend and update the record,
the result will be then in the tree

friend
|-AName2
best friend
|-AName
workers
|-AName3

parentswap indicates, that the type has changed and introduce a node move to the other parent which matches the changed type via the insertnode-method

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6275887
thanks meikl, i think i understand it a bit better now.

as i said, you are a genius and thank you very much for your help in all of this.

0
 

Author Comment

by:mi6agent
ID: 6275894
again, i give and excellent grade for an excellent answer and an excellent guy that took the time to help.

thanks.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6276302
no no, i'm not a genius

well glad you like it
you a very generous with your points, thnaks :-)

good luck again

meikl ;-)
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

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…
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…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

759 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

18 Experts available now in Live!

Get 1:1 Help Now