line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Tk::DBIx::Tree;
|
2
|
|
|
|
|
|
|
#------------------------------------------------
|
3
|
|
|
|
|
|
|
# automagically updated versioning variables -- CVS modifies these!
|
4
|
|
|
|
|
|
|
#------------------------------------------------
|
5
|
|
|
|
|
|
|
our $Revision = '$Revision: 1.2 $';
|
6
|
|
|
|
|
|
|
our $CheckinDate = '$Date: 2003/11/06 17:55:56 $';
|
7
|
|
|
|
|
|
|
our $CheckinUser = '$Author: xpix $';
|
8
|
|
|
|
|
|
|
our $Version = 1.5;
|
9
|
|
|
|
|
|
|
# we need to clean these up right here
|
10
|
|
|
|
|
|
|
$Revision =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
|
11
|
|
|
|
|
|
|
$CheckinDate =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
|
12
|
|
|
|
|
|
|
$CheckinUser =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
|
13
|
|
|
|
|
|
|
#-------------------------------------------------
|
14
|
|
|
|
|
|
|
#-- package Tk::DBIx::Tree -----------------------
|
15
|
|
|
|
|
|
|
#-------------------------------------------------
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
18
|
1
|
|
|
1
|
|
4450
|
use DBIx::Tree;
|
|
1
|
|
|
|
|
45578
|
|
|
1
|
|
|
|
|
55
|
|
19
|
1
|
|
|
1
|
|
1694
|
use Tk::Tree;
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
use Tk::Compound;
|
21
|
|
|
|
|
|
|
use Tk::ItemStyle; |
22
|
|
|
|
|
|
|
use Tk::ResizeButton;
|
23
|
|
|
|
|
|
|
use Term::ANSIColor;
|
24
|
|
|
|
|
|
|
use base qw/Tk::Derived Tk::Frame/;
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
use strict;
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Construct Tk::Widget 'DBITree';
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# ------------------------------------------
|
31
|
|
|
|
|
|
|
sub ClassInit
|
32
|
|
|
|
|
|
|
# ------------------------------------------
|
33
|
|
|
|
|
|
|
{
|
34
|
|
|
|
|
|
|
my($class,$mw) = @_;
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
}
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# ------------------------------------------
|
39
|
|
|
|
|
|
|
sub Populate {
|
40
|
|
|
|
|
|
|
# ------------------------------------------
|
41
|
|
|
|
|
|
|
my ($obj, $args) = @_;
|
42
|
|
|
|
|
|
|
my $style;
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
$obj->{dbh} = delete $args->{'-dbh'} || return error("No DB-Handle!"); |
45
|
|
|
|
|
|
|
$obj->{table} = delete $args->{'-table'} || return error("No Table!"); |
46
|
|
|
|
|
|
|
$obj->{debug} = delete $args->{'-debug'} || 0; |
47
|
|
|
|
|
|
|
$obj->{idx} = delete $args->{'-idx'} || return error("No IndexColumn!"); |
48
|
|
|
|
|
|
|
$obj->{fields} = delete $args->{'-fields'} || return error("No Fields!"); |
49
|
|
|
|
|
|
|
$obj->{textcolumn} = delete $args->{'-textcolumn'} || return error("No Textcolumn!"); |
50
|
|
|
|
|
|
|
$obj->{joiner} = delete $args->{'-joiner'}; |
51
|
|
|
|
|
|
|
$obj->{start_id} = delete $args->{'-start_id'} || 1; |
52
|
|
|
|
|
|
|
$obj->{command} = delete $args->{'-command'}; |
53
|
|
|
|
|
|
|
$obj->{parent_id} = delete $args->{'-parent_id'} || return error("No Parent_id!"); |
54
|
|
|
|
|
|
|
$obj->{columnWidths} = delete $args->{'-columnWidths'}; |
55
|
|
|
|
|
|
|
$obj->{maxchars} = delete $args->{'-maxchars'}; |
56
|
|
|
|
|
|
|
$obj->{colNames} = delete $args->{'-colNames'}; |
57
|
|
|
|
|
|
|
$obj->{entry_create_cb} = delete $args->{'-entry_create_cb'}; |
58
|
|
|
|
|
|
|
$obj->{time_column} = delete $args->{'-time_column'}; |
59
|
|
|
|
|
|
|
$obj->{opencmd} = delete $args->{'-opencmd'}; |
60
|
|
|
|
|
|
|
$obj->{closecmd} = delete $args->{'-closecmd'}; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
my $h_style = delete $args->{'-highlight'} || [-foreground => 'blue']; |
63
|
|
|
|
|
|
|
my $n_style = delete $args->{'-normal'} || [-foreground => 'black']; |
64
|
|
|
|
|
|
|
$obj->{highlight} = $obj->ItemStyle('imagetext', @{$h_style});
|
65
|
|
|
|
|
|
|
$obj->{normal} = $obj->ItemStyle('imagetext', @{$n_style});
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
$obj->SUPER::Populate($args);
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
my %specs;
|
71
|
|
|
|
|
|
|
$specs{refresh} = [qw/METHOD refresh Refresh/, undef];
|
72
|
|
|
|
|
|
|
$specs{close_all} = [qw/METHOD close_all Close_all/, undef];
|
73
|
|
|
|
|
|
|
$specs{listEntrys} = [qw/METHOD listEntrys ListEntrys/, undef];
|
74
|
|
|
|
|
|
|
$specs{remember} = [qw/METHOD remember Remember/, undef];
|
75
|
|
|
|
|
|
|
$specs{select_entrys} = [qw/METHOD select_entrys Select_entrys/, undef];
|
76
|
|
|
|
|
|
|
$specs{info} = [qw/METHOD info Info/, undef];
|
77
|
|
|
|
|
|
|
$specs{infozoom} = [qw/METHOD infozoom InfoZoom/, undef];
|
78
|
|
|
|
|
|
|
$specs{color_all} = [qw/METHOD color_all Color_All/, undef];
|
79
|
|
|
|
|
|
|
$specs{color_clear} = [qw/METHOD color_clear Color_Clear/, undef];
|
80
|
|
|
|
|
|
|
$specs{get_id} = [qw/METHOD get_id Get_Id/, undef];
|
81
|
|
|
|
|
|
|
$specs{parent_id} = [qw/METHOD parent_id Parent_Id/, undef];
|
82
|
|
|
|
|
|
|
$specs{see} = [qw/METHOD see See/, undef];
|
83
|
|
|
|
|
|
|
$specs{childs} = [qw/METHOD childs Childs/, undef];
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$specs{neu} = [qw/METHOD neu Neu/, undef];
|
86
|
|
|
|
|
|
|
$specs{move} = [qw/METHOD move Move/, undef];
|
87
|
|
|
|
|
|
|
$specs{copy} = [qw/METHOD copy Copy/, undef];
|
88
|
|
|
|
|
|
|
$specs{dele} = [qw/METHOD dele Dele/, undef];
|
89
|
|
|
|
|
|
|
$specs{refresh_id} = [qw/METHOD refresh_id Refresh_Id/, undef];
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
$obj->ConfigSpecs(%specs);
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
$obj->{last_refresh_time} = 1;
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
$obj->{tree} = $obj->Scrolled('Tree',
|
96
|
|
|
|
|
|
|
-scrollbars => 'osoe',
|
97
|
|
|
|
|
|
|
-columns => scalar @{$obj->{fields}} + 1,
|
98
|
|
|
|
|
|
|
-header => 1,
|
99
|
|
|
|
|
|
|
-separator => ':',
|
100
|
|
|
|
|
|
|
)->pack(-expand => 1,
|
101
|
|
|
|
|
|
|
-fill => 'both');
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
$obj->{tree}->configure(-opencmd => sub{
|
104
|
|
|
|
|
|
|
$obj->{OPEN}->{$_[0]} = 'offen';
|
105
|
|
|
|
|
|
|
my $ok = 1;
|
106
|
|
|
|
|
|
|
$ok = &{$obj->{opencmd}}(@_)
|
107
|
|
|
|
|
|
|
if(defined $obj->{opencmd} and ref $obj->{opencmd} eq 'CODE');
|
108
|
|
|
|
|
|
|
if($ok) {
|
109
|
|
|
|
|
|
|
$obj->refresh( undef, $_[0] );
|
110
|
|
|
|
|
|
|
}
|
111
|
|
|
|
|
|
|
$obj->{tree}->OpenCmd(@_)
|
112
|
|
|
|
|
|
|
});
|
113
|
|
|
|
|
|
|
$obj->{tree}->configure(-closecmd => sub{
|
114
|
|
|
|
|
|
|
my $path = $_[0];
|
115
|
|
|
|
|
|
|
my $ok = 1;
|
116
|
|
|
|
|
|
|
foreach my $item (keys %{$obj->{OPEN}}) {
|
117
|
|
|
|
|
|
|
delete $obj->{OPEN}->{$item}
|
118
|
|
|
|
|
|
|
if($item =~ /^$path/);
|
119
|
|
|
|
|
|
|
}
|
120
|
|
|
|
|
|
|
$ok = &{$obj->{closecmd}}(@_)
|
121
|
|
|
|
|
|
|
if(defined $obj->{closecmd} and ref $obj->{closecmd} eq 'CODE');
|
122
|
|
|
|
|
|
|
if($ok) {
|
123
|
|
|
|
|
|
|
$obj->{tree}->CloseCmd(@_)
|
124
|
|
|
|
|
|
|
}
|
125
|
|
|
|
|
|
|
});
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
$obj->Advertise("tree" => $obj->{tree});
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
} # end Populate
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# Class private methods;
|
133
|
|
|
|
|
|
|
# ------------------------------------------
|
134
|
|
|
|
|
|
|
sub refresh_id {
|
135
|
|
|
|
|
|
|
# ------------------------------------------
|
136
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
137
|
|
|
|
|
|
|
my $path = shift || return error('No Id');
|
138
|
|
|
|
|
|
|
my $data = shift || $obj->info('data', $path);
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
$path = $obj->id2path($path);
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
return unless($obj->info('exists',$path));
|
143
|
|
|
|
|
|
|
my ($id, $pid) = $obj->id($path);
|
144
|
|
|
|
|
|
|
$obj->dele($path);
|
145
|
|
|
|
|
|
|
$obj->neu($id, $pid, $data);
|
146
|
|
|
|
|
|
|
}
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# ------------------------------------------
|
149
|
|
|
|
|
|
|
sub neu {
|
150
|
|
|
|
|
|
|
# ------------------------------------------
|
151
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
152
|
|
|
|
|
|
|
my $id = shift || return error('No Id');
|
153
|
|
|
|
|
|
|
my $to_parent = shift || return error('No To Id');
|
154
|
|
|
|
|
|
|
my $data = shift || return error('No Data');
|
155
|
|
|
|
|
|
|
my $ignore_status = shift || 0;
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
$obj->debug('Neu - Id: %s, To_Parent: %s, Data %s', $id, $to_parent, $data);
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
$data->{$obj->{idx}} = $id
|
160
|
|
|
|
|
|
|
unless $data->{$obj->{idx}};
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my ($iid, $pid) = $obj->id($id);
|
163
|
|
|
|
|
|
|
my $new_path = sprintf('%s:%d', $to_parent, $iid );
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
$obj->{tree}->setmode($to_parent, 'open')
|
166
|
|
|
|
|
|
|
if($obj->{tree}->getmode($to_parent) eq 'none');
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
$obj->debug('Ignore Status? <%s> Parent Exists? <%s> Getmode(Parent) <%s>',
|
169
|
|
|
|
|
|
|
($ignore_status ? 'yes' : 'no'),
|
170
|
|
|
|
|
|
|
$obj->info('exists', $to_parent),
|
171
|
|
|
|
|
|
|
$obj->{tree}->getmode($to_parent));
|
172
|
|
|
|
|
|
|
return if(! $ignore_status and (! $obj->info('exists', $to_parent) or $obj->{tree}->getmode($to_parent) eq 'open'));
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
$obj->{tree}->add($new_path,
|
175
|
|
|
|
|
|
|
-itemtype => 'imagetext',
|
176
|
|
|
|
|
|
|
-data => $data,
|
177
|
|
|
|
|
|
|
-text => $obj->parse_text($data->{$obj->{textcolumn}}, $obj->{textcolumn}),
|
178
|
|
|
|
|
|
|
-style => $obj->{normal},
|
179
|
|
|
|
|
|
|
);
|
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
$obj->{tree}->setmode($new_path, 'open')
|
182
|
|
|
|
|
|
|
if(defined $obj->{ptree}->{$iid});
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
&{$obj->{entry_create_cb}}($obj->{tree}, $new_path, $data)
|
186
|
|
|
|
|
|
|
if(defined $obj->{entry_create_cb} and ref $obj->{entry_create_cb} eq 'CODE');
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
my $c = 1;
|
189
|
|
|
|
|
|
|
foreach my $field (@{$obj->{fields}}) {
|
190
|
|
|
|
|
|
|
$obj->{tree}->itemCreate( $new_path, $c++,
|
191
|
|
|
|
|
|
|
-text => $obj->parse_text($data->{$field}, $field),
|
192
|
|
|
|
|
|
|
-style => $obj->{normal},
|
193
|
|
|
|
|
|
|
);
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
push(@{$obj->{ListOfAllEntries}}, $new_path);
|
196
|
|
|
|
|
|
|
$obj->{Paths}->{$id} = $new_path;
|
197
|
|
|
|
|
|
|
return $new_path;
|
198
|
|
|
|
|
|
|
}
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# ------------------------------------------
|
201
|
|
|
|
|
|
|
sub move {
|
202
|
|
|
|
|
|
|
# ------------------------------------------
|
203
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
204
|
|
|
|
|
|
|
my $from_entry = $obj->id2path(shift) || return error('No From Id');
|
205
|
|
|
|
|
|
|
my $to_parent = shift || return error('No To Id');
|
206
|
|
|
|
|
|
|
my $data = shift;
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
my $to_path = $obj->{Paths}->{int $to_parent} || $obj->{Paths}->{$to_parent} || $obj->id2path($to_parent);
|
209
|
|
|
|
|
|
|
my ($id, $pid) = $obj->id($from_entry);
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
my $did = $obj->dele($from_entry)
|
213
|
|
|
|
|
|
|
if($obj->info('exists',$from_entry));
|
214
|
|
|
|
|
|
|
my $nid = $obj->neu($id, $to_path, $data)
|
215
|
|
|
|
|
|
|
if($obj->info('exists',$to_path));
|
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
$obj->{ListOfAllEntries} = $obj->rm_from_array($obj->{ListOfAllEntries}, $from_entry);
|
218
|
|
|
|
|
|
|
push(@{$obj->{ListOfAllEntries}}, $nid)
|
219
|
|
|
|
|
|
|
if($nid);
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
return $nid;
|
222
|
|
|
|
|
|
|
}
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
# ------------------------------------------
|
225
|
|
|
|
|
|
|
sub copy {
|
226
|
|
|
|
|
|
|
# ------------------------------------------
|
227
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
228
|
|
|
|
|
|
|
my $from_entry = shift || return error('No From Id');
|
229
|
|
|
|
|
|
|
my $to_parent = shift || return error('No To Id');
|
230
|
|
|
|
|
|
|
my $data = shift;
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
my ($id, $pid) = $obj->id($from_entry);
|
233
|
|
|
|
|
|
|
my $to_entry = sprintf('%s:%d', $obj->{Paths}->{$to_parent}, $id);
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
my $hl = $obj->{tree};
|
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
return unless($obj->{tree}->infoExists($from_entry));
|
238
|
|
|
|
|
|
|
return unless($obj->{tree}->infoExists($to_entry));
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
my @entry_args;
|
241
|
|
|
|
|
|
|
foreach ($hl->entryconfigure($from_entry)) {
|
242
|
|
|
|
|
|
|
push @entry_args, $_->[0] => $_->[4] if defined $_->[4];
|
243
|
|
|
|
|
|
|
}
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
$hl->add($to_entry, @entry_args);
|
246
|
|
|
|
|
|
|
$hl->entryconfigure($to_entry, -data => $data)
|
247
|
|
|
|
|
|
|
if defined $data;
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
foreach my $col (1 .. $hl->cget(-columns)-1) {
|
250
|
|
|
|
|
|
|
my @item_args;
|
251
|
|
|
|
|
|
|
foreach ($hl->itemConfigure($from_entry, $col)) {
|
252
|
|
|
|
|
|
|
push @item_args, $_->[0] => $_->[4] if defined $_->[4];
|
253
|
|
|
|
|
|
|
}
|
254
|
|
|
|
|
|
|
$hl->itemCreate($to_entry, $col, @item_args);
|
255
|
|
|
|
|
|
|
}
|
256
|
|
|
|
|
|
|
$obj->refresh_id($to_entry, $data);
|
257
|
|
|
|
|
|
|
push(@{$obj->{ListOfAllEntries}}, $to_entry);
|
258
|
|
|
|
|
|
|
$obj->{Paths}->{$id} = $to_entry;
|
259
|
|
|
|
|
|
|
return $to_entry;
|
260
|
|
|
|
|
|
|
}
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# ------------------------------------------
|
263
|
|
|
|
|
|
|
sub dele {
|
264
|
|
|
|
|
|
|
# ------------------------------------------
|
265
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
266
|
|
|
|
|
|
|
my $id = shift || return error('No Id');
|
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
my $parent = $obj->info('parent', $id) || return;
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
$obj->{tree}->deleteEntry($id);
|
271
|
|
|
|
|
|
|
$obj->{ListOfAllEntries} = $obj->rm_from_array($obj->{ListOfAllEntries}, $id);
|
272
|
|
|
|
|
|
|
$obj->{tree}->setmode($parent, 'none')
|
273
|
|
|
|
|
|
|
if( ! $obj->info('children', $parent) );
|
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
my ($iid, $pid) = $obj->id($id);
|
276
|
|
|
|
|
|
|
delete $obj->{Paths}->{ $iid };
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
return $id;
|
279
|
|
|
|
|
|
|
}
|
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# ------------------------------------------
|
282
|
|
|
|
|
|
|
sub refresh {
|
283
|
|
|
|
|
|
|
# ------------------------------------------
|
284
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
285
|
|
|
|
|
|
|
my $redraw = shift || $obj->Table_is_Change($obj->{last_refresh_time}, $obj->{table});
|
286
|
|
|
|
|
|
|
my $item = shift;
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
$obj->Busy;
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
$obj->debug('Refresh: redraw = %s, item = %s',
|
291
|
|
|
|
|
|
|
(defined $redraw ? $redraw : 'NONE'),
|
292
|
|
|
|
|
|
|
(defined $item ? $item : 'NONE')
|
293
|
|
|
|
|
|
|
);
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
return if(! defined $redraw && ! defined $item);
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
if(defined $redraw and $redraw) {
|
298
|
|
|
|
|
|
|
$obj->debug('Redraw! %s', $item);
|
299
|
|
|
|
|
|
|
@{$obj->{ListOfAllEntries}} = ();
|
300
|
|
|
|
|
|
|
$obj->{Paths} = {};
|
301
|
|
|
|
|
|
|
$obj->{tree}->delete('all');
|
302
|
|
|
|
|
|
|
}
|
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
unless(defined $obj->{tree_buttons}) {
|
305
|
|
|
|
|
|
|
my $c = -1;
|
306
|
|
|
|
|
|
|
foreach my $name ($obj->{textcolumn}, @{$obj->{fields}}) {
|
307
|
|
|
|
|
|
|
$c++;
|
308
|
|
|
|
|
|
|
$obj->{tree_buttons}->{$name} = $obj->{tree}->ResizeButton(
|
309
|
|
|
|
|
|
|
-text => $obj->{colNames}->[$c] || $name,
|
310
|
|
|
|
|
|
|
-relief => 'flat',
|
311
|
|
|
|
|
|
|
-border => -2,
|
312
|
|
|
|
|
|
|
-pady => -10,
|
313
|
|
|
|
|
|
|
-padx => 10,
|
314
|
|
|
|
|
|
|
-widget => \$obj->{tree},
|
315
|
|
|
|
|
|
|
-column => $c,
|
316
|
|
|
|
|
|
|
);
|
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
$obj->Advertise(sprintf("HB_%s",$name) => $obj->{tree_buttons}->{$name});
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
$obj->{tree}->headerCreate($c,
|
321
|
|
|
|
|
|
|
-itemtype => 'window',
|
322
|
|
|
|
|
|
|
-widget => $obj->{tree_buttons}->{$name},
|
323
|
|
|
|
|
|
|
);
|
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
$obj->{tree}->columnWidth($c, $obj->{columnWidths}->[$c])
|
326
|
|
|
|
|
|
|
if(defined $obj->{columnWidths}->[$c]);
|
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
}
|
329
|
|
|
|
|
|
|
}
|
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
$obj->{dbtree} = DBIx::Tree->new(
|
332
|
|
|
|
|
|
|
connection => $obj->{dbh},
|
333
|
|
|
|
|
|
|
sql => $obj->makeSql,
|
334
|
|
|
|
|
|
|
method => sub { $obj->make_tree_list(@_) },
|
335
|
|
|
|
|
|
|
columns => [$obj->{idx}, $obj->{textcolumn}, $obj->{parent_id}],
|
336
|
|
|
|
|
|
|
start_id => $obj->{start_id},
|
337
|
|
|
|
|
|
|
recursive => 0,
|
338
|
|
|
|
|
|
|
);
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
$obj->{fieldtypes} = $obj->getFieldTypes
|
341
|
|
|
|
|
|
|
unless(defined $obj->{fieldtypes});
|
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
$obj->{tree}->configure(-command => $obj->{command})
|
344
|
|
|
|
|
|
|
if(defined $obj->{command} and ref $obj->{command} eq 'CODE');
|
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
$obj->remember();
|
347
|
|
|
|
|
|
|
$obj->list({
|
348
|
|
|
|
|
|
|
item => $item,
|
349
|
|
|
|
|
|
|
redraw => $redraw,
|
350
|
|
|
|
|
|
|
});
|
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
$obj->{tree}->focus;
|
353
|
|
|
|
|
|
|
# $obj->select_entrys($obj->{FoundEntrys});
|
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
if($obj->{zoom} and scalar @{$obj->{FoundEntrys}}) {
|
356
|
|
|
|
|
|
|
$obj->{zoom} = 0;
|
357
|
|
|
|
|
|
|
$obj->zoom();
|
358
|
|
|
|
|
|
|
}
|
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
$obj->Unbusy;
|
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
$obj->{last_refresh_time} = time;
|
363
|
|
|
|
|
|
|
}
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
# ------------------------------------------
|
366
|
|
|
|
|
|
|
sub select_entrys {
|
367
|
|
|
|
|
|
|
# ------------------------------------------
|
368
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
369
|
|
|
|
|
|
|
$obj->{FoundEntrys} = shift || return $obj->{FoundEntrys};
|
370
|
|
|
|
|
|
|
$obj->color_all();
|
371
|
|
|
|
|
|
|
$obj->zoom if($obj->infozoom);
|
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
my @found;
|
374
|
|
|
|
|
|
|
foreach my $id (@{$obj->{FoundEntrys}} ) {
|
375
|
|
|
|
|
|
|
my $entry = $obj->id2path($id);
|
376
|
|
|
|
|
|
|
push(@found, $entry)
|
377
|
|
|
|
|
|
|
if(defined $entry);
|
378
|
|
|
|
|
|
|
}
|
379
|
|
|
|
|
|
|
$obj->{FoundEntrys} = \@found;
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
foreach (@found) {
|
382
|
|
|
|
|
|
|
$obj->to_parent_open($_);
|
383
|
|
|
|
|
|
|
$obj->color_row($_, $obj->{highlight});
|
384
|
|
|
|
|
|
|
}
|
385
|
|
|
|
|
|
|
my $entry = $found[0] || return;
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
if($obj->info('exists', $entry)) {
|
388
|
|
|
|
|
|
|
$obj->{tree}->anchorSet($entry);
|
389
|
|
|
|
|
|
|
$obj->{tree}->selectionSet($entry);
|
390
|
|
|
|
|
|
|
$obj->{tree}->see($entry);
|
391
|
|
|
|
|
|
|
}
|
392
|
|
|
|
|
|
|
}
|
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
# ------------------------------------------
|
395
|
|
|
|
|
|
|
sub see {
|
396
|
|
|
|
|
|
|
# ------------------------------------------
|
397
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
398
|
|
|
|
|
|
|
my $ids = shift || return debug('No Id in see()!');
|
399
|
|
|
|
|
|
|
my @ret;
|
400
|
|
|
|
|
|
|
$obj->{tree}->selectionClear();
|
401
|
|
|
|
|
|
|
undef $obj->{FoundEntrys};
|
402
|
|
|
|
|
|
|
foreach my $id ( split(/[^0-9A-Za-z]/, $ids) ) {
|
403
|
|
|
|
|
|
|
next unless($id);
|
404
|
|
|
|
|
|
|
my $entry = $obj->id2path($id) || next;
|
405
|
|
|
|
|
|
|
push(@{$obj->{FoundEntrys}}, $id);
|
406
|
|
|
|
|
|
|
$obj->debug('%s: = %s', $id, $entry);
|
407
|
|
|
|
|
|
|
$obj->to_parent_open($entry);
|
408
|
|
|
|
|
|
|
$obj->{tree}->selectionSet($entry);
|
409
|
|
|
|
|
|
|
push(@ret, $entry);
|
410
|
|
|
|
|
|
|
}
|
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
my $last = $ret[0] or return error('No Id to see!');
|
413
|
|
|
|
|
|
|
$obj->{tree}->OpenCmd(1)
|
414
|
|
|
|
|
|
|
if($obj->{tree}->getmode(1) eq 'open');
|
415
|
|
|
|
|
|
|
$obj->{tree}->see($last);
|
416
|
|
|
|
|
|
|
$obj->{tree}->anchorSet($last);
|
417
|
|
|
|
|
|
|
$obj->color_row($last, $obj->{highlight});
|
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
$obj->select_entrys( \@ret )
|
420
|
|
|
|
|
|
|
if(scalar @ret > 1);
|
421
|
|
|
|
|
|
|
return @ret;
|
422
|
|
|
|
|
|
|
}
|
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# ------------------------------------------
|
426
|
|
|
|
|
|
|
sub color_row {
|
427
|
|
|
|
|
|
|
# ------------------------------------------
|
428
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
429
|
|
|
|
|
|
|
my $id = shift || return error('No Id');
|
430
|
|
|
|
|
|
|
my $color = shift || $obj->{normal};
|
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
$id = $obj->id2path($id)
|
433
|
|
|
|
|
|
|
unless($id =~ /\:/);
|
434
|
|
|
|
|
|
|
return unless($obj->info('exists', $id));
|
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
my $i = 0;
|
437
|
|
|
|
|
|
|
foreach ($obj->{textcolumn}, @{$obj->{fields}}) {
|
438
|
|
|
|
|
|
|
$obj->{tree}->itemConfigure($id, $i, -style => $color);
|
439
|
|
|
|
|
|
|
$i++;
|
440
|
|
|
|
|
|
|
}
|
441
|
|
|
|
|
|
|
}
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# ------------------------------------------
|
444
|
|
|
|
|
|
|
sub color_clear {
|
445
|
|
|
|
|
|
|
# ------------------------------------------
|
446
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
447
|
|
|
|
|
|
|
my $entrys = shift || $obj->{FoundEntrys} || return;
|
448
|
|
|
|
|
|
|
my $color = shift || $obj->{normal};
|
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
foreach my $entry (sort @{$entrys}) {
|
451
|
|
|
|
|
|
|
$obj->color_row($entry, $color);
|
452
|
|
|
|
|
|
|
}
|
453
|
|
|
|
|
|
|
}
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
# ------------------------------------------
|
457
|
|
|
|
|
|
|
sub color_all {
|
458
|
|
|
|
|
|
|
# ------------------------------------------
|
459
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
460
|
|
|
|
|
|
|
my $color = shift || $obj->{normal};
|
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
foreach my $entry (sort @{$obj->{ListOfAllEntries}}) {
|
463
|
|
|
|
|
|
|
$obj->color_row($entry, $color);
|
464
|
|
|
|
|
|
|
}
|
465
|
|
|
|
|
|
|
}
|
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# ------------------------------------------
|
468
|
|
|
|
|
|
|
sub remember {
|
469
|
|
|
|
|
|
|
# ------------------------------------------
|
470
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
471
|
|
|
|
|
|
|
my $rem = shift;
|
472
|
|
|
|
|
|
|
my $ret;
|
473
|
|
|
|
|
|
|
unless( $rem ) {
|
474
|
|
|
|
|
|
|
$ret->{status} = $obj->{OPEN};
|
475
|
|
|
|
|
|
|
$ret->{version} = $Version;
|
476
|
|
|
|
|
|
|
my $i = 0;
|
477
|
|
|
|
|
|
|
my $conf;
|
478
|
|
|
|
|
|
|
foreach my $spalte ($obj->{textcolumn}, @{$obj->{fields}}) {
|
479
|
|
|
|
|
|
|
push(@{$ret->{widths}}, $obj->{tree}->columnWidth($i++));
|
480
|
|
|
|
|
|
|
}
|
481
|
|
|
|
|
|
|
} else {
|
482
|
|
|
|
|
|
|
return $obj->debug('This configuration (V: %s) isn\'t compatible with this (V: %s). Ignoring.',
|
483
|
|
|
|
|
|
|
(defined $rem->{version} ? $rem->{version} : 'NoVersion'),
|
484
|
|
|
|
|
|
|
$Version)
|
485
|
|
|
|
|
|
|
if(! defined $rem->{version} or (defined $rem->{version} and $Version > $rem->{version}));
|
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
$obj->{OPEN} = $obj->{tree}->{status} = $rem->{status}
|
488
|
|
|
|
|
|
|
if(defined $rem->{status});
|
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
$obj->{widths} = $rem->{widths}
|
491
|
|
|
|
|
|
|
if(defined $rem->{widths});
|
492
|
|
|
|
|
|
|
}
|
493
|
|
|
|
|
|
|
return $ret;
|
494
|
|
|
|
|
|
|
}
|
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
# ------------------------------------------
|
497
|
|
|
|
|
|
|
sub make_tree_list {
|
498
|
|
|
|
|
|
|
# ------------------------------------------
|
499
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
500
|
|
|
|
|
|
|
my %parms = @_;
|
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
my @parent_ids = @{ $parms{parent_id} };
|
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
my $treeval = '';
|
505
|
|
|
|
|
|
|
foreach (@parent_ids) {
|
506
|
|
|
|
|
|
|
$treeval .= "$_:";
|
507
|
|
|
|
|
|
|
}
|
508
|
|
|
|
|
|
|
$treeval .= $parms{id};
|
509
|
|
|
|
|
|
|
push(@{$obj->{ListOfAllEntries}}, $treeval);
|
510
|
|
|
|
|
|
|
}
|
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
# ------------------------------------------
|
513
|
|
|
|
|
|
|
sub get_id {
|
514
|
|
|
|
|
|
|
# ------------------------------------------
|
515
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
516
|
|
|
|
|
|
|
my $w = shift || return error('No Widget!');
|
517
|
|
|
|
|
|
|
my $ev = $w->XEvent;
|
518
|
|
|
|
|
|
|
my $id = $w->nearest($ev->y);
|
519
|
|
|
|
|
|
|
$obj->{tree}->anchorSet($id);
|
520
|
|
|
|
|
|
|
$obj->{tree}->selectionClear();
|
521
|
|
|
|
|
|
|
$obj->{tree}->selectionSet($id);
|
522
|
|
|
|
|
|
|
my ($col, $col_nr) = $obj->x2col( $ev->x + $w->xview() ); |
523
|
|
|
|
|
|
|
my $wert = $w->itemCget($id, $col_nr, -text); |
524
|
|
|
|
|
|
|
return ($id, $col, $col_nr, $wert);
|
525
|
|
|
|
|
|
|
}
|
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
# ------------------------------------------ |
528
|
|
|
|
|
|
|
sub x2col { |
529
|
|
|
|
|
|
|
# ------------------------------------------ |
530
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
531
|
|
|
|
|
|
|
my $x = shift; |
532
|
|
|
|
|
|
|
my $c = 0; |
533
|
|
|
|
|
|
|
my $von = 0; |
534
|
|
|
|
|
|
|
foreach my $name ($obj->{textcolumn}, @{$obj->{fields}}) {
|
535
|
|
|
|
|
|
|
my $breite = $obj->{tree}->columnWidth( $c); |
536
|
|
|
|
|
|
|
my $bis = $von + $breite; |
537
|
|
|
|
|
|
|
return (($obj->{colNames}->[$c] || $name), $c) |
538
|
|
|
|
|
|
|
if($x >= $von && $x <= $bis); |
539
|
|
|
|
|
|
|
$von += $breite; |
540
|
|
|
|
|
|
|
$c++;
|
541
|
|
|
|
|
|
|
} |
542
|
|
|
|
|
|
|
}
|
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
# ------------------------------------------
|
545
|
|
|
|
|
|
|
sub infozoom {
|
546
|
|
|
|
|
|
|
# ------------------------------------------
|
547
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
548
|
|
|
|
|
|
|
$obj->debug('Zoom is %s', ( $obj->{zoom} ? 'on' : 'off' ));
|
549
|
|
|
|
|
|
|
return $obj->{zoom};
|
550
|
|
|
|
|
|
|
}
|
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
# ------------------------------------------
|
553
|
|
|
|
|
|
|
sub zoom {
|
554
|
|
|
|
|
|
|
# ------------------------------------------
|
555
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
556
|
|
|
|
|
|
|
return unless($obj->{FoundEntrys});
|
557
|
|
|
|
|
|
|
$obj->Busy;
|
558
|
|
|
|
|
|
|
$obj->{zoom} = ($obj->{zoom} ? undef : 1);
|
559
|
|
|
|
|
|
|
if($obj->{zoom}) {
|
560
|
|
|
|
|
|
|
foreach my $entry (sort @{$obj->{ListOfAllEntries}}) {
|
561
|
|
|
|
|
|
|
next unless($entry);
|
562
|
|
|
|
|
|
|
my $search = $entry;
|
563
|
|
|
|
|
|
|
$search =~ s/\:/\\:/sig;
|
564
|
|
|
|
|
|
|
unless(grep(/^$search/, @{$obj->{FoundEntrys}})) {
|
565
|
|
|
|
|
|
|
unless($obj->info('hidden', $entry)) {
|
566
|
|
|
|
|
|
|
$obj->{tree}->hide('entry', $entry);
|
567
|
|
|
|
|
|
|
push(@{$obj->{HiddenEntrys}}, $entry);
|
568
|
|
|
|
|
|
|
}
|
569
|
|
|
|
|
|
|
}
|
570
|
|
|
|
|
|
|
}
|
571
|
|
|
|
|
|
|
} else {
|
572
|
|
|
|
|
|
|
foreach my $entry (@{$obj->{HiddenEntrys}}) {
|
573
|
|
|
|
|
|
|
$obj->{tree}->show('entry', $entry)
|
574
|
|
|
|
|
|
|
if($obj->info('hidden', $entry));
|
575
|
|
|
|
|
|
|
}
|
576
|
|
|
|
|
|
|
@{$obj->{HiddenEntrys}} = qw//;
|
577
|
|
|
|
|
|
|
}
|
578
|
|
|
|
|
|
|
$obj->Unbusy;
|
579
|
|
|
|
|
|
|
}
|
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
# ------------------------------------------
|
583
|
|
|
|
|
|
|
sub makeSql {
|
584
|
|
|
|
|
|
|
# ------------------------------------------
|
585
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
586
|
|
|
|
|
|
|
my $sql;
|
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
if($obj->{joiner}) {
|
589
|
|
|
|
|
|
|
$sql = sprintf('SELECT %s, %s, %s, %s FROM %s LEFT JOIN %s ON %s ORDER BY %s',
|
590
|
|
|
|
|
|
|
$obj->{idx}, $obj->{textcolumn},join(',', @{$obj->{fields}}), $obj->{parent_id},
|
591
|
|
|
|
|
|
|
$obj->{table}->[0], $obj->{table}->[1],
|
592
|
|
|
|
|
|
|
$obj->{joiner},
|
593
|
|
|
|
|
|
|
$obj->{textcolumn}
|
594
|
|
|
|
|
|
|
);
|
595
|
|
|
|
|
|
|
} else {
|
596
|
|
|
|
|
|
|
$sql = sprintf('select %s, %s, %s, %s from %s %s ORDER BY %s, %s',
|
597
|
|
|
|
|
|
|
$obj->{idx}, $obj->{textcolumn} ,join(',', @{$obj->{fields}}), $obj->{parent_id},
|
598
|
|
|
|
|
|
|
$obj->{table},
|
599
|
|
|
|
|
|
|
sprintf('WHERE %s in (%s)', $obj->{parent_id}, join(',', @{$obj->search_unique_ids($obj->{OPEN})} ) ),
|
600
|
|
|
|
|
|
|
$obj->{parent_id}, $obj->{idx}
|
601
|
|
|
|
|
|
|
);
|
602
|
|
|
|
|
|
|
}
|
603
|
|
|
|
|
|
|
$obj->debug('makeSql: %s', $sql)
|
604
|
|
|
|
|
|
|
if($obj->{debug});
|
605
|
|
|
|
|
|
|
return $sql;
|
606
|
|
|
|
|
|
|
}
|
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
# ------------------ |
610
|
|
|
|
|
|
|
sub search_unique_ids {
|
611
|
|
|
|
|
|
|
# ------------------ |
612
|
|
|
|
|
|
|
my $obj = shift || return error ('No Object!' );
|
613
|
|
|
|
|
|
|
my $ids = shift;
|
614
|
|
|
|
|
|
|
my $ret;
|
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
foreach my $item (keys %$ids) {
|
617
|
|
|
|
|
|
|
foreach(split(':', $item)) {
|
618
|
|
|
|
|
|
|
$ret->{$_} = 1;
|
619
|
|
|
|
|
|
|
};
|
620
|
|
|
|
|
|
|
}
|
621
|
|
|
|
|
|
|
my @r = (0,$obj->{start_id}, keys %$ret);
|
622
|
|
|
|
|
|
|
return \@r;
|
623
|
|
|
|
|
|
|
}
|
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
# ------------------------------------------
|
627
|
|
|
|
|
|
|
sub getFieldTypes {
|
628
|
|
|
|
|
|
|
# ------------------------------------------
|
629
|
|
|
|
|
|
|
my $obj = shift or return warn("No object");
|
630
|
|
|
|
|
|
|
my $dbh = $obj->{dbh};
|
631
|
|
|
|
|
|
|
my $table = ref $obj->{table} ? $obj->{table}->[0] : $obj->{table};
|
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
return $obj->{$table}->{fieldtypes}
|
634
|
|
|
|
|
|
|
if(defined $obj->{$table}->{fieldtypes});
|
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
$obj->{$table}->{fieldtypes} = $dbh->selectall_hashref("show fields from $table", 'Field')
|
637
|
|
|
|
|
|
|
or return $obj->debug($dbh->errstr);
|
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
return $obj->{$table}->{fieldtypes};
|
640
|
|
|
|
|
|
|
}
|
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
# ------------------------------------------
|
644
|
|
|
|
|
|
|
sub list {
|
645
|
|
|
|
|
|
|
# ------------------------------------------
|
646
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
647
|
|
|
|
|
|
|
my $arg = shift;
|
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
my $item = $arg->{item};
|
650
|
|
|
|
|
|
|
my $redraw = $arg->{redraw};
|
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
return if(defined $item and $obj->info('exists', $item) and $obj->info('children', $item));
|
653
|
|
|
|
|
|
|
my $idx = ( index($obj->{idx}, '.') ? ( split( '\.', $obj->{idx} ) )[-1] : $obj->{idx});
|
654
|
|
|
|
|
|
|
my $iname = $1 if($idx =~ /([a-z_]+)/si);
|
655
|
|
|
|
|
|
|
my $len = $1 if($obj->getFieldTypes->{$iname}->{Type} =~ /(\d+)/);
|
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
if($DBIx::Tree::VERSION < 1) {
|
658
|
|
|
|
|
|
|
$obj->{dbtree}->do_query;
|
659
|
|
|
|
|
|
|
$obj->{dbtree}->tree;
|
660
|
|
|
|
|
|
|
} else {
|
661
|
|
|
|
|
|
|
$obj->{dbtree}->traverse;
|
662
|
|
|
|
|
|
|
}
|
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
my $sql = $obj->makeSql;
|
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
my $DATA = $obj->{dbh}->selectall_hashref( $sql, $idx)
|
667
|
|
|
|
|
|
|
or return error($obj->{dbh}->errstr);
|
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
foreach my $id (sort @{$obj->{ListOfAllEntries}}) {
|
670
|
|
|
|
|
|
|
my ($item_id, $pid) = $obj->id($id);
|
671
|
|
|
|
|
|
|
next if(! $obj->{tree}->infoExists($pid) and $pid);
|
672
|
|
|
|
|
|
|
next if($obj->{tree}->infoExists($id));
|
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
$obj->{Paths}->{$item_id} = $id;
|
675
|
|
|
|
|
|
|
my $row = $DATA->{$item_id} || $DATA->{sprintf("%0${len}d", $item_id)} || error('Error: No Data for %s', $item_id);
|
676
|
|
|
|
|
|
|
$obj->{tree}->add($id,
|
677
|
|
|
|
|
|
|
-itemtype => 'imagetext',
|
678
|
|
|
|
|
|
|
-data => $row,
|
679
|
|
|
|
|
|
|
-text => $obj->parse_text($row->{$obj->{textcolumn}}, $obj->{textcolumn}),
|
680
|
|
|
|
|
|
|
-style => $obj->{normal},
|
681
|
|
|
|
|
|
|
) if($row);
|
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
&{$obj->{entry_create_cb}}($obj->{tree}, $id, $row)
|
684
|
|
|
|
|
|
|
if(defined $obj->{entry_create_cb} and ref $obj->{entry_create_cb} eq 'CODE');
|
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
my $c = 1;
|
687
|
|
|
|
|
|
|
foreach my $field (@{$obj->{fields}}) {
|
688
|
|
|
|
|
|
|
$obj->{tree}->itemCreate( $id, $c++,
|
689
|
|
|
|
|
|
|
-text => $obj->parse_text($row->{$field}, $field),
|
690
|
|
|
|
|
|
|
-style => $obj->{normal},
|
691
|
|
|
|
|
|
|
);
|
692
|
|
|
|
|
|
|
}
|
693
|
|
|
|
|
|
|
}
|
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
# Draw Indicators
|
696
|
|
|
|
|
|
|
$obj->{tree}->autosetmode;
|
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
# Check is exists Ptree or Table is change, then reload
|
700
|
|
|
|
|
|
|
$sql = sprintf('select %s, %s from %s GROUP BY %s',
|
701
|
|
|
|
|
|
|
$obj->{idx}, $obj->{parent_id},
|
702
|
|
|
|
|
|
|
(ref $obj->{table} ? join(',', @{$obj->{table}}) : $obj->{table}),
|
703
|
|
|
|
|
|
|
$obj->{parent_id}
|
704
|
|
|
|
|
|
|
);
|
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
$obj->debug($sql);
|
707
|
|
|
|
|
|
|
$obj->{ptree} = $obj->{dbh}->selectall_hashref($sql, $obj->{parent_id})
|
708
|
|
|
|
|
|
|
if($redraw);
|
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
# Set the modes from every tree
|
711
|
|
|
|
|
|
|
foreach my $entry (@{$obj->{ListOfAllEntries}}) {
|
712
|
|
|
|
|
|
|
my ($id, $pid) = $obj->id($entry);
|
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
if( defined $obj->{ptree}->{$id} and $obj->{tree}->getmode($entry) eq 'none') {
|
715
|
|
|
|
|
|
|
$obj->{tree}->setmode($entry, 'open');
|
716
|
|
|
|
|
|
|
}
|
717
|
|
|
|
|
|
|
if( defined $obj->{ptree}->{$id} and $obj->{tree}->getmode($entry) eq 'close') {
|
718
|
|
|
|
|
|
|
$obj->{tree}->setmode($entry, 'close');
|
719
|
|
|
|
|
|
|
}
|
720
|
|
|
|
|
|
|
if(! defined $obj->{ptree}->{$id}) {
|
721
|
|
|
|
|
|
|
$obj->{tree}->setmode($entry, 'none');
|
722
|
|
|
|
|
|
|
}
|
723
|
|
|
|
|
|
|
}
|
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
}
|
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
# ------------------------------------------
|
728
|
|
|
|
|
|
|
sub close_all {
|
729
|
|
|
|
|
|
|
# ------------------------------------------
|
730
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
731
|
|
|
|
|
|
|
return unless(ref $obj->{ListOfAllEntries} eq 'ARRAY');
|
732
|
|
|
|
|
|
|
foreach my $entry (sort @{$obj->{ListOfAllEntries}}) {
|
733
|
|
|
|
|
|
|
$obj->{tree}->close($entry);
|
734
|
|
|
|
|
|
|
}
|
735
|
|
|
|
|
|
|
}
|
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
# ------------------------------------------
|
738
|
|
|
|
|
|
|
sub to_parent_open{
|
739
|
|
|
|
|
|
|
# ------------------------------------------
|
740
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
741
|
|
|
|
|
|
|
my $entry = shift || return error('No Entry!');
|
742
|
|
|
|
|
|
|
$entry = $obj->id2path($entry) || return error('This Entry <%s> is not exist!', $entry);
|
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
my ($id, $pid) = $obj->id($entry);
|
745
|
|
|
|
|
|
|
my $path = $obj->{start_id};
|
746
|
|
|
|
|
|
|
foreach my $e (split(/\:/, $entry)) {
|
747
|
|
|
|
|
|
|
next if($e eq $obj->{start_id});
|
748
|
|
|
|
|
|
|
next if($e eq $id);
|
749
|
|
|
|
|
|
|
$path .= sprintf(':%d', $e);
|
750
|
|
|
|
|
|
|
$obj->{tree}->open($path)
|
751
|
|
|
|
|
|
|
if($obj->info('exists', $path));
|
752
|
|
|
|
|
|
|
}
|
753
|
|
|
|
|
|
|
}
|
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
# ------------------------------------------
|
756
|
|
|
|
|
|
|
sub parse_text {
|
757
|
|
|
|
|
|
|
# ------------------------------------------
|
758
|
|
|
|
|
|
|
my $obj = shift;
|
759
|
|
|
|
|
|
|
my $text = shift || return ' ';
|
760
|
|
|
|
|
|
|
my $field = shift || return error('No FieldName!');
|
761
|
|
|
|
|
|
|
my $maxchars =
|
762
|
|
|
|
|
|
|
(ref $obj->{maxchars} eq 'HASH'
|
763
|
|
|
|
|
|
|
? $obj->{maxchars}->{$field}
|
764
|
|
|
|
|
|
|
: $obj->{maxchars}
|
765
|
|
|
|
|
|
|
) || 0;
|
766
|
|
|
|
|
|
|
$text = substr($text, 0, $maxchars).'...'
|
767
|
|
|
|
|
|
|
if($maxchars and length($text)>$maxchars);
|
768
|
|
|
|
|
|
|
$text =~ s/(\r|\n)//sig;
|
769
|
|
|
|
|
|
|
return $text;
|
770
|
|
|
|
|
|
|
}
|
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
# ------------------------------------------
|
773
|
|
|
|
|
|
|
sub parent_id {
|
774
|
|
|
|
|
|
|
# ------------------------------------------
|
775
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
776
|
|
|
|
|
|
|
my $path = shift || return error('No Path');
|
777
|
|
|
|
|
|
|
my $parent = $obj->info('parent', $path)
|
778
|
|
|
|
|
|
|
or return error('Parent not found!');
|
779
|
|
|
|
|
|
|
return (split( /:/, $parent ))[-1];
|
780
|
|
|
|
|
|
|
}
|
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
# ------------------------------------------
|
784
|
|
|
|
|
|
|
sub id {
|
785
|
|
|
|
|
|
|
# ------------------------------------------
|
786
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
787
|
|
|
|
|
|
|
my $path = shift || return error('No Path');
|
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
return $path if(index($path, ':') == -1);
|
791
|
|
|
|
|
|
|
my @elms = split(':', $path);
|
792
|
|
|
|
|
|
|
my $id = pop @elms;
|
793
|
|
|
|
|
|
|
my $pid = join(':', @elms);
|
794
|
|
|
|
|
|
|
return ($id, $pid);
|
795
|
|
|
|
|
|
|
}
|
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
# ------------------ |
798
|
|
|
|
|
|
|
sub childs {
|
799
|
|
|
|
|
|
|
# ------------------ |
800
|
|
|
|
|
|
|
my $obj = shift || return error ('No Object!' );
|
801
|
|
|
|
|
|
|
my ($i, $p) = $obj->id(shift);
|
802
|
|
|
|
|
|
|
my $id = int($i) || return error ('No Id!' );
|
803
|
|
|
|
|
|
|
$obj->debug('childs - Id: %s', $id);
|
804
|
|
|
|
|
|
|
my @ret;
|
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
# Caching
|
807
|
|
|
|
|
|
|
return @{$obj->{children}->{$id}}
|
808
|
|
|
|
|
|
|
if(defined $obj->{children}->{$id});
|
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
if(defined $obj->{ptree}->{$id}) {
|
811
|
|
|
|
|
|
|
my $sql = sprintf('select %s from %s where %s = %d',
|
812
|
|
|
|
|
|
|
$obj->{idx}, $obj->{table}, $obj->{parent_id}, $id);
|
813
|
|
|
|
|
|
|
my $chields = $obj->getSqlArray($sql);
|
814
|
|
|
|
|
|
|
foreach my $child (@{$chields}) {
|
815
|
|
|
|
|
|
|
push(@ret, $child->[0]);
|
816
|
|
|
|
|
|
|
my @ch = $obj->childs($child->[0])
|
817
|
|
|
|
|
|
|
if(defined $obj->{ptree}->{$child->[0]});
|
818
|
|
|
|
|
|
|
push(@ret, @ch);
|
819
|
|
|
|
|
|
|
}
|
820
|
|
|
|
|
|
|
}
|
821
|
|
|
|
|
|
|
# Caching
|
822
|
|
|
|
|
|
|
$obj->{children}->{$id} = \@ret;
|
823
|
|
|
|
|
|
|
return @ret;
|
824
|
|
|
|
|
|
|
}
|
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
# ------------------------------------------
|
829
|
|
|
|
|
|
|
sub id2path {
|
830
|
|
|
|
|
|
|
# ------------------------------------------
|
831
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
832
|
|
|
|
|
|
|
my $id = shift || return debug('No ID');
|
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
return $id
|
835
|
|
|
|
|
|
|
if($id =~ /\:/);
|
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
return $obj->{Paths}->{$id}
|
838
|
|
|
|
|
|
|
if(defined $obj->{Paths}->{$id} and $obj->{Paths}->{$id} =~ /\:/ and $obj->{Paths}->{$id} ne $obj->{start_id});
|
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
$id = int($id);
|
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
my @tree;
|
843
|
|
|
|
|
|
|
my $parent_id = $obj->sqlv("select %s from %s where %s = '%s'",
|
844
|
|
|
|
|
|
|
$obj->{parent_id},
|
845
|
|
|
|
|
|
|
(ref $obj->{table} ? join(',', @{$obj->{table}}) : $obj->{table}),
|
846
|
|
|
|
|
|
|
$obj->{idx}, $id);
|
847
|
|
|
|
|
|
|
return error('No found!')
|
848
|
|
|
|
|
|
|
unless(defined $parent_id);
|
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
unshift(@tree, $parent_id, $id);
|
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
my $maxdeep;
|
854
|
|
|
|
|
|
|
while($parent_id) {
|
855
|
|
|
|
|
|
|
last if($maxdeep++ >= 10);
|
856
|
|
|
|
|
|
|
my $vater_parent_id = $obj->sqlv('select %s from %s where %s = "%s"',
|
857
|
|
|
|
|
|
|
$obj->{parent_id}, $obj->{table}, $obj->{idx}, $parent_id) || last;
|
858
|
|
|
|
|
|
|
unshift(@tree, $vater_parent_id);
|
859
|
|
|
|
|
|
|
$parent_id = $vater_parent_id;
|
860
|
|
|
|
|
|
|
}
|
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
# Cache this Information
|
863
|
|
|
|
|
|
|
$obj->{Paths}->{$id} = join(':', @tree);
|
864
|
|
|
|
|
|
|
return $obj->{Paths}->{$id};
|
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
}
|
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
# ------------------------------------------
|
869
|
|
|
|
|
|
|
sub listEntrys {
|
870
|
|
|
|
|
|
|
# ------------------------------------------
|
871
|
|
|
|
|
|
|
my $obj = shift;
|
872
|
|
|
|
|
|
|
return $obj->{ListOfAllEntries};
|
873
|
|
|
|
|
|
|
}
|
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
# ------------------------------------------
|
876
|
|
|
|
|
|
|
sub info {
|
877
|
|
|
|
|
|
|
# ------------------------------------------
|
878
|
|
|
|
|
|
|
my $obj = shift or return error("No object");
|
879
|
|
|
|
|
|
|
my $typ = shift or return error("No Type");
|
880
|
|
|
|
|
|
|
my $entry = shift;
|
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
# $obj->debug('info: %s - %s', $typ, $entry);
|
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
if($typ =~ /^(selection|anchor|dragsite|dropsite)$/si) {
|
885
|
|
|
|
|
|
|
my @ids = $obj->{tree}->info($typ);
|
886
|
|
|
|
|
|
|
return \@ids;
|
887
|
|
|
|
|
|
|
}
|
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
if($entry and $entry !~ /\:/) {
|
890
|
|
|
|
|
|
|
$entry = $obj->id2path($entry)
|
891
|
|
|
|
|
|
|
or return error('Can\'t find <%s> in Paths!', $entry);
|
892
|
|
|
|
|
|
|
}
|
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
return error('Can\'t find Id: %s', $entry)
|
895
|
|
|
|
|
|
|
if($typ ne 'exists' and ! $obj->{tree}->info('exists', $entry));
|
896
|
|
|
|
|
|
|
my $answ = $obj->{tree}->info($typ, $entry);
|
897
|
|
|
|
|
|
|
# $obj->debug('info: Answer = <%s>', $answ);
|
898
|
|
|
|
|
|
|
return $answ;
|
899
|
|
|
|
|
|
|
}
|
900
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
# ------------------------------------------
|
903
|
|
|
|
|
|
|
sub getSqlArray {
|
904
|
|
|
|
|
|
|
# ------------------------------------------
|
905
|
|
|
|
|
|
|
my $obj = shift or return error("No object");
|
906
|
|
|
|
|
|
|
my $sql = shift or return error('No Sql');
|
907
|
|
|
|
|
|
|
my $dbh = $obj->{dbh};
|
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
$obj->debug($sql);
|
910
|
|
|
|
|
|
|
my $sth = $dbh->prepare($sql) or return error("$DBI::errstr - $sql");
|
911
|
|
|
|
|
|
|
$sth->execute or return error("$DBI::errstr - $sql");
|
912
|
|
|
|
|
|
|
return $sth->fetchall_arrayref;
|
913
|
|
|
|
|
|
|
}
|
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
# ------------------------------------------
|
916
|
|
|
|
|
|
|
sub Table_is_Change {
|
917
|
|
|
|
|
|
|
# ------------------------------------------
|
918
|
|
|
|
|
|
|
my $obj = shift or return error("No object");
|
919
|
|
|
|
|
|
|
my $lasttime = shift || $obj->{last_refresh_time}; # No last time, first request!
|
920
|
|
|
|
|
|
|
my $table = shift || $obj->{table} || $obj->{table}->[0];
|
921
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
my $dbh = $obj->{dbh};
|
923
|
|
|
|
|
|
|
my $ret = 0;
|
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
my $data = $dbh->selectall_hashref(sprintf("SHOW TABLE STATUS LIKE '%s'", $table),'Name')
|
926
|
|
|
|
|
|
|
or return $obj->debug($dbh->errstr);
|
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
my $unixtime = $obj->sqlv("select UNIX_TIMESTAMP('%s')", $data->{$table}->{Update_time})
|
929
|
|
|
|
|
|
|
if(defined $data->{$table}->{Update_time});
|
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
$obj->{last_refresh_time} = time;
|
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
if(defined $unixtime and $unixtime > $lasttime) {
|
934
|
|
|
|
|
|
|
return 1;
|
935
|
|
|
|
|
|
|
}
|
936
|
|
|
|
|
|
|
}
|
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
# ------------------------------------------
|
939
|
|
|
|
|
|
|
sub rm_from_array {
|
940
|
|
|
|
|
|
|
# ------------------------------------------
|
941
|
|
|
|
|
|
|
my $obj = shift || return error('No Object');
|
942
|
|
|
|
|
|
|
my $arr = shift || return error('No Array');
|
943
|
|
|
|
|
|
|
my $id = shift || return error('No Id');
|
944
|
|
|
|
|
|
|
$obj->debug('rm_from_array - Arr: %s, Id: %s', $arr, $id);
|
945
|
|
|
|
|
|
|
my @new_array = grep(!/$id/, @$arr);
|
946
|
|
|
|
|
|
|
|
947
|
|
|
|
|
|
|
return \@new_array;
|
948
|
|
|
|
|
|
|
}
|
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
# ------------------ |
951
|
|
|
|
|
|
|
sub sqlv {
|
952
|
|
|
|
|
|
|
# ------------------ |
953
|
|
|
|
|
|
|
my $obj = shift || return error ('No Object!' );
|
954
|
|
|
|
|
|
|
my $sql = sprintf(shift, @_) || return error ('No Sql' );
|
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
$obj->debug($sql);
|
957
|
|
|
|
|
|
|
return $obj->getSqlArray($sql)->[0][0];
|
958
|
|
|
|
|
|
|
}
|
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
# ------------------------------------------
|
963
|
|
|
|
|
|
|
sub debug {
|
964
|
|
|
|
|
|
|
# ------------------------------------------
|
965
|
|
|
|
|
|
|
my $obj = shift;
|
966
|
|
|
|
|
|
|
return unless($obj->{debug});
|
967
|
|
|
|
|
|
|
my ($package, $filename, $line, $subroutine, $hasargs,
|
968
|
|
|
|
|
|
|
$wantarray, $evaltext, $is_require, $hints, $bitmask) = caller(1);
|
969
|
|
|
|
|
|
|
print color 'green';
|
970
|
|
|
|
|
|
|
printf '#%d: ', $line;
|
971
|
|
|
|
|
|
|
printf @_ if(scalar @_);
|
972
|
|
|
|
|
|
|
print "\n";
|
973
|
|
|
|
|
|
|
print color 'reset';
|
974
|
|
|
|
|
|
|
}
|
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
# ------------------------------------------
|
977
|
|
|
|
|
|
|
sub error {
|
978
|
|
|
|
|
|
|
# ------------------------------------------
|
979
|
|
|
|
|
|
|
my $msg = shift;
|
980
|
|
|
|
|
|
|
my ($package, $filename, $line, $subroutine, $hasargs,
|
981
|
|
|
|
|
|
|
$wantarray, $evaltext, $is_require, $hints, $bitmask) = caller(1);
|
982
|
|
|
|
|
|
|
my $error = sprintf("ERROR in %s %s #%d: <%s>\n",
|
983
|
|
|
|
|
|
|
(defined $package ? $package : 'nopackage'),
|
984
|
|
|
|
|
|
|
(defined $subroutine ? $subroutine : 'nosub'),
|
985
|
|
|
|
|
|
|
(defined $line ? $line : 'noline'),
|
986
|
|
|
|
|
|
|
(defined $msg ? sprintf($msg, @_) : 'no message')
|
987
|
|
|
|
|
|
|
);
|
988
|
|
|
|
|
|
|
print color 'bold red';
|
989
|
|
|
|
|
|
|
print $error;
|
990
|
|
|
|
|
|
|
print color 'reset';
|
991
|
|
|
|
|
|
|
return undef;
|
992
|
|
|
|
|
|
|
}
|
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
1;
|
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
=head1 NAME
|
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
Tk::DBIx::Tree - Megawidget to display a table column in a tree.
|
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
use Tk;
|
1005
|
|
|
|
|
|
|
use Tk::DBIx::Tree;
|
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
my $top = MainWindow->new;
|
1008
|
|
|
|
|
|
|
my $tkdbi = $top->DBITree(
|
1009
|
|
|
|
|
|
|
-dbh => $dbh, |
1010
|
|
|
|
|
|
|
-table => 'Inventory', |
1011
|
|
|
|
|
|
|
-textcolumn => 'name', |
1012
|
|
|
|
|
|
|
-idx => 'id', |
1013
|
|
|
|
|
|
|
-columnWidths => [undef, undef, undef, 150], |
1014
|
|
|
|
|
|
|
-fields => [qw(changed_by changed_at descr)], |
1015
|
|
|
|
|
|
|
-parent_id => 'parent_id', |
1016
|
|
|
|
|
|
|
-start_id => 1, |
1017
|
|
|
|
|
|
|
-maxchars => { descr => 25 }, |
1018
|
|
|
|
|
|
|
)->pack(-expand => 1,
|
1019
|
|
|
|
|
|
|
-fill => 'both');
|
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
MainLoop;
|
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
This is a megawidget to display a sql statement from your database in a tree view
|
1026
|
|
|
|
|
|
|
widget. When you've got one of those nasty self-referential tables that you
|
1027
|
|
|
|
|
|
|
want to bust out into a tree, this is the module to check out.
|
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
=head1 WIDGET-SPECIFIC OPTIONS
|
1030
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
=head2 -dbh => $ref_on_database_handle
|
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
A database handle, this will return an error if it is'nt defined.
|
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
=head2 -debug => [I<0>|1]
|
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
This is a switch to turn on debug output to the standard console (STDOUT)
|
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
=head2 -table => 'tablename'
|
1040
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
The table to display.
|
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
=head2 -idx => 'index_column'
|
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
The index column from the table.
|
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
=head2 -fields => [col0, col1, col2, ...]
|
1048
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
List of additional fields to display.
|
1050
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
=head2 -colNames => [col0, col1, col2, ...]
|
1052
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
List of alternative names for every column. This will display on header.
|
1054
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
=head2 -where => 'WHERE foo == 1, ...'
|
1056
|
|
|
|
|
|
|
|
1057
|
|
|
|
|
|
|
Additional where statement for choice rows in table.
|
1058
|
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
=head2 -textcolumn => colname
|
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
The name of the column to be displayed in the tree..
|
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
=head2 -start_id => integer
|
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
The id, where the widget will start to create the tree. Default is 1.
|
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
=head2 -columnWidths => [colWidth_0, colWidth_1, colWidth_2, ...]
|
1068
|
|
|
|
|
|
|
|
1069
|
|
|
|
|
|
|
Default field column width.
|
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
=head2 -highlight => I<[-foreground => 'blue']>
|
1072
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
Style for founded Entries.
|
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
=head2 -normal => I<[-foreground => 'black']>
|
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
Default style for Entries.
|
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
=head2 -maxchars => number or {col1 =number}
|
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
Maximum number of characters to be displayed within the cells. Global
|
1082
|
|
|
|
|
|
|
validity or set only for named columns.
|
1083
|
|
|
|
|
|
|
I.E.:
|
1084
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
-maxchars => {
|
1086
|
|
|
|
|
|
|
descr => 25,
|
1087
|
|
|
|
|
|
|
name => 10,
|
1088
|
|
|
|
|
|
|
},
|
1089
|
|
|
|
|
|
|
# or ....
|
1090
|
|
|
|
|
|
|
-maxchars => 25, # global for all fields
|
1091
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
=head2 -time_column => $name_from_time_column
|
1094
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
Maximum number of characters to be displayed within the cells. Global
|
1096
|
|
|
|
|
|
|
validity or set only for named columns.
|
1097
|
|
|
|
|
|
|
I.E.:
|
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
-maxchars => {
|
1100
|
|
|
|
|
|
|
descr => 25,
|
1101
|
|
|
|
|
|
|
name => 10,
|
1102
|
|
|
|
|
|
|
},
|
1103
|
|
|
|
|
|
|
# or ....
|
1104
|
|
|
|
|
|
|
-maxchars => 25, # global for all fields
|
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
=head1 METHODS
|
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
These are the methods you can use with this Widget.
|
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
=head2 $DBITree->refresh('reload');
|
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
Refresh the tree. if you call this method with the parameter reload
|
1113
|
|
|
|
|
|
|
then this will reload the table from database. If you call this without parameter, then
|
1114
|
|
|
|
|
|
|
look this widget is the table changed (update date) at the last refresh. If this true, then
|
1115
|
|
|
|
|
|
|
load this the complete table and redraw the tree.
|
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
=head2 $DBITree->refresh_id( I, I );
|
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
This will refresh (delete -> new) a Tree item.
|
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
=head2 $DBITree->copy( I, I, I );
|
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
Copy an entry (entry) to a parent branch (to_parent_entry) with data (data);
|
1124
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
=head2 $DBITree->move( I, I, I );
|
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
Move an entry (from_entry) to a parent branch (to_parent_entry) with data (data);
|
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
=head2 $DBITree->dele( I );
|
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
Delete a entry.
|
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
=head2 $DBITree->neu( I, I, I );
|
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
Create a entry.
|
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
=head2 $DBITree->close_all;
|
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
close all tree branches.
|
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
=head2 $DBITree->info('anchor, bbox, children, B, dragsite, dropsite ...', $id);
|
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
This is a wrapper to the HList Method ->info. The default method is info('data', ...).
|
1144
|
|
|
|
|
|
|
Please read the manual from Tk::HList.
|
1145
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
=head2 $DBITree->id2path(I);
|
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
This returns the path for given id.
|
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
=head2 $DBITree->ListEntrys;
|
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
This returnd a sorted ref array with all entrys in the tree.
|
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
=head2 $DBITree->select_entrys([en1, en2, en3, ...]);
|
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
This returns a sorted ref array with all selected entries
|
1157
|
|
|
|
|
|
|
in the tree or you can set an array of selected entries.
|
1158
|
|
|
|
|
|
|
Also you can use only the id's, i.e.:
|
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
$dbitree->select_entrys([qw/1:2 1:3 1:4/]);
|
1161
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
# or ...
|
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
$dbitree->select_entrys([qw/2 3 4/]);
|
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
These is friendly if you use i.e. a statement 'select id from table where foo == bla'
|
1167
|
|
|
|
|
|
|
and you have only the id's without the pathinformation. Tk::DBIx::Tree know, select only
|
1168
|
|
|
|
|
|
|
the entries have at last position this id in path.
|
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
=head2 $DBITree->zoom;
|
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
Shrink or unshrink tree to display only founded entries.
|
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
=head2 $DBITree->infozoom;
|
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
Returnd true if zoom active.
|
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
=head2 $DBITree->color_all([style]);
|
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
Set all entries to normal style without parameters.
|
1181
|
|
|
|
|
|
|
You can put a new Style to all entries.
|
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
i.e:
|
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
$DBITree->color_clear([qw/1 2 3/], [-background => 'gray50']);
|
1186
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
=head2 $DBITree->color_clear([entrys], style);
|
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
Remove all higlighted styles from the functions see and select_entrys.
|
1190
|
|
|
|
|
|
|
if you don't give entrys, tree take the internal foundentrys.
|
1191
|
|
|
|
|
|
|
if you don't give style, tree take the normal style.
|
1192
|
|
|
|
|
|
|
|
1193
|
|
|
|
|
|
|
i.e:
|
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
$DBITree->color_clear([-background => 'gray50']);
|
1196
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
=head2 $DBITree->get_id;
|
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
select the row under mouseposition and returnd following parameters.
|
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
=over 4
|
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
=item path - The path from the entry under mouseposition.
|
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
=item col - Column name under mouseposition.
|
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
=item path - Column number under mouseposition.
|
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
=item value - Cell value under mouseposition.
|
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
=back
|
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
=head2 $DBITree->childs($item);
|
1215
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
Return an array with paths from childs for $item, include $item.
|
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
=head2 $DBITree->parent_id($path);
|
1219
|
|
|
|
|
|
|
|
1220
|
|
|
|
|
|
|
Return the actually id from the parentree (only the integer id, not the hole path)
|
1221
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
=head2 $DBITree->see($id);
|
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
Jump to id (only database id)
|
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
=head2 $DBITree->remember( $hash );
|
1227
|
|
|
|
|
|
|
|
1228
|
|
|
|
|
|
|
This method is very useful, when you want to remember the last tree status
|
1229
|
|
|
|
|
|
|
and column widths for the resize button. This returns a ref hash with following
|
1230
|
|
|
|
|
|
|
keys, if this call is done without parameters.
|
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
=over 4
|
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
=item widths - a ref array including the width of each column.
|
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
=item stats - a ref hash with status information(open close none) for each entry.
|
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
=back
|
1239
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
You can give an old Hash (may eval-load at program start) and the tree
|
1241
|
|
|
|
|
|
|
remembers this status.
|
1242
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
I.E.:
|
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
$tree->rembember( $tree->rembember );
|
1246
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
# or ...
|
1248
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
$tree->remember( {
|
1250
|
|
|
|
|
|
|
status => {
|
1251
|
|
|
|
|
|
|
'0:1' ='open',
|
1252
|
|
|
|
|
|
|
'0:1:2' ='close',
|
1253
|
|
|
|
|
|
|
...
|
1254
|
|
|
|
|
|
|
},
|
1255
|
|
|
|
|
|
|
widths =[165, 24, 546],
|
1256
|
|
|
|
|
|
|
} );
|
1257
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
=head1 CALLBACKS
|
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
=head2 -command => sub{ ... }
|
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
Callback on TreeWidget at browsing.
|
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
=head2 -entry_create_cb => sub{ ... }
|
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
Callback if an entry created. The routine have 2 parameters:
|
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
=over 4
|
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
=item entry - a ref to created entry
|
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
=item data - a ref hash with row information.
|
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
=back
|
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
i.e;
|
1277
|
|
|
|
|
|
|
|
1278
|
|
|
|
|
|
|
-entry_create_cb => sub{
|
1279
|
|
|
|
|
|
|
my($w, $path, $row) = @_;
|
1280
|
|
|
|
|
|
|
if(exists $DOC->{ $row->{id} } and exists $EVENT->{ $row->{id} } ) {
|
1281
|
|
|
|
|
|
|
$w->entryconfigure($path, -image => $pics{'icon_document_event'});
|
1282
|
|
|
|
|
|
|
}
|
1283
|
|
|
|
|
|
|
},
|
1284
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
=head2 -opencmd => sub{ ... }
|
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
Callback on TreeWidget if this entry activate(from User or Automatic) to open.
|
1288
|
|
|
|
|
|
|
if this return false, then Tree doesn't refresh the tree.
|
1289
|
|
|
|
|
|
|
i.E.
|
1290
|
|
|
|
|
|
|
-opencmd => sub{ &display_prj_items( @_ ) }, |
1291
|
|
|
|
|
|
|
|
1292
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
=head2 -closecmd => sub{ ... }
|
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
Callback on TreeWidget if this entry activate(from User or Automatic) to close.
|
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
|
1298
|
|
|
|
|
|
|
=head1 ADVERTISED WIDGETS
|
1299
|
|
|
|
|
|
|
|
1300
|
|
|
|
|
|
|
=head2 'tree' => Tree-Widget
|
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
This is a normal Tree widget. I.e.:
|
1303
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
$DBITree->Subwidget('tree')->configure(
|
1305
|
|
|
|
|
|
|
-background => 'gray50',
|
1306
|
|
|
|
|
|
|
};
|
1307
|
|
|
|
|
|
|
|
1308
|
|
|
|
|
|
|
=head2 'HB_' => ResizeButton-Widget
|
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
This is a (Resize)Button widget.
|
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
=head1 CHANGES
|
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
$Log: Tree.pm,v $ |
1315
|
|
|
|
|
|
|
Revision 1.2 2003/11/06 17:55:56 xpix |
1316
|
|
|
|
|
|
|
! bugfixes in refresh_id |
1317
|
|
|
|
|
|
|
* not hudge load for tree |
1318
|
|
|
|
|
|
|
|
1319
|
|
|
|
|
|
|
Revision 1.1 2003/10/24 10:46:28 xpix |
1320
|
|
|
|
|
|
|
* new Name for CPAN |
1321
|
|
|
|
|
|
|
* new Parser for tree, at ths time is possible only read a one Tree |
1322
|
|
|
|
|
|
|
|
1323
|
|
|
|
|
|
|
!! new cvs name !!
|
1324
|
|
|
|
|
|
|
|
1325
|
|
|
|
|
|
|
Revision 1.11 2003/08/13 12:58:13 xpix |
1326
|
|
|
|
|
|
|
* colored debug output |
1327
|
|
|
|
|
|
|
* new method childs, output an array with complete paths from childs |
1328
|
|
|
|
|
|
|
* new methods neu, move, dele to transfering from entrys |
1329
|
|
|
|
|
|
|
* new option maxchars |
1330
|
|
|
|
|
|
|
! many, many bug fixes |
1331
|
|
|
|
|
|
|
|
1332
|
|
|
|
|
|
|
Revision 1.8 2003/07/18 16:14:15 xpix |
1333
|
|
|
|
|
|
|
! Fehler im Table_is_Change algo, fix |
1334
|
|
|
|
|
|
|
! Komplett refresh bei TreeStatusaenderung |
1335
|
|
|
|
|
|
|
! to_parent_open macht jetzt wirklich nur die Vaeter und nicht noch den Sohn auf ;-) |
1336
|
|
|
|
|
|
|
! unit. value in Form.pm |
1337
|
|
|
|
|
|
|
|
1338
|
|
|
|
|
|
|
Revision 1.10 2003/07/17 14:59:54 xpix |
1339
|
|
|
|
|
|
|
! many little bugfixes |
1340
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
Revision 1.3 2003/06/24 16:38:44 xpix |
1342
|
|
|
|
|
|
|
* add symbolic to cvs |
1343
|
|
|
|
|
|
|
* new loking mechanism in Form.pm |
1344
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
Revision 1.9 2003/06/23 16:15:22 xpix |
1346
|
|
|
|
|
|
|
! cvs error |
1347
|
|
|
|
|
|
|
|
1348
|
|
|
|
|
|
|
Revision 1.8 2003/06/18 15:31:47 xpix |
1349
|
|
|
|
|
|
|
* new methods: copy, move, neu ... dele. This will work only on the Tree Widget (not in table) |
1350
|
|
|
|
|
|
|
* change a little bit the docu |
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
Revision 1.7 2003/06/16 12:58:01 xpix |
1353
|
|
|
|
|
|
|
! No Error, if the id ot exists in selct_entrys |
1354
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
Revision 1.6 2003/05/23 13:47:46 xpix |
1356
|
|
|
|
|
|
|
! No debug if debug = 0 |
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
Revision 1.5 2003/05/20 13:51:50 xpix |
1359
|
|
|
|
|
|
|
* add field parent_id to data entry |
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
Revision 1.4 2003/05/11 16:33:47 xpix |
1362
|
|
|
|
|
|
|
* new option -colNames |
1363
|
|
|
|
|
|
|
* new option -entry_create_cb |
1364
|
|
|
|
|
|
|
* new option -higlight |
1365
|
|
|
|
|
|
|
* new option -normal |
1366
|
|
|
|
|
|
|
* new method info |
1367
|
|
|
|
|
|
|
* new method infozoom |
1368
|
|
|
|
|
|
|
* new method color_all |
1369
|
|
|
|
|
|
|
* new method get_id |
1370
|
|
|
|
|
|
|
! much bugfixes |
1371
|
|
|
|
|
|
|
* better select_entrys (without pathinformation) |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
Revision 1.3 2003/05/05 16:02:06 xpix |
1374
|
|
|
|
|
|
|
* correct the documentation and write a little more ;-) |
1375
|
|
|
|
|
|
|
|
1376
|
|
|
|
|
|
|
Revision 1.2 2003/05/04 23:38:25 xpix
|
1377
|
|
|
|
|
|
|
! bug in make_tree_list
|
1378
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
Revision 1.1 2003/05/04 20:52:13 xpix
|
1380
|
|
|
|
|
|
|
* New Widget for display a table in a tree
|
1381
|
|
|
|
|
|
|
|
1382
|
|
|
|
|
|
|
=head1 AUTHOR
|
1383
|
|
|
|
|
|
|
|
1384
|
|
|
|
|
|
|
Copyright (C) 2003 , Frank (xpix) Herrmann. All rights reserved.
|
1385
|
|
|
|
|
|
|
|
1386
|
|
|
|
|
|
|
http://www.xpix.de
|
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|