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