manqod 1.1505.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/bin/manqod +309 -0
  2. data/doc/HOWTOS +11 -0
  3. data/doc/INSTALL +6 -0
  4. data/doc/LICENCE +450 -0
  5. data/doc/README +33 -0
  6. data/doc/benchmarkings/ListLoader.rb +177 -0
  7. data/doc/manqod.png +0 -0
  8. data/doc/manqod.svg +99 -0
  9. data/doc/server.conf.example +24 -0
  10. data/lib/About.rb +93 -0
  11. data/lib/BarMenu/BarMenuItem.rb +46 -0
  12. data/lib/BarMenu.rb +76 -0
  13. data/lib/ButtonMenu/ButtonMenuItem.rb +82 -0
  14. data/lib/ButtonMenu/EndSeparator.rb +14 -0
  15. data/lib/ButtonMenu/StartSeparator.rb +14 -0
  16. data/lib/ButtonMenu.rb +154 -0
  17. data/lib/Common/Conf.rb +119 -0
  18. data/lib/Common/Eprint.rb +180 -0
  19. data/lib/Common/EventCache.rb +41 -0
  20. data/lib/Common/Fixnum.rb +18 -0
  21. data/lib/Common/Images.rb +41 -0
  22. data/lib/Common/ManqodDB.rb +40 -0
  23. data/lib/Common/MyExec.rb +77 -0
  24. data/lib/Common/MyImage.rb +47 -0
  25. data/lib/Common/Nick.rb +25 -0
  26. data/lib/Common/String.rb +15 -0
  27. data/lib/FormHolder/Form/InputHolder/Button.rb +133 -0
  28. data/lib/FormHolder/Form/InputHolder/Calendar.rb +101 -0
  29. data/lib/FormHolder/Form/InputHolder/CalendarButton.rb +117 -0
  30. data/lib/FormHolder/Form/InputHolder/ColorButton.rb +54 -0
  31. data/lib/FormHolder/Form/InputHolder/Combo.rb +82 -0
  32. data/lib/FormHolder/Form/InputHolder/ComboWithNew.rb +103 -0
  33. data/lib/FormHolder/Form/InputHolder/Common/Model.rb +337 -0
  34. data/lib/FormHolder/Form/InputHolder/ConstCombo.rb +18 -0
  35. data/lib/FormHolder/Form/InputHolder/ConstText.rb +17 -0
  36. data/lib/FormHolder/Form/InputHolder/Duration.rb +73 -0
  37. data/lib/FormHolder/Form/InputHolder/EditableList.rb +57 -0
  38. data/lib/FormHolder/Form/InputHolder/FieldCombo.rb +40 -0
  39. data/lib/FormHolder/Form/InputHolder/FieldList.rb +40 -0
  40. data/lib/FormHolder/Form/InputHolder/FileChooser.rb +131 -0
  41. data/lib/FormHolder/Form/InputHolder/FontButton.rb +37 -0
  42. data/lib/FormHolder/Form/InputHolder/FormImage.rb +74 -0
  43. data/lib/FormHolder/Form/InputHolder/HScale.rb +44 -0
  44. data/lib/FormHolder/Form/InputHolder/Hidden.rb +41 -0
  45. data/lib/FormHolder/Form/InputHolder/Label.rb +40 -0
  46. data/lib/FormHolder/Form/InputHolder/List.rb +176 -0
  47. data/lib/FormHolder/Form/InputHolder/MultiLine.rb +63 -0
  48. data/lib/FormHolder/Form/InputHolder/Password.rb +41 -0
  49. data/lib/FormHolder/Form/InputHolder/QBuilder/QObject.rb +269 -0
  50. data/lib/FormHolder/Form/InputHolder/QBuilder.rb +333 -0
  51. data/lib/FormHolder/Form/InputHolder/RadioGroup.rb +82 -0
  52. data/lib/FormHolder/Form/InputHolder/SourceView.rb +100 -0
  53. data/lib/FormHolder/Form/InputHolder/Spin.rb +49 -0
  54. data/lib/FormHolder/Form/InputHolder/Text.rb +55 -0
  55. data/lib/FormHolder/Form/InputHolder/TimeStamp.rb +82 -0
  56. data/lib/FormHolder/Form/InputHolder/TimeStampButton.rb +93 -0
  57. data/lib/FormHolder/Form/InputHolder/Toggle.rb +43 -0
  58. data/lib/FormHolder/Form/InputHolder.rb +458 -0
  59. data/lib/FormHolder/Form.rb +529 -0
  60. data/lib/FormHolder.rb +203 -0
  61. data/lib/Gtk.rb +101 -0
  62. data/lib/GtkAttributes.rb +76 -0
  63. data/lib/Kernel.rb +48 -0
  64. data/lib/ListHolder/EditableList/CellRenderers/Combo.rb +91 -0
  65. data/lib/ListHolder/EditableList/CellRenderers/ComboText.rb +22 -0
  66. data/lib/ListHolder/EditableList/CellRenderers/ConstCombo.rb +12 -0
  67. data/lib/ListHolder/EditableList/CellRenderers/ConstText.rb +23 -0
  68. data/lib/ListHolder/EditableList/CellRenderers/Pixbuf.rb +18 -0
  69. data/lib/ListHolder/EditableList/CellRenderers/Progress.rb +36 -0
  70. data/lib/ListHolder/EditableList/CellRenderers/Text.rb +51 -0
  71. data/lib/ListHolder/EditableList/CellRenderers/Toggle.rb +35 -0
  72. data/lib/ListHolder/EditableList/Column.rb +223 -0
  73. data/lib/ListHolder/EditableList/DrbListModel.rb +809 -0
  74. data/lib/ListHolder/EditableList/ListPrintOperation/ColumnsHeaderLayout.rb +56 -0
  75. data/lib/ListHolder/EditableList/ListPrintOperation/CustomPageSetup.rb +100 -0
  76. data/lib/ListHolder/EditableList/ListPrintOperation/FooterLayout.rb +26 -0
  77. data/lib/ListHolder/EditableList/ListPrintOperation/HeaderLayout.rb +35 -0
  78. data/lib/ListHolder/EditableList/ListPrintOperation/IterLayout.rb +89 -0
  79. data/lib/ListHolder/EditableList/ListPrintOperation.rb +365 -0
  80. data/lib/ListHolder/EditableList.rb +309 -0
  81. data/lib/ListHolder/GanttHolder/Gantt/Rectangle.rb +290 -0
  82. data/lib/ListHolder/GanttHolder/Gantt.rb +317 -0
  83. data/lib/ListHolder/GanttHolder/GanttFooter.rb +27 -0
  84. data/lib/ListHolder/GanttHolder/GanttScaler.rb +60 -0
  85. data/lib/ListHolder/GanttHolder.rb +31 -0
  86. data/lib/ListHolder/HistoryWindow.rb +63 -0
  87. data/lib/ListHolder/ListButtonHolder/ArchiveButton.rb +37 -0
  88. data/lib/ListHolder/ListButtonHolder/ButtonGroup.rb +32 -0
  89. data/lib/ListHolder/ListButtonHolder/FilterButton.rb +28 -0
  90. data/lib/ListHolder/ListButtonHolder/ListButton.rb +305 -0
  91. data/lib/ListHolder/ListButtonHolder/OrderingButton.rb +26 -0
  92. data/lib/ListHolder/ListButtonHolder/SumPanelButton.rb +23 -0
  93. data/lib/ListHolder/ListButtonHolder.rb +94 -0
  94. data/lib/ListHolder/ListPanel/ListFilter/FRenderer/Combo.rb +94 -0
  95. data/lib/ListHolder/ListPanel/ListFilter/FRenderer/ConstCombo.rb +11 -0
  96. data/lib/ListHolder/ListPanel/ListFilter/FRenderer/Text.rb +26 -0
  97. data/lib/ListHolder/ListPanel/ListFilter/FRenderer/Toggle.rb +41 -0
  98. data/lib/ListHolder/ListPanel/ListFilter/FRenderer.rb +58 -0
  99. data/lib/ListHolder/ListPanel/ListFilter.rb +42 -0
  100. data/lib/ListHolder/ListPanel/ListSum/Text.rb +32 -0
  101. data/lib/ListHolder/ListPanel/ListSum.rb +72 -0
  102. data/lib/ListHolder/ListPanel.rb +60 -0
  103. data/lib/ListHolder.rb +241 -0
  104. data/lib/LoginWindow.rb +77 -0
  105. data/lib/MainRouter.rb +64 -0
  106. data/lib/ManqodCommon.rb +295 -0
  107. data/lib/ManqodHelp/FormatEditor/FormatJustificationWidget.rb +76 -0
  108. data/lib/ManqodHelp/FormatsEditor.rb +139 -0
  109. data/lib/ManqodHelp/HelpBrowser/FormatTagTable/FormatTag.rb +84 -0
  110. data/lib/ManqodHelp/HelpBrowser/FormatTagTable.rb +39 -0
  111. data/lib/ManqodHelp/HelpBrowser.rb +135 -0
  112. data/lib/ManqodHelp/HelpIndex.rb +62 -0
  113. data/lib/ManqodHelp/HelpToolbar.rb +16 -0
  114. data/lib/ManqodHelp.rb +120 -0
  115. data/lib/ManqodRPC.rb +37 -0
  116. data/lib/Memcache.rb +82 -0
  117. data/lib/MyConfig.rb +93 -0
  118. data/lib/Print/PrintItem/TextLayout.rb +47 -0
  119. data/lib/Print/PrintItem.rb +240 -0
  120. data/lib/Print.rb +199 -0
  121. data/lib/PrintEditor/ItemInfo/ItemImage.rb +30 -0
  122. data/lib/PrintEditor/ItemInfo/ItemList.rb +44 -0
  123. data/lib/PrintEditor/ItemInfo/ItemTextAlignment.rb +27 -0
  124. data/lib/PrintEditor/ItemInfo.rb +129 -0
  125. data/lib/PrintEditor/PageLayout.rb +91 -0
  126. data/lib/PrintEditor/PrintEditorItem.rb +310 -0
  127. data/lib/PrintEditor.rb +195 -0
  128. data/lib/RelationBuilder/RTable/RField.rb +91 -0
  129. data/lib/RelationBuilder/RTable.rb +293 -0
  130. data/lib/RelationBuilder/Relation/RelationHandle.rb +70 -0
  131. data/lib/RelationBuilder/Relation.rb +161 -0
  132. data/lib/RelationBuilder/RunQuery.rb +55 -0
  133. data/lib/RelationBuilder/SearchWindow.rb +72 -0
  134. data/lib/RelationBuilder.rb +468 -0
  135. data/lib/SB/ListProgress.rb +150 -0
  136. data/lib/SB/Messaging.rb +77 -0
  137. data/lib/SB.rb +29 -0
  138. data/lib/mynotebook.rb +131 -0
  139. data/lib/mytouchwindow.rb +162 -0
  140. data/lib/mywindow.rb +134 -0
  141. data/lib/wysiwyg-print-label.rb +57 -0
  142. metadata +231 -0
@@ -0,0 +1,809 @@
1
+ #this file is part of manqod
2
+ #manqod is distributed under the CDDL licence
3
+ #the author of manqod is Dobai-Pataky Balint(dpblnt@gmail.com)
4
+
5
+ class ListModel
6
+ include DRbUndumped
7
+ include ManqodCommon
8
+ include Conf
9
+
10
+ def initialize(list)
11
+ @filter=nil
12
+ @data=nil
13
+ @id_index=Hash.new
14
+ @sorter=nil
15
+ @parentselected=nil
16
+ @filtered_rowcount=0
17
+ @rowcount=0
18
+ @rows_loaded=nil
19
+ @show_archive=false
20
+ @list=list
21
+ @remote_model=nil
22
+ @key_parent=nil
23
+ @key_parent2=nil
24
+ @moditem=nil
25
+ @base=nil
26
+ @thread=nil
27
+ @headers=Hash.new
28
+ @headertypes=Array.new
29
+ end
30
+ attr_accessor :filter, :data, :moditem
31
+ attr_reader :rowcount, :rows_loaded, :thread, :sorter
32
+ attr_accessor :filtered_rowcount
33
+ attr_accessor :list, :parentM
34
+ attr_accessor :parentselected
35
+
36
+ attr_reader :column_of_visible, :column_of_id, :column_of_sensitive, :base, :list_key, :column_of_background, :column_of_foreground
37
+ attr_reader :column_of_child_key, :column_of_parent_key, :column_of_child_key2, :column_of_parent_key2
38
+ attr_reader :key_child, :key_parent, :key_child2, :key_parent2
39
+ attr_reader :column_of_gantt_start, :column_of_gantt_duration, :column_of_gantt_successors, :column_of_gantt_group, :column_of_gantt_group_color, :column_of_gantt_partial, :column_of_gantt_percentage
40
+ attr_reader :show_archive, :archive_key
41
+ attr_reader :headers, :headertypes
42
+
43
+
44
+ def drbmodel
45
+ begin
46
+ @remote_model
47
+ rescue =>err
48
+ edebug("error: #{err}\n#{err.backtrace.joint("\n")}\n","list","error")
49
+ end
50
+ end
51
+ def print_iter(iter)
52
+ if iter
53
+ headers.each_value{|h| print h['data'],":",iter[h['model_col']]," "}
54
+ print "\n"
55
+ end
56
+ end
57
+ def resubscribe
58
+ begin
59
+ @remote_model=manqod_db.moditem(get_id)
60
+ drbmodel.subscribe(self)
61
+ rescue =>err
62
+ retry if warn("can't reconnect to server",err.to_s,"list",ERROR,false,true)
63
+ end
64
+ end
65
+ def print_iter_of_id(id_to_print)
66
+ print_iter(iter_of_id(id_to_print))
67
+ end
68
+
69
+ def to_s
70
+ "model of #{list}"
71
+ end
72
+
73
+ def wipe
74
+ begin
75
+ drbmodel.unsubscribe(self) if @remote_model && @remote_model.alive?
76
+ rescue =>err
77
+ eerror("unsubscribing: #{err}","main")
78
+ end
79
+ if @sorter and @sorter.sort_column_id
80
+ edebug("saving model's sortcolumn: #{@sorter.sort_column_id}","config","info")
81
+ set_conf(get_id,0,"sortcolumn",@sorter.sort_column_id[0])
82
+ set_conf(get_id,0,"sortorder",if @sorter.sort_column_id[1]==Gtk::SORT_ASCENDING then "asc" else "desc";end)
83
+ end
84
+ end
85
+
86
+ def get_id
87
+ list.get_id
88
+ end
89
+
90
+ def lock_iter(locked_id)
91
+ counter=0
92
+ begin
93
+ counter+=1
94
+ manqod_db.lock_id_of_base(@base,locked_id)
95
+ rescue =>err
96
+ resubscribe
97
+ if counter==3
98
+ warn("server is gone",err.to_s,"list",ERROR,false,false)
99
+ else
100
+ retry
101
+ end
102
+ end
103
+ end
104
+
105
+ def unlock_iter(unlocked_id)
106
+ counter=0
107
+ begin
108
+ counter+=1
109
+ manqod_db.unlock_id_of_base(@base,unlocked_id)
110
+ rescue =>err
111
+ resubscribe
112
+ if counter==3
113
+ warn("server is gone",err.to_s,"list",ERROR,false,false)
114
+ else
115
+ retry
116
+ end
117
+ end
118
+ end
119
+
120
+ def display_lock(locked_id)
121
+ einfo("display lock called for: #{locked_id}")
122
+ if iter=@id_index[locked_id]
123
+ iter[@column_of_sensitive]=drbmodel.data[locked_id][@column_of_sensitive]
124
+ list.changed
125
+ list.notify_observers(list)
126
+ end
127
+ end
128
+ def locked?(locked_id)
129
+ locked=nil
130
+ if iter=@id_index[locked_id]
131
+ locked=!iter[@column_of_sensitive]
132
+ end
133
+ locked
134
+ end
135
+
136
+ #finds iter by col_num, col_num=colnum number to search for, col_num_data=the data we're looking for
137
+ def data_iter_of_col_num(col_num,col_num_data)
138
+ found_iter=nil
139
+ @data.each{|model,path,iter|
140
+ if iter[col_num]==col_num_data
141
+ found_iter=iter
142
+ break
143
+ end
144
+ }
145
+ found_iter
146
+ end
147
+ def iter_of_id(id_of_iter)
148
+ found_iter=nil
149
+ @sorter.each{|model,path,iter|
150
+ if iter[@column_of_id] == id_of_iter.to_i
151
+ found_iter=iter
152
+ break
153
+ end
154
+ } if @sorter
155
+ found_iter
156
+ end
157
+
158
+ def iter_at_cursor
159
+ iter_of_id(list.get_cursor_id) if list.get_cursor_id
160
+ end
161
+
162
+ def data_of_column(colname,lid=list.get_cursor_id)
163
+ ret=nil
164
+ if di=iter_of_id(lid) and col=headers[colname]
165
+ ret=di[col["model_col"]]
166
+ end
167
+ end
168
+
169
+ def create_skeleton
170
+ unless get_id
171
+ edebug("can't update, no list_id set","list","error")
172
+ return
173
+ end
174
+ # list.progress.pulse(list.get_id)
175
+ # @thread=Thread.new{
176
+ begin
177
+ drbmodel.unsubscribe(self) unless @remote_model.nil?
178
+ rescue => err
179
+ ewarn("server model is gone")
180
+ end
181
+ begin
182
+ @remote_model=manqod_db.moditem(get_id)
183
+ rescue =>err
184
+ eerror(backtrace_to_debug(err),'list')
185
+ if reconnect_manqod_db
186
+ retry
187
+ else
188
+ tell_exception("server is gone")
189
+ end
190
+ end
191
+ @moditem=cache.get("#{get_id}moditem")
192
+ @headers=cache.get("#{get_id}headers")
193
+ @headertypes=cache.get("#{get_id}headertypes")
194
+ moditem_attributes=cache.get("#{get_id}attributes")
195
+ @querysql=moditem_attributes[:querySQL]
196
+ @base=moditem_attributes[:base]
197
+ @list_key=moditem_attributes[:list_key]
198
+ @key_child=moditem_attributes[:child_key]
199
+ @key_parent=moditem_attributes[:parent_key]
200
+
201
+ @key_child2=moditem_attributes[:child_key2]
202
+ @key_parent2=moditem_attributes[:parent_key2]
203
+ @tree_key=moditem_attributes[:tree_key]
204
+ @column_of_id=moditem_attributes[:column_of_id]
205
+ @column_of_visible=moditem_attributes[:column_of_visible]
206
+ @column_of_sensitive=moditem_attributes[:column_of_sensitive]
207
+ @column_of_background=moditem_attributes[:column_of_background]
208
+ @column_of_foreground=moditem_attributes[:column_of_foreground]
209
+ @column_of_archive=moditem_attributes[:column_of_archive]
210
+ @column_of_tree_parent=moditem_attributes[:column_of_tree_parent]
211
+ @column_of_tree=moditem_attributes[:column_of_tree]
212
+ @fetch_filter_key=moditem_attributes[:fetch_filter_key]
213
+ @fetch_filter_value=moditem_attributes[:fetch_filter_value]
214
+ @column_of_fetch_filter=moditem_attributes[:column_of_fetch_filter]
215
+ @archive_key=moditem_attributes[:archive_key]
216
+
217
+ drbmodel.subscribe(self)
218
+
219
+
220
+ @parentM=list.parentM.get_model if list.parentM
221
+
222
+ if @tree_key
223
+ @data = Gtk::TreeStore.new(*headertypes)
224
+ else
225
+ @data = Gtk::ListStore.new(*headertypes)
226
+ end
227
+
228
+ hdebug="#{hdebug}\nheadertypes: #{headertypes.inspect}\nheaders:\n"
229
+
230
+ headers.each_value{|val| hdebug="#{hdebug} #{val['data']} #{val['model_col']}\n"}
231
+ edebug("#{hdebug}","list","debug")
232
+ @column_of_child_key=nil
233
+ if @key_child && headers.has_key?(@key_child)
234
+ @column_of_child_key=headers[@key_child]["model_col"]
235
+ end
236
+ @column_of_child_key2=nil
237
+ if @key_child2 && headers.has_key?(@key_child2)
238
+ @column_of_child_key2=headers[@key_child2]["model_col"]
239
+ end
240
+ #if child_key defined, but parent_key is not, we set parent_key=parentM.list_key
241
+ @key_parent=parentM.list_key if @key_child && @key_parent.nil?
242
+ #if child_key2 defined, but parent_key2 is not, we set parent_key2='id'
243
+ @key_parent2=parentM.list_key if @key_child2 && @key_parent2.nil?
244
+
245
+ @column_of_parent_key=nil
246
+ if @key_parent && parentM && parentM.headers.has_key?(@key_parent)
247
+ @column_of_parent_key=parentM.headers[@key_parent]["model_col"]
248
+ end
249
+ @column_of_parent_key2=nil
250
+ if @key_parent2 && parentM && parentM.headers.has_key?(@key_parent2)
251
+ @column_of_parent_key2=parentM.headers[@key_parent2]["model_col"]
252
+ end
253
+ @filter=Gtk::TreeModelFilter.new(@data)
254
+ @filter.set_visible_column(column_of_visible)
255
+ @sorter=Gtk::TreeModelSort.new(@filter)
256
+ if sortcolumn=get_conf(get_id,0,"sortcolumn") and sortorder=get_conf(get_id,0,"sortorder")
257
+ @sorter.set_sort_column_id(sortcolumn.to_i,sortorder=="asc" ? Gtk::SORT_ASCENDING : Gtk::SORT_DESCENDING)
258
+ end
259
+
260
+ if gantt_start=list.gtk_attribute('gantt_start')
261
+ @column_of_gantt_start=headers[gantt_start]
262
+ end
263
+
264
+ if gantt_duration=list.gtk_attribute('gantt_duration')
265
+ @column_of_gantt_duration=headers[gantt_duration]
266
+ end
267
+ if gantt_successors=list.gtk_attribute('gantt_successors')
268
+ @column_of_gantt_successors=headers[gantt_successors]
269
+ end
270
+ if gantt_group=list.gtk_attribute('gantt_group')
271
+ @column_of_gantt_group=headers[gantt_group]
272
+ end
273
+
274
+ if gantt_group=list.gtk_attribute('gantt_group')
275
+ @column_of_gantt_group=headers[gantt_group]
276
+ end
277
+ if gantt_group_color=list.gtk_attribute('gantt_group_color')
278
+ @column_of_gantt_group_color=headers[gantt_group_color]
279
+ end
280
+ if gantt_partial=list.gtk_attribute('gantt_partial')
281
+ @column_of_gantt_partial=headers[gantt_partial]
282
+ end
283
+ if gantt_percentage=list.gtk_attribute('gantt_percentage')
284
+ @column_of_gantt_percentage=headers[gantt_percentage]
285
+ end
286
+
287
+ list.set_info("created")
288
+ # }
289
+ # @thread.join
290
+ end
291
+
292
+ def update(notifier,ids=nil,notification_subect=nil)
293
+ =begin
294
+ notifier is the notifier object
295
+ ids is the array of ids which should be reloaded/deleted
296
+ notification_subject:
297
+ @column_of: lock/unlock the ids
298
+ "structure": for create_skeleton
299
+ "buttons" : reload the list buttons
300
+ else : load ids
301
+ =end
302
+ before=Time.now
303
+ case notifier.class.name
304
+ when 'BarMenuItem'
305
+ #we're main list, menu is notifying
306
+ load_data(notifier)
307
+ when 'MyEditableList'
308
+ #we're sublist
309
+ unless(@parentselected == notifier.get_cursor_id)
310
+ @parentselected=notifier.get_cursor_id
311
+ @current_parent_key=if @column_of_parent_key and parent_iter=parentM.iter_at_cursor
312
+ parent_iter[@column_of_parent_key]
313
+ end
314
+
315
+ @current_parent_key2=if @column_of_parent_key2 and parent_iter
316
+ parent_iter[@column_of_parent_key2]
317
+ end
318
+ if @key_child.nil? and !parentM.nil?
319
+ tell_exception("[#{self}] add child_key attribute!","list","warning")
320
+ load_data(notifier)
321
+ end
322
+ refilter
323
+ end
324
+ when 'String'
325
+ case notification_subect
326
+ when @column_of_sensitive
327
+ einfo("lock change recieved: #{ids}","list")
328
+ Gtk.thread_protect{display_lock(ids)}
329
+ when "structure"
330
+ einfo("structure change recieved","list")
331
+ Gtk.thread_protect{@list.create_skeleton}
332
+ Gtk.thread_protect{@list.update(self)}
333
+ when "buttons"
334
+ einfo("button change recieved","list")
335
+ Gtk.thread_protect{list.caller.buttonholder.update(list,true)}
336
+ else
337
+ #no subject, we recieved just ids, so reload them
338
+ einfo("load #{ids.inspect} recieved","list")
339
+ Gtk.thread_protect{load_data(notifier,ids)}
340
+ end
341
+ when 'ListModel','ArchiveButton'
342
+ #it's self
343
+ load_data(self)
344
+ else
345
+ ewarn("unknown notifier #{notifier}[#{notifier.class.name}] for list update","list")
346
+ end
347
+ update_time=Time.now.to_f-before.to_f
348
+ edebug("updateed in "+sprintf("%.2fs",update_time),"time","debug")
349
+ end
350
+
351
+ def refilter(one=nil)
352
+ edebug("refiltering #{one}")
353
+ if one.nil?
354
+ list.set_model(nil)
355
+ list.progress.zero(list.object_id,@rowcount,@moditem["display"])
356
+ @thread=Thread.new{
357
+ r=0
358
+ @data.each{|model, path, iter|
359
+ filter_one_iter(iter)
360
+ r+=1
361
+ list.progress.step(list.object_id,r)
362
+ }
363
+ }
364
+ @thread.join
365
+ einfo("refiltered","list")
366
+ list.set_model(@sorter)
367
+ list.progress.done(list.object_id)
368
+ unless list.destroyed?
369
+ list.scroll_to_cursor
370
+ list.update_tip
371
+ list.caller.list_panel.list_sum.calculate
372
+ end
373
+ else
374
+ filter_one_iter(one)
375
+ end
376
+
377
+ #update filtered count
378
+
379
+ @filtered_rowcount=0
380
+ @data.each{|model, path, iter| @filtered_rowcount+=1 if iter[column_of_visible]}
381
+ list.set_info("#{@filtered_rowcount}/#{@rowcount}")
382
+ self
383
+ end
384
+
385
+ def filter_one_iter(iter)
386
+ if @key_child.nil? || (@key_child && iter[@column_of_child_key] == @current_parent_key) || (@key_child2 && iter[@column_of_child_key2] == @current_parent_key2)
387
+ filter_count=0
388
+ filter_hits=0
389
+ list.columns.each{|column|
390
+ fl=get_conf(get_id,column.header["id"],"filter").to_s.upcase
391
+ case column.header['type']
392
+ when 'gtk_combo', 'gtk_const_combo' then fl = (fl=="-1" or fl=="") ? "" : "=#{fl}"
393
+ end
394
+ #if timestamp, then we convert the comparision data to the timestamp format specified by attributes
395
+ comp=case column.header['type']
396
+ when 'gtk_timestamp' then Time.at(iter[column.header["model_col"]]).strftime(column.timestamp_format).upcase
397
+ else iter[column.header["model_col"]].to_s.upcase
398
+ end
399
+
400
+ if fl.length>0
401
+ filter_count=filter_count+1
402
+ filter_hits=filter_hits+
403
+ case column.header['type']
404
+ when 'gtk_int','Integer','gtk_float','gtk_progress','gtk_duration' then
405
+ case fl[0].chr
406
+ when "<" then comp.to_f < fl[1 .. fl.length].to_f ? 1: 0
407
+ when ">" then comp.to_f > fl[1 .. fl.length].to_f ? 1: 0
408
+ when "!" then comp.to_f != fl[1 .. fl.length].to_f ? 1: 0
409
+ when "=" then comp.to_f == fl[1 .. fl.length].to_f ? 1: 0
410
+ else comp.to_f == fl[0 .. fl.length].to_f ? 1: 0
411
+ end
412
+ else
413
+ case fl[0].chr
414
+ when "=" then comp == fl[1 .. fl.length] ? 1: 0
415
+ when "<" then comp < fl[1 .. fl.length] ? 1: 0
416
+ when ">" then comp > fl[1 .. fl.length] ? 1: 0
417
+ when "!" then comp != fl[1 .. fl.length] ? 1: 0
418
+ else comp.index(fl) ? 1: 0
419
+ end
420
+ end
421
+ end
422
+ } unless list.destroyed?
423
+ iter[column_of_visible]=filter_hits == filter_count
424
+ #make sure parent iters are visible, only when we're tree
425
+ unhide_tree_parent_iters(iter) if @column_of_tree && iter[@column_of_visible]
426
+ else
427
+ iter[@column_of_visible]=false
428
+ end
429
+ iter[@column_of_visible]
430
+ end
431
+
432
+ #recursive show parent iters
433
+ def unhide_tree_parent_iters(iter)
434
+ iter[@column_of_visible]=true;
435
+ unhide_tree_parent_iters(iter.parent) if iter.parent
436
+ end
437
+
438
+ def load_data(notifier,ids=nil)
439
+ # @thread=Thread.new{
440
+ ids=[ids] if !ids.nil? and ids.class != Array
441
+ edebug("called for data_load for #{ids.inspect} by #{notifier}","list","info")
442
+ begin
443
+ we_have_server=drbmodel.alive?
444
+ rescue => err
445
+ if reconnect_manqod_db
446
+ retry
447
+ else
448
+ tell_exception("server is gone")
449
+ end
450
+ end
451
+
452
+ return unless we_have_server
453
+
454
+ before=Time.now
455
+ @rows_loaded=0
456
+ @rowcount=drbmodel.rowcount
457
+ ffv=if @fetch_filter_value then eeval(@fetch_filter_value) else nil end
458
+ edebug("fetch-filter: key:#{@fetch_filter_key}, value:#{@fetch_filter_value}=#{ffv}","list")
459
+ if ids.nil?
460
+ list.set_model(nil)
461
+ list.set_info("0")
462
+ @data.clear
463
+ @id_index.clear
464
+ parent_iter=parentM.iter_at_cursor if parentM
465
+ @current_parent_key=if @column_of_parent_key and parent_iter
466
+ parent_iter[@column_of_parent_key]
467
+ end
468
+ @current_parent_key2=if @column_of_parent_key2 and parent_iter
469
+ parent_iter[@column_of_parent_key2]
470
+ end
471
+
472
+ list.progress.zero(list.object_id,0,@moditem["display"])
473
+
474
+ prep_time=Time.now.to_f-before.to_f
475
+ ff=nil
476
+ pkeys=Array.new
477
+ # @thread=Thread.new{
478
+ keys=cache.get("#{@moditem["id"]}[ids]")
479
+ keys.each{|v| pkeys.push("#{@moditem["id"]}[#{v}]")}
480
+ ff=cache.get(pkeys)
481
+ @rowcount=ff ? ff.size : 0
482
+ # }
483
+ # @thread.join
484
+
485
+ # ff=drbmodel.filtered_fetch2(ffv,@show_archive)
486
+ fetch_time=Time.now.to_f-before.to_f
487
+ list.progress.zero(list.object_id,@rowcount,@moditem["display"])
488
+
489
+ pkeys.each{|idx|
490
+ row=ff[idx]
491
+ eerror("row #{idx} is nil!","list") if row.nil?
492
+ # next if !@show_archive && !@column_of_archive.nil? && row[@column_of_archive]
493
+ next unless (@column_of_fetch_filter.nil? || ffv.nil? ||
494
+ (!@fetch_filter_negate &&
495
+ row[@column_of_fetch_filter].to_s == ffv.to_s
496
+ ) ||
497
+ (@fetch_filter_negate && row[@column_of_fetch_filter].to_s != ff_value.to_s)
498
+ ) && row && (@column_of_archive.nil? || (@show_archive || !row[@column_of_archive]))
499
+ #we recieve a row
500
+ iter=if @tree_key then @data.append(@id_index[row[@column_of_tree].to_i]) else @data.append end
501
+ begin
502
+ row.each_pair{|key,val| iter[key]=val}
503
+ rescue =>err
504
+ eerror("filling row: #{err}\n#{key.inspect}=>#{val}\niter:#{iter.inspect}, row:#{row.inspect}","list")
505
+ end
506
+ @id_index[row[@column_of_id].to_i]=iter
507
+ @rows_loaded+=1
508
+ Thread.new{list.progress.step(list.object_id,@rows_loaded)}
509
+ # Thread.pass
510
+
511
+ } unless ff.nil? #nil if no keys found, the list is empty
512
+
513
+ t=Time.new
514
+ refilter
515
+ filtert=Time.new.to_f-t.to_f
516
+ update_time=Time.now.to_f-before.to_f
517
+ enormal("total: #{@filtered_rowcount}/#{@rows_loaded}/#{@rowcount} (p:"+sprintf("%.2fs",prep_time)+",f:"+sprintf("%.2fs",fetch_time)+",refilter:"+sprintf("%.2fs",filtert)+")"+sprintf("%.2fs",update_time),"time")
518
+ einfo("data loaded #{ids or 'all rows'}","list")
519
+ else
520
+ ids.each{|row_id|
521
+ begin
522
+ row=cache.get("#{@moditem["id"]}[#{row_id}]")
523
+ # eerror("row #{row_id} is nil!","list") if row.nil?
524
+ #row=drbmodel.data[row_id]
525
+ if row && (@column_of_fetch_filter.nil? || ffv.nil? ||
526
+ (!@fetch_filter_negate &&
527
+ row[@column_of_fetch_filter].to_s == ffv.to_s
528
+ ) ||
529
+ (@fetch_filter_negate && row[@column_of_fetch_filter].to_s != ff_value.to_s)
530
+ ) && (@column_of_archive.nil? || (@show_archive || !row[@column_of_archive]))
531
+
532
+ piter=@id_index[row[@column_of_tree].to_i]
533
+ if iter=@id_index[row_id]
534
+ #iter is found
535
+ if iter.parent!=piter
536
+ # we remove iter, so we readd it later, thus reparenting it
537
+ parent_iter=iter.parent
538
+ rec_save_childs(iter)
539
+ iter=nil
540
+ need_to_reload=true
541
+ end
542
+ end
543
+ unless iter=@id_index[row_id]
544
+ #new iter
545
+ if @tree_key then
546
+ list.set_model(nil) if !piter.nil? and !piter.has_child?
547
+ iter=@data.append(piter)
548
+ else
549
+ iter=@data.append
550
+ end
551
+ end
552
+
553
+ begin
554
+ row.each_pair{|key,val| iter[key]=val}
555
+ rescue =>err
556
+ edebug("filling one row: #{err}\n iter:#{iter}, row:#{row.inspect}, id:#{row_id}","list","error")
557
+ end
558
+ @id_index[row[@column_of_id].to_i]=iter
559
+ @data.row_changed(iter.path,iter)
560
+ reload_saved_childs if need_to_reload
561
+ refilter(iter)
562
+ else
563
+ #we were called to load_data of a non existing id, which means it's archive and we don't show archive
564
+ if iter_to_remove=@id_index[row_id]
565
+ data.remove(iter_to_remove)
566
+ @id_index.delete(row_id)
567
+ end
568
+ end
569
+ rescue Memcached::NotFound
570
+ eerror("cache not found: id:[#{row_id}]")
571
+ data.remove(iter_to_remove)
572
+ @id_index.delete(row_id)
573
+
574
+ rescue => err
575
+ eerror("#{err}\n\t#{err.backtrace.join("\n\t")}")
576
+ #we were called to load_data of a non existing id, which means it's deleted
577
+ end
578
+ }
579
+ gstart=Time.new
580
+ #list.set_model(@sorter) if list.model.nil?
581
+ gtime=Time.new.to_f-gstart.to_f
582
+ Gtk.thread_protect{list.scroll_to_cursor}
583
+
584
+ update_time=Time.now.to_f-before.to_f
585
+ # edebug("total: #{@filtered_rowcount}/#{@rowcount} "+sprintf("%.2fs",update_time) + +sprintf("%.2fs",gtime),"time","normal")
586
+ edebug("data loaded #{ids.inspect or 'all rows'}","list","info")
587
+ end
588
+
589
+ # }
590
+ end
591
+
592
+ def rec_save_childs(root_iter)
593
+ @childs_to_readd=Array.new if @childs_to_readd.nil?
594
+ if iter=root_iter.first_child
595
+ loop{
596
+ @childs_to_readd.push(iter[column_of_id])
597
+ prev_iter=iter.clone
598
+ finished=!iter.next!
599
+ rec_save_childs(prev_iter)
600
+ break if finished
601
+ }
602
+ end
603
+ @id_index.delete(root_iter[@column_of_id].to_i)
604
+ @data.remove(root_iter)
605
+ end
606
+
607
+ def reload_saved_childs
608
+ load_data(self,@childs_to_readd) if @childs_to_readd.class == Array && @childs_to_readd.size>0
609
+ end
610
+
611
+ def duplicate_iter(iter_to_dup)
612
+ drbmodel.duplicate_iter(iter_to_dup)
613
+ end
614
+
615
+ def remove_iters(iters_to_remove)
616
+ drbmodel.remove_iters(iters_to_remove,nick)
617
+ end
618
+
619
+ def add_iter
620
+ if table=guess_table(@querysql,'id')
621
+ sql="insert into #{table}";
622
+ if @key_child
623
+ sql="#{sql} set #{@key_child}="
624
+ if @key_parent=="id"
625
+ sql="#{sql}'#{parentselected}'"
626
+ else
627
+ if parent_header=parentM.headers[@key_parent] and parent_iter=parentM.iter_at_cursor
628
+ sql="#{sql}'#{parent_iter[parent_header["model_col"]]}'"
629
+ end
630
+ end
631
+ sql="#{sql},#{moditem['additional_on_insert']}" if moditem['additional_on_insert'].length>0
632
+ else
633
+ if lastt=@querysql.index('{parentselected}')
634
+ last=@querysql.rindex('=',lastt)-1
635
+ temp1=@querysql[1 .. last]
636
+ first=temp1.rindex(' ')+1
637
+ sql="#{sql} set "+@querysql[first .. last]+"='#{parentselected}'"
638
+ sql=sql+", "+moditem['additional_on_insert'] if moditem['additional_on_insert'].length>0
639
+ else
640
+ if moditem['additional_on_insert'].length>0
641
+ sql=sql+" set #{moditem['additional_on_insert']}"
642
+ else
643
+ sql="#{sql} () VALUES()";
644
+ end
645
+ end
646
+ end
647
+ end
648
+ query(sql)
649
+ inserted_id=qrow("select id from #{table} order by id desc limit 1")["id"].to_i
650
+ row_modified(inserted_id)
651
+ inserted_id
652
+ end
653
+
654
+ def change_value_of_iter(iter, column_data, new_value)
655
+ sql="update #{@base} set #{column_data}='#{new_value}' where #{@list_key}='#{iter[column_of_id]}' limit 1"
656
+ einfo("changing #{column_data.inspect} to #{new_value.inspect} updatesql: #{sql.inspect}","list")
657
+ query(eeval("\"#{sql}\""))
658
+ row_modified(iter[column_of_id])
659
+ end
660
+
661
+ def change_value_of_id(iter_id, column_data, new_value)
662
+ sql="update #{@base} set #{column_data}='#{new_value}' where #{@list_key}='#{iter_id}' limit 1"
663
+ einfo("changing #{column_data.inspect} to #{new_value.inspect} updatesql: #{sql.inspect}","list")
664
+ query(eeval("\"#{sql}\""))
665
+ row_modified(iter_id)
666
+ end
667
+
668
+ def change_value_of_path(path, column_data, new_value)
669
+ change_value_of_iter(@sorter.get_iter(path), column_data, new_value)
670
+ end
671
+
672
+ def row_modified(modified_id=list.get_cursor_id)
673
+ edebug("row modified #{modified_id.inspect}","list","info")
674
+ drbmodel.rows_changed(modified_id,nick)
675
+ list.set_model(@sorter) if list.model.nil?
676
+ list.scroll_to_cursor
677
+ end
678
+
679
+ def iter2csv(iter)
680
+ row=""
681
+ list.columns.each{|col|
682
+ case col.header["type"]
683
+ when "gtk_const_text" then ct=col.renderer.get_display(iter[col.colnum].to_s)
684
+ when "gtk_const_combo","gtk_combo" then ct=col.renderer.get_text_from_value(iter[col.colnum].to_s)
685
+ else
686
+ ct=case col.data_type.to_s
687
+ when "Integer" then number_format(iter[col.colnum],0)
688
+ when "Float" then number_format(iter[col.colnum],2)
689
+ else iter[col.colnum].to_s
690
+ end
691
+ end
692
+ row="#{row}#{ct.to_s},"
693
+ }
694
+ row="#{row[0..row.length]}\n"
695
+ end
696
+
697
+ def to_csv(filename,ids=nil)
698
+ file = File.new(filename, "wb+")
699
+ ids=Array.new
700
+
701
+ row=""
702
+ list.columns.each{|col|
703
+ row="#{row}#{col.header['header']},"
704
+ }
705
+ file.write("#{row[0..row.length]}\n")
706
+
707
+ if @list.selection.count_selected_rows > 1
708
+ @list.selection.selected_each{|model, path, iter| file.write(iter2csv(iter))}
709
+ else
710
+ @filter.each{|model,path,iter| file.write(iter2csv(iter))}
711
+ end
712
+ file.close
713
+ edebug("saved","list")
714
+ end
715
+
716
+ def from_csv(filename)
717
+ header=true
718
+ ids=Array.new
719
+ IO.foreach(filename){|line|
720
+ row=line.chomp.split(",")
721
+ unless header
722
+ sql="insert into #{base} set"
723
+ comma=false
724
+ #child key auto adding
725
+ if @key_child
726
+ comma=true
727
+ sql="#{sql} #{@key_child}="
728
+ if @key_parent=="id"
729
+ sql="#{sql}'#{parentselected}'"
730
+ else
731
+ if parent_header=parentM.headers[@key_parent] and parent_iter=parentM.iter_at_cursor
732
+ sql="#{sql}'#{parent_iter[parent_header["model_col"]]}'"
733
+ end
734
+ end
735
+ end
736
+ #values
737
+ list.columns.each{|col|
738
+ if c=col.gtk_attribute("csv_column_number")
739
+ sql="#{sql}#{comma ? ",": ""} #{col.header['data']}=\"#{row[c.to_i-1]}\""
740
+ comma=true
741
+ end
742
+ }
743
+ sql="#{sql};" #unless sql.nil?
744
+ sql="#{sql} #{moditem['additional_on_insert']}" if moditem['additional_on_insert'].length>0
745
+ query(sql)
746
+ inserted_id=qrow("select id from #{base} order by id desc limit 1")["id"].to_i
747
+ ids.push(inserted_id)
748
+ end
749
+ header=false
750
+ }
751
+ drbmodel.rows_changed(ids,nick) if ids.size>0
752
+ edebug("csv loaded","list")
753
+ end
754
+
755
+ def set_show_archive(ns)
756
+ @show_archive=ns.to_s == 'true'
757
+ end
758
+
759
+ def prev_sorted_iter(iter)
760
+ pp=iter.path
761
+ if pp.prev!
762
+ @sorter.get_iter(pp)
763
+ end
764
+ end
765
+
766
+ def next_sorted_iter(iter)
767
+ pp=iter.path
768
+ if pp.next!
769
+ @sorter.get_iter(pp)
770
+ end
771
+ end
772
+
773
+ def move_up_id(uid)
774
+ ordering=@list.gtk_attribute("ordering")
775
+ if ordering && (ocolh=headers[ordering]) && (iter=iter_of_id(uid))
776
+ ocol=ocolh["model_col"]
777
+ if prev_iter=prev_sorted_iter(iter) #only if we have previous
778
+ if pprev_iter=prev_sorted_iter(prev_iter)
779
+ #middle of prev and pprev
780
+ change_value_of_iter(iter,ordering,(prev_iter[ocol]+pprev_iter[ocol])/2.0)
781
+ else
782
+ #prev -1
783
+ change_value_of_iter(iter,ordering,prev_iter[ocol]-1)
784
+ end
785
+ end
786
+ end
787
+ end
788
+
789
+ def move_down_id(uid)
790
+ ordering=@list.gtk_attribute("ordering")
791
+ if ordering && (ocolh=headers[ordering]) && (iter=iter_of_id(uid))
792
+ ocol=ocolh["model_col"]
793
+ if next_iter=next_sorted_iter(iter) #only if we have next
794
+ if nnext_iter=next_sorted_iter(next_iter)
795
+ #middle of next and nnext
796
+ change_value_of_iter(iter,ordering,(nnext_iter[ocol]+next_iter[ocol])/2.0)
797
+ else
798
+ #next +1
799
+ change_value_of_iter(iter,ordering,next_iter[ocol]+1)
800
+ end
801
+ end
802
+ end
803
+ end
804
+
805
+ def alive?
806
+ true
807
+ end
808
+ end
809
+