manqod 1.1505.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/manqod +309 -0
- data/doc/HOWTOS +11 -0
- data/doc/INSTALL +6 -0
- data/doc/LICENCE +450 -0
- data/doc/README +33 -0
- data/doc/benchmarkings/ListLoader.rb +177 -0
- data/doc/manqod.png +0 -0
- data/doc/manqod.svg +99 -0
- data/doc/server.conf.example +24 -0
- data/lib/About.rb +93 -0
- data/lib/BarMenu/BarMenuItem.rb +46 -0
- data/lib/BarMenu.rb +76 -0
- data/lib/ButtonMenu/ButtonMenuItem.rb +82 -0
- data/lib/ButtonMenu/EndSeparator.rb +14 -0
- data/lib/ButtonMenu/StartSeparator.rb +14 -0
- data/lib/ButtonMenu.rb +154 -0
- data/lib/Common/Conf.rb +119 -0
- data/lib/Common/Eprint.rb +180 -0
- data/lib/Common/EventCache.rb +41 -0
- data/lib/Common/Fixnum.rb +18 -0
- data/lib/Common/Images.rb +41 -0
- data/lib/Common/ManqodDB.rb +40 -0
- data/lib/Common/MyExec.rb +77 -0
- data/lib/Common/MyImage.rb +47 -0
- data/lib/Common/Nick.rb +25 -0
- data/lib/Common/String.rb +15 -0
- data/lib/FormHolder/Form/InputHolder/Button.rb +133 -0
- data/lib/FormHolder/Form/InputHolder/Calendar.rb +101 -0
- data/lib/FormHolder/Form/InputHolder/CalendarButton.rb +117 -0
- data/lib/FormHolder/Form/InputHolder/ColorButton.rb +54 -0
- data/lib/FormHolder/Form/InputHolder/Combo.rb +82 -0
- data/lib/FormHolder/Form/InputHolder/ComboWithNew.rb +103 -0
- data/lib/FormHolder/Form/InputHolder/Common/Model.rb +337 -0
- data/lib/FormHolder/Form/InputHolder/ConstCombo.rb +18 -0
- data/lib/FormHolder/Form/InputHolder/ConstText.rb +17 -0
- data/lib/FormHolder/Form/InputHolder/Duration.rb +73 -0
- data/lib/FormHolder/Form/InputHolder/EditableList.rb +57 -0
- data/lib/FormHolder/Form/InputHolder/FieldCombo.rb +40 -0
- data/lib/FormHolder/Form/InputHolder/FieldList.rb +40 -0
- data/lib/FormHolder/Form/InputHolder/FileChooser.rb +131 -0
- data/lib/FormHolder/Form/InputHolder/FontButton.rb +37 -0
- data/lib/FormHolder/Form/InputHolder/FormImage.rb +74 -0
- data/lib/FormHolder/Form/InputHolder/HScale.rb +44 -0
- data/lib/FormHolder/Form/InputHolder/Hidden.rb +41 -0
- data/lib/FormHolder/Form/InputHolder/Label.rb +40 -0
- data/lib/FormHolder/Form/InputHolder/List.rb +176 -0
- data/lib/FormHolder/Form/InputHolder/MultiLine.rb +63 -0
- data/lib/FormHolder/Form/InputHolder/Password.rb +41 -0
- data/lib/FormHolder/Form/InputHolder/QBuilder/QObject.rb +269 -0
- data/lib/FormHolder/Form/InputHolder/QBuilder.rb +333 -0
- data/lib/FormHolder/Form/InputHolder/RadioGroup.rb +82 -0
- data/lib/FormHolder/Form/InputHolder/SourceView.rb +100 -0
- data/lib/FormHolder/Form/InputHolder/Spin.rb +49 -0
- data/lib/FormHolder/Form/InputHolder/Text.rb +55 -0
- data/lib/FormHolder/Form/InputHolder/TimeStamp.rb +82 -0
- data/lib/FormHolder/Form/InputHolder/TimeStampButton.rb +93 -0
- data/lib/FormHolder/Form/InputHolder/Toggle.rb +43 -0
- data/lib/FormHolder/Form/InputHolder.rb +458 -0
- data/lib/FormHolder/Form.rb +529 -0
- data/lib/FormHolder.rb +203 -0
- data/lib/Gtk.rb +101 -0
- data/lib/GtkAttributes.rb +76 -0
- data/lib/Kernel.rb +48 -0
- data/lib/ListHolder/EditableList/CellRenderers/Combo.rb +91 -0
- data/lib/ListHolder/EditableList/CellRenderers/ComboText.rb +22 -0
- data/lib/ListHolder/EditableList/CellRenderers/ConstCombo.rb +12 -0
- data/lib/ListHolder/EditableList/CellRenderers/ConstText.rb +23 -0
- data/lib/ListHolder/EditableList/CellRenderers/Pixbuf.rb +18 -0
- data/lib/ListHolder/EditableList/CellRenderers/Progress.rb +36 -0
- data/lib/ListHolder/EditableList/CellRenderers/Text.rb +51 -0
- data/lib/ListHolder/EditableList/CellRenderers/Toggle.rb +35 -0
- data/lib/ListHolder/EditableList/Column.rb +223 -0
- data/lib/ListHolder/EditableList/DrbListModel.rb +809 -0
- data/lib/ListHolder/EditableList/ListPrintOperation/ColumnsHeaderLayout.rb +56 -0
- data/lib/ListHolder/EditableList/ListPrintOperation/CustomPageSetup.rb +100 -0
- data/lib/ListHolder/EditableList/ListPrintOperation/FooterLayout.rb +26 -0
- data/lib/ListHolder/EditableList/ListPrintOperation/HeaderLayout.rb +35 -0
- data/lib/ListHolder/EditableList/ListPrintOperation/IterLayout.rb +89 -0
- data/lib/ListHolder/EditableList/ListPrintOperation.rb +365 -0
- data/lib/ListHolder/EditableList.rb +309 -0
- data/lib/ListHolder/GanttHolder/Gantt/Rectangle.rb +290 -0
- data/lib/ListHolder/GanttHolder/Gantt.rb +317 -0
- data/lib/ListHolder/GanttHolder/GanttFooter.rb +27 -0
- data/lib/ListHolder/GanttHolder/GanttScaler.rb +60 -0
- data/lib/ListHolder/GanttHolder.rb +31 -0
- data/lib/ListHolder/HistoryWindow.rb +63 -0
- data/lib/ListHolder/ListButtonHolder/ArchiveButton.rb +37 -0
- data/lib/ListHolder/ListButtonHolder/ButtonGroup.rb +32 -0
- data/lib/ListHolder/ListButtonHolder/FilterButton.rb +28 -0
- data/lib/ListHolder/ListButtonHolder/ListButton.rb +305 -0
- data/lib/ListHolder/ListButtonHolder/OrderingButton.rb +26 -0
- data/lib/ListHolder/ListButtonHolder/SumPanelButton.rb +23 -0
- data/lib/ListHolder/ListButtonHolder.rb +94 -0
- data/lib/ListHolder/ListPanel/ListFilter/FRenderer/Combo.rb +94 -0
- data/lib/ListHolder/ListPanel/ListFilter/FRenderer/ConstCombo.rb +11 -0
- data/lib/ListHolder/ListPanel/ListFilter/FRenderer/Text.rb +26 -0
- data/lib/ListHolder/ListPanel/ListFilter/FRenderer/Toggle.rb +41 -0
- data/lib/ListHolder/ListPanel/ListFilter/FRenderer.rb +58 -0
- data/lib/ListHolder/ListPanel/ListFilter.rb +42 -0
- data/lib/ListHolder/ListPanel/ListSum/Text.rb +32 -0
- data/lib/ListHolder/ListPanel/ListSum.rb +72 -0
- data/lib/ListHolder/ListPanel.rb +60 -0
- data/lib/ListHolder.rb +241 -0
- data/lib/LoginWindow.rb +77 -0
- data/lib/MainRouter.rb +64 -0
- data/lib/ManqodCommon.rb +295 -0
- data/lib/ManqodHelp/FormatEditor/FormatJustificationWidget.rb +76 -0
- data/lib/ManqodHelp/FormatsEditor.rb +139 -0
- data/lib/ManqodHelp/HelpBrowser/FormatTagTable/FormatTag.rb +84 -0
- data/lib/ManqodHelp/HelpBrowser/FormatTagTable.rb +39 -0
- data/lib/ManqodHelp/HelpBrowser.rb +135 -0
- data/lib/ManqodHelp/HelpIndex.rb +62 -0
- data/lib/ManqodHelp/HelpToolbar.rb +16 -0
- data/lib/ManqodHelp.rb +120 -0
- data/lib/ManqodRPC.rb +37 -0
- data/lib/Memcache.rb +82 -0
- data/lib/MyConfig.rb +93 -0
- data/lib/Print/PrintItem/TextLayout.rb +47 -0
- data/lib/Print/PrintItem.rb +240 -0
- data/lib/Print.rb +199 -0
- data/lib/PrintEditor/ItemInfo/ItemImage.rb +30 -0
- data/lib/PrintEditor/ItemInfo/ItemList.rb +44 -0
- data/lib/PrintEditor/ItemInfo/ItemTextAlignment.rb +27 -0
- data/lib/PrintEditor/ItemInfo.rb +129 -0
- data/lib/PrintEditor/PageLayout.rb +91 -0
- data/lib/PrintEditor/PrintEditorItem.rb +310 -0
- data/lib/PrintEditor.rb +195 -0
- data/lib/RelationBuilder/RTable/RField.rb +91 -0
- data/lib/RelationBuilder/RTable.rb +293 -0
- data/lib/RelationBuilder/Relation/RelationHandle.rb +70 -0
- data/lib/RelationBuilder/Relation.rb +161 -0
- data/lib/RelationBuilder/RunQuery.rb +55 -0
- data/lib/RelationBuilder/SearchWindow.rb +72 -0
- data/lib/RelationBuilder.rb +468 -0
- data/lib/SB/ListProgress.rb +150 -0
- data/lib/SB/Messaging.rb +77 -0
- data/lib/SB.rb +29 -0
- data/lib/mynotebook.rb +131 -0
- data/lib/mytouchwindow.rb +162 -0
- data/lib/mywindow.rb +134 -0
- data/lib/wysiwyg-print-label.rb +57 -0
- metadata +231 -0
@@ -0,0 +1,317 @@
|
|
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 Gantt < Gtk::Viewport
|
6
|
+
include ManqodCommon
|
7
|
+
#seconds/pixel,scale point distance, time_format, day0_format, name
|
8
|
+
Resolution={1=>[10,3*60,"%d %b\n%H:%M","day {%j}\n%H:%M","10 seconds/pixel (17 min/inch)"],
|
9
|
+
2=>[60,200,"%d %b\n%H:%M","day {%j}\n%H:%M","1 minute/pixel (95 min/inch)"],
|
10
|
+
3=>[60*10,200,"%d %b\n%H:%M","day {%j}\n%H:%M","10 minutes/pixel (16 hours/inch)"],
|
11
|
+
4=>[60*30,200,"%d %b\n%H:%M","day {%j}\n%H:%M","30 minutes/pixel (2 days/inch)"],
|
12
|
+
5=>[60*60,24*10,"%Y %b %d","day {%j}\n%H:%M","1 hour/pixel (4 days/inch)"],
|
13
|
+
6=>[60*60*2,2*24*10,"%Y %b %d","day {%j}\n%H:%M","2 hour/pixel (8 days/inch)"],
|
14
|
+
7=>[60*60*4,4*24*10,"%Y %b %d","day {%j}\n%H:%M","4 hour/pixel (16 days/inch)"],
|
15
|
+
8=>[60*60*6,4*24*10,"%Y %b %d","day {%j}\n%H:%M","6 hour/pixel (24 days/inch)"],
|
16
|
+
9=>[60*60*8,4*24*10,"%Y %b %d","day {%j}\n%H:%M","8 hour/pixel (32 days/inch)"],
|
17
|
+
10=>[60*60*12,4*24*10,"%Y %b %d","day {%j}\n%H:%M","12 hour/pixel (48 days/inch)"],
|
18
|
+
11=>[60*60*24,4*24*10,"%Y %b %d","day {%j} %H:%M","1 day/pixel (96 days/inch)"]
|
19
|
+
}
|
20
|
+
|
21
|
+
None = 0
|
22
|
+
Moving = 1
|
23
|
+
Connecting = 2
|
24
|
+
Scrolling = 3
|
25
|
+
def initialize(gantt_holder)
|
26
|
+
@gantt_holder=gantt_holder
|
27
|
+
#hold start and end points here for which Scaler will need to draw header
|
28
|
+
@points=Array.new
|
29
|
+
@rectangles=Hash.new
|
30
|
+
#time interval/pixel
|
31
|
+
@min_time=0
|
32
|
+
@res_idx=(list.gtk_attribute("gantt_res_idx") || '2').to_i
|
33
|
+
@day0=(list.gtk_attribute("gantt_day0") || 'false') == 'true'
|
34
|
+
@scaler_format=if @day0 then list.gtk_attribute("gantt_day0_header_format") || "%d %b\n%H:%M"
|
35
|
+
else list.gtk_attribute("gantt_header_format") || "%d %b\n%H:%M" end
|
36
|
+
@time_format=list.gtk_attribute("gantt_time_format") || "%H:%M"
|
37
|
+
|
38
|
+
super(Gtk::Adjustment.new(0,0,0,0,0,0),list.holder.list_scroller.vadjustment)
|
39
|
+
set_resize_mode(Gtk::RESIZE_PARENT)
|
40
|
+
add(Gtk::EventBox.new.add(@widget=Gtk::Fixed.new))
|
41
|
+
|
42
|
+
child.signal_connect("scroll-event"){|me,ev|
|
43
|
+
zoom_in if ev.direction == Gdk::EventScroll::UP && ev.state.control_mask?
|
44
|
+
zoom_out if ev.direction == Gdk::EventScroll::DOWN && ev.state.control_mask?
|
45
|
+
}
|
46
|
+
child.signal_connect("button-press-event"){|me,ev|
|
47
|
+
case ev.button
|
48
|
+
#right button dragging: editing successors/predecessors
|
49
|
+
when 3 then
|
50
|
+
unless (@successors_column && successors_editable)
|
51
|
+
ewarn("no editable successors_column specified?")
|
52
|
+
else
|
53
|
+
if @start=rectangle?(ev.x,ev.y)
|
54
|
+
#double
|
55
|
+
# if ev.event_type == Gdk::Event::BUTTON2_PRESS
|
56
|
+
# @start.set_new_successors(nil)
|
57
|
+
# else
|
58
|
+
@state = Connecting
|
59
|
+
window.set_cursor(Gdk::Cursor.new(Gdk::Cursor::CROSS))
|
60
|
+
# end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
#left click: moving
|
64
|
+
when 1 then
|
65
|
+
@start=rectangle?(ev.x,ev.y)
|
66
|
+
if start_editable && !@start.nil? && !@start.has_child?
|
67
|
+
@state = Moving
|
68
|
+
@move_shift=ev.x-@start.x1
|
69
|
+
window.set_cursor(Gdk::Cursor.new(Gdk::Cursor::HAND2))
|
70
|
+
end
|
71
|
+
#middle click: panning
|
72
|
+
when 2 then
|
73
|
+
@state = Scrolling
|
74
|
+
@scroll_x=ev.x
|
75
|
+
@scroll_y=ev.y
|
76
|
+
window.set_cursor(Gdk::Cursor.new(Gdk::Cursor::HAND1))
|
77
|
+
end
|
78
|
+
clear
|
79
|
+
# gantt_holder.scaler.clear
|
80
|
+
false
|
81
|
+
}
|
82
|
+
child.signal_connect("button-release-event"){|me,ev|
|
83
|
+
case @state
|
84
|
+
when Connecting
|
85
|
+
@motion=nil
|
86
|
+
@end=rectangle?(ev.x,ev.y)
|
87
|
+
@start.toggle_successor(@end)
|
88
|
+
when Moving
|
89
|
+
#moving finished
|
90
|
+
@start.move_to(hadjustment.value+self.pointer[0]-@move_shift,true)
|
91
|
+
@motion=nil
|
92
|
+
when Scrolling
|
93
|
+
end
|
94
|
+
window.set_cursor(nil)
|
95
|
+
@state = None
|
96
|
+
clear
|
97
|
+
false
|
98
|
+
}
|
99
|
+
child.signal_connect("motion-notify-event"){|me,ev|
|
100
|
+
case @state
|
101
|
+
when Connecting then
|
102
|
+
@motion=[ev.x,ev.y]
|
103
|
+
clear
|
104
|
+
when Moving then
|
105
|
+
@start.move_to(hadjustment.value+self.pointer[0]-@move_shift)
|
106
|
+
@motion=[ev.x,ev.y]
|
107
|
+
clear
|
108
|
+
when Scrolling then
|
109
|
+
px=@scroll_x - self.pointer[0]
|
110
|
+
py=@scroll_y - self.pointer[1]
|
111
|
+
px=hadjustment.lower if px < hadjustment.lower
|
112
|
+
py=vadjustment.lower if py < hadjustment.lower
|
113
|
+
px=hadjustment.upper - hadjustment.page_size if px > hadjustment.upper - hadjustment.page_size
|
114
|
+
py=vadjustment.upper - vadjustment.page_size if py > vadjustment.upper - vadjustment.page_size
|
115
|
+
hadjustment.value=px
|
116
|
+
vadjustment.value=py
|
117
|
+
clear
|
118
|
+
end
|
119
|
+
}
|
120
|
+
#set footer height
|
121
|
+
list.holder.signal_connect("size-allocate"){|me,alloc|
|
122
|
+
h=list.holder.buttonholder.holder.allocation.height
|
123
|
+
h+=list.holder.list_panel.allocation.height if list.holder.list_panel.visibility
|
124
|
+
gantt_holder.footer.set_height_request(h) unless gantt_holder.footer.destroyed?
|
125
|
+
false
|
126
|
+
}
|
127
|
+
#set gantt height
|
128
|
+
list.holder.list_scroller.vadjustment.signal_connect("changed"){|vad|
|
129
|
+
@widget.set_height_request(vad.upper) unless @widget.destroyed?
|
130
|
+
false
|
131
|
+
}
|
132
|
+
@widget.signal_connect("expose-event"){|me,ev|
|
133
|
+
cr=me.window.create_cairo_context.set_line_cap(Cairo::LineCap::ROUND)
|
134
|
+
@rectangles.each{|rid,r|
|
135
|
+
#draw rectangles, hilight the hovered on connecting
|
136
|
+
r.draw(cr,(@start == r) || (@end == r) || (@motion && r.in_area?(@motion[0],@motion[1])))
|
137
|
+
}
|
138
|
+
#draw arrows,verticals
|
139
|
+
@rectangles.each{|rid,r|
|
140
|
+
r.draw_arrow(cr).draw_verticals(cr)
|
141
|
+
r.draw_hilight(cr) if @cursor_id == rid
|
142
|
+
}
|
143
|
+
#printing percentages
|
144
|
+
@rectangles.each{|rid,r|
|
145
|
+
r.print_percentage(cr)
|
146
|
+
} if percentage_column
|
147
|
+
#draw connecting line
|
148
|
+
if @start && @state == Connecting && @motion
|
149
|
+
cr.set_line_width(3).set_source_rgba(148.0/255,88.0/255,116.0/255,0.5).set_dash(100000)
|
150
|
+
cr.move_to(@start.x,@start.y)
|
151
|
+
cr.line_to(@motion[0],@motion[1])
|
152
|
+
cr.stroke
|
153
|
+
end
|
154
|
+
}
|
155
|
+
signal_connect("destroy"){|me|
|
156
|
+
list.delete_observer(self)
|
157
|
+
}
|
158
|
+
end
|
159
|
+
attr_reader :widget
|
160
|
+
attr_reader :gantt_holder, :res_idx, :min_time, :max_time, :points, :cursor_id
|
161
|
+
attr_reader :start_column, :dur_column, :successors_column, :day0, :group_column, :group_color_column, :partial_column, :percentage_column
|
162
|
+
attr_reader :start_editable, :successors_editable, :rectangles
|
163
|
+
attr_reader :scaler_format, :time_format
|
164
|
+
|
165
|
+
def update(notifier)
|
166
|
+
if list.model && model && list.list_model.column_of_gantt_start && list.list_model.column_of_gantt_duration
|
167
|
+
@start_column=list.list_model.column_of_gantt_start["model_col"].to_i if list.list_model.column_of_gantt_start
|
168
|
+
@start_editable=list.list_model.column_of_gantt_start["editable"]=="true" if list.list_model.column_of_gantt_start
|
169
|
+
@dur_column=list.list_model.column_of_gantt_duration["model_col"].to_i if list.list_model.column_of_gantt_duration
|
170
|
+
@successors_column=list.list_model.column_of_gantt_successors["model_col"].to_i if list.list_model.column_of_gantt_successors
|
171
|
+
@successors_editable=list.list_model.column_of_gantt_successors["editable"]=="true" if list.list_model.column_of_gantt_successors
|
172
|
+
@group_column=list.list_model.column_of_gantt_group["model_col"].to_i if list.list_model.column_of_gantt_group
|
173
|
+
@partial_column=list.list_model.column_of_gantt_partial["model_col"].to_i if list.list_model.column_of_gantt_partial
|
174
|
+
@group_color_column=list.list_model.column_of_gantt_group_color["model_col"].to_i if list.list_model.column_of_gantt_group_color
|
175
|
+
@percentage_column=list.list_model.column_of_gantt_percentage["model_col"].to_i if list.list_model.column_of_gantt_percentage
|
176
|
+
#set up rectangles
|
177
|
+
@rectangles.clear
|
178
|
+
create_rectangle(model.iter_first)
|
179
|
+
#visible iters
|
180
|
+
gmin=gmax=nil
|
181
|
+
@rectangles.each_value{|r|
|
182
|
+
#initialize gmin,gmax
|
183
|
+
gmin=gmax=r.x1 if gmin.nil?
|
184
|
+
gmin=r.x1-scale_res if gmin>r.x1-scale_res
|
185
|
+
gmax=r.x2+scale_res if gmax<r.x2+scale_res
|
186
|
+
}
|
187
|
+
|
188
|
+
@points.clear
|
189
|
+
@min_time=if day0 then 0 else gmin||0 end
|
190
|
+
@max_time=gmax||0
|
191
|
+
#set our maximum width
|
192
|
+
@widget.set_width_request(@max_time-@min_time)# if gmax && @widget.allocation.width < gmax-gmin
|
193
|
+
@cursor_id=list.get_cursor_id
|
194
|
+
@rectangles.each{|rid,r|
|
195
|
+
r.set_gantt_min_x(@min_time)
|
196
|
+
#center on selected
|
197
|
+
hadjustment.clamp_page(r.x1-hadjustment.page_size/3,r.x2+hadjustment.page_size/3) if @cursor_id == rid
|
198
|
+
#set up successors
|
199
|
+
r.init_successors if successors_column
|
200
|
+
#set up scaler points
|
201
|
+
(r.x1-scale_res).step(r.x2+scale_res,scale_res){|i| @points.push(i.divmod(scale_res)[0])}
|
202
|
+
}
|
203
|
+
@points=@points.uniq.sort!
|
204
|
+
|
205
|
+
#redraw
|
206
|
+
gantt_holder.scaler.clear
|
207
|
+
show_all
|
208
|
+
clear
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def create_rectangle(iter,level=0)
|
213
|
+
#crawl the tree recursively and create rectangles
|
214
|
+
vi=!iter.nil?
|
215
|
+
start=nil
|
216
|
+
finish=nil
|
217
|
+
height=nil
|
218
|
+
percent=0
|
219
|
+
dursum=0
|
220
|
+
while vi
|
221
|
+
r=Rectangle.new(self,iter)
|
222
|
+
r.level=level
|
223
|
+
start=r.start if start.nil? || start>r.start
|
224
|
+
finish=r.finish if finish.nil? || finish<r.finish
|
225
|
+
height=r.y1+r.height if height.nil? || height<r.height+r.y1
|
226
|
+
dursum+=r.dur
|
227
|
+
percent+=r.dur.to_f * r.percentage/100.0 #calculate the current complete percentage of r
|
228
|
+
@rectangles[r.iter_id]=r
|
229
|
+
if iter.has_child?
|
230
|
+
starts,finishs,percents,heights=create_rectangle(iter.first_child,level+1)
|
231
|
+
r.set_height(heights-r.y1) unless heights-r.y1 == r.height
|
232
|
+
height=r.y1+r.height if height.nil? || height<r.height+r.y1 #recalc height, since it changes by depth
|
233
|
+
r.set_start(starts,true) unless starts == r.start
|
234
|
+
r.set_duration(finishs-starts,true) unless finishs-starts == r.dur
|
235
|
+
r.set_percentage(percents,true) unless percents == r.percentage
|
236
|
+
end
|
237
|
+
vi=iter.next!
|
238
|
+
end
|
239
|
+
[start,finish,if dursum==0 then 0 else (100.0*percent/dursum).to_i end,height]
|
240
|
+
end
|
241
|
+
|
242
|
+
#check if this rectangle contains the point @ x,y
|
243
|
+
def rectangle?(x,y)
|
244
|
+
found=nil
|
245
|
+
@rectangles.each_value{|r|
|
246
|
+
if r.in_area?(x,y) && (found.nil? || found.level<r.level)
|
247
|
+
found=r
|
248
|
+
end
|
249
|
+
}
|
250
|
+
found
|
251
|
+
end
|
252
|
+
def min_for_rectangle(pr)
|
253
|
+
min=0
|
254
|
+
chmin=0
|
255
|
+
@rectangles.each_value{|r|
|
256
|
+
#by goup items' maximum
|
257
|
+
min=r.finish if group_column && r.group == pr.group && r.start<pr.start && pr.start<r.finish
|
258
|
+
#children's maxmimum
|
259
|
+
r.successors.each{|sid,s| chmin=r.partial_finish if s == pr && r.partial_finish>chmin }
|
260
|
+
}
|
261
|
+
[min,chmin].max
|
262
|
+
end
|
263
|
+
def collisions(pr)
|
264
|
+
cs=Array.new
|
265
|
+
@rectangles.each_value{|r|
|
266
|
+
#by goup items' maximum
|
267
|
+
if group_column && r != pr && r.group == pr.group
|
268
|
+
min=[pr.start,r.start].max
|
269
|
+
max=[pr.start+pr.dur,r.start+r.dur].min
|
270
|
+
cs.push([min,max]) if min<max
|
271
|
+
end
|
272
|
+
}
|
273
|
+
cs
|
274
|
+
end
|
275
|
+
def rectangle_by_id?(rid)
|
276
|
+
@rectangles[rid]
|
277
|
+
end
|
278
|
+
def clear
|
279
|
+
@widget.queue_draw_area(0, 0, @widget.allocation.width, @widget.allocation.height)
|
280
|
+
end
|
281
|
+
def list
|
282
|
+
gantt_holder.list
|
283
|
+
end
|
284
|
+
def model
|
285
|
+
list.list_model.data
|
286
|
+
end
|
287
|
+
def res
|
288
|
+
Resolution[res_idx][0]
|
289
|
+
end
|
290
|
+
def scale_res
|
291
|
+
Resolution[res_idx][1]
|
292
|
+
end
|
293
|
+
def display_time(t)
|
294
|
+
s=Time.at(t).strftime(@time_format)
|
295
|
+
end
|
296
|
+
def res_name
|
297
|
+
Resolution[res_idx][4]
|
298
|
+
end
|
299
|
+
def zoom_in
|
300
|
+
unless @res_idx==1
|
301
|
+
@res_idx-=1
|
302
|
+
gantt_holder.footer.set_res_label
|
303
|
+
update(self)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
def zoom_out
|
307
|
+
unless @res_idx==Resolution.size
|
308
|
+
@res_idx+=1
|
309
|
+
gantt_holder.footer.set_res_label
|
310
|
+
update(self)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
def to_s
|
314
|
+
"Gantt of #{list}"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
@@ -0,0 +1,27 @@
|
|
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 GanttFooter < Gtk::HBox
|
6
|
+
def initialize(gantt_holder)
|
7
|
+
@gantt_holder=gantt_holder
|
8
|
+
super()
|
9
|
+
set_height_request(20)
|
10
|
+
pack_start(zoomer=Gtk::HBox.new,false,false)
|
11
|
+
zoomer.pack_start(zoom_in=Gtk::Button.new.set_image(Gtk::Image.new(Gtk::Stock::ZOOM_IN,Gtk::IconSize::SMALL_TOOLBAR)))
|
12
|
+
zoomer.pack_start(zoom_out=Gtk::Button.new.set_image(Gtk::Image.new(Gtk::Stock::ZOOM_OUT,Gtk::IconSize::SMALL_TOOLBAR)))
|
13
|
+
zoomer.pack_start(@zoom_label=Gtk::Label.new)
|
14
|
+
set_res_label
|
15
|
+
zoom_in.signal_connect("pressed"){|me|
|
16
|
+
gantt_holder.gantt.zoom_in
|
17
|
+
}
|
18
|
+
zoom_out.signal_connect("pressed"){|me|
|
19
|
+
gantt_holder.gantt.zoom_out
|
20
|
+
}
|
21
|
+
end
|
22
|
+
attr_reader :gantt_holder
|
23
|
+
def set_res_label
|
24
|
+
@zoom_label.set_label("resolution:\n#{gantt_holder.gantt.res_name}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,60 @@
|
|
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 GanttScaler < Gtk::Viewport
|
6
|
+
include Conf
|
7
|
+
def initialize(gantt_holder)
|
8
|
+
@gantt_holder=gantt_holder
|
9
|
+
super(gantt.hadjustment,Gtk::Adjustment.new(0,0,0,0,0,0))
|
10
|
+
# set_policy(Gtk::POLICY_NEVER,Gtk::POLICY_NEVER)
|
11
|
+
# add_with_viewport(Gtk::EventBox.new.add(@widget=Gtk::Fixed.new))
|
12
|
+
add(@widget=Gtk::Fixed.new)
|
13
|
+
@widget.set_height_request(20)
|
14
|
+
#set width the same as gantt's
|
15
|
+
gantt.hadjustment.signal_connect("changed"){|vad|
|
16
|
+
@widget.set_width_request(vad.upper)
|
17
|
+
false
|
18
|
+
}
|
19
|
+
#font=get_conf(0,0,"list-cell-font")||"Sans 6"
|
20
|
+
font="Sans 6"
|
21
|
+
@widget.signal_connect("expose-event",font){|me,ev,font|
|
22
|
+
cr=me.window.create_cairo_context
|
23
|
+
pl=cr.create_pango_layout
|
24
|
+
pl.set_font_description(Pango::FontDescription.new(font))#.set_width(@width*Pango::SCALE)
|
25
|
+
pl.set_wrap(Pango::Layout::WRAP_WORD_CHAR).set_ellipsize(Pango::Layout::ELLIPSIZE_NONE)
|
26
|
+
|
27
|
+
unless gantt.points.size == 0
|
28
|
+
start=gantt.scale_res*gantt.points.first
|
29
|
+
|
30
|
+
gantt.points.each{|point|
|
31
|
+
x=point*gantt.scale_res-start
|
32
|
+
cr.set_source_rgba(48.0/255,88.0/255,116.0/255,1)
|
33
|
+
cr.set_line_width(0.5)
|
34
|
+
cr.move_to(x,6)
|
35
|
+
cr.rel_line_to(0,18)
|
36
|
+
cr.stroke
|
37
|
+
|
38
|
+
cr.set_source_rgba(48.0/255,88.0/255,116.0/255,0.8)
|
39
|
+
|
40
|
+
pl.set_text(Time.at((x+gantt.min_time)*gantt.res).strftime(gantt.scaler_format))
|
41
|
+
cr.move_to(x+2,1)
|
42
|
+
cr.show_pango_layout(pl)
|
43
|
+
|
44
|
+
cr.stroke
|
45
|
+
}
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
attr_reader :gantt_holder, :widget
|
50
|
+
def clear
|
51
|
+
@widget.queue_draw_area(0, 0, @widget.allocation.width, @widget.allocation.height)
|
52
|
+
end
|
53
|
+
def gantt
|
54
|
+
gantt_holder.gantt
|
55
|
+
end
|
56
|
+
def to_s
|
57
|
+
"Scaler of #{gantt}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,31 @@
|
|
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 GanttHolder < Gtk::VBox
|
6
|
+
include ManqodCommon
|
7
|
+
|
8
|
+
def initialize(list_holder)
|
9
|
+
@list_holder=list_holder
|
10
|
+
super()
|
11
|
+
|
12
|
+
@gantt=Gantt.new(self)
|
13
|
+
pack_start(@scaler=GanttScaler.new(self),false,false)
|
14
|
+
pack_start(gantt)
|
15
|
+
pack_start(@footer=GanttFooter.new(self),false,false)
|
16
|
+
set_size_request(0,0)
|
17
|
+
|
18
|
+
list.signal_connect("cursor-changed"){|me| @gantt.update(self)}
|
19
|
+
list.signal_connect("size-allocate"){|me,*a| @gantt.update(self)}
|
20
|
+
end
|
21
|
+
attr_reader :scaler, :gantt, :footer
|
22
|
+
|
23
|
+
def update
|
24
|
+
end
|
25
|
+
|
26
|
+
def list
|
27
|
+
@list_holder.list
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,63 @@
|
|
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 HistoryWindow < Gtk::Window
|
6
|
+
def initialize(list_holder)
|
7
|
+
@holder=list_holder
|
8
|
+
@row_id=nil
|
9
|
+
super()
|
10
|
+
set_title('history')
|
11
|
+
set_modal(true)
|
12
|
+
set_transient_for(@holder.get_ancestor(Gtk::Window))
|
13
|
+
set_has_frame(false)
|
14
|
+
set_window_position(Gtk::Window::POS_CENTER_ON_PARENT)
|
15
|
+
set_size_request(600,300)
|
16
|
+
@store=Gtk::TreeStore.new(String,String,String,String,String) #time,nick,operation, header, data
|
17
|
+
add(Gtk::VBox.new)
|
18
|
+
child.pack_start(Gtk::ScrolledWindow.new.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC).add(hview=Gtk::TreeView.new(@store))).
|
19
|
+
pack_start(Gtk::HBox.new.
|
20
|
+
pack_start(prevb=Gtk::Button.new(Gtk::Stock::GO_BACK),false,false).
|
21
|
+
pack_start(nextb=Gtk::Button.new(Gtk::Stock::GO_FORWARD),false,false).
|
22
|
+
pack_start(Gtk::Alignment.new(0,0,0,0),true,true).
|
23
|
+
pack_start(closeb=Gtk::Button.new(Gtk::Stock::CLOSE),false,false),
|
24
|
+
false,false)
|
25
|
+
closeb.signal_connect('clicked'){|me| self.destroy}
|
26
|
+
nextb.signal_connect('clicked'){|me| load_history(@row_id+1)}
|
27
|
+
prevb.signal_connect('clicked'){|me| load_history(@row_id-1)}
|
28
|
+
|
29
|
+
renderer = Gtk::CellRendererText.new
|
30
|
+
hview.append_column(Gtk::TreeViewColumn.new("Time", renderer, :text => 0))
|
31
|
+
hview.append_column(Gtk::TreeViewColumn.new("User", renderer, :text => 1))
|
32
|
+
hview.append_column(op_col=Gtk::TreeViewColumn.new("Operatioin", renderer, :text => 2))
|
33
|
+
hview.append_column(Gtk::TreeViewColumn.new("Field", renderer, :text => 3))
|
34
|
+
hview.append_column(Gtk::TreeViewColumn.new("History", renderer, :text => 4))
|
35
|
+
hview.set_expander_column(op_col).set_enable_tree_lines(true)
|
36
|
+
load_history(@holder.list.get_cursor_id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def load_history(new_row_id)
|
40
|
+
@store.clear
|
41
|
+
@row_id=new_row_id
|
42
|
+
set_title("history for #{@holder.list.list_model.base} ##{@row_id}")
|
43
|
+
last_u=nil
|
44
|
+
piter=nil
|
45
|
+
@holder.admin.rows("select history.*,gtkheaders.header from history left join gtkheaders on gtkheaders.id = history.header_id where base='#{@holder.list.list_model.base}' and row_id='#{@row_id}' order by ctime desc").each{|row|
|
46
|
+
unless last_u == row["ctime"]
|
47
|
+
iter=@store.append(nil)
|
48
|
+
piter=iter
|
49
|
+
last_u=row["ctime"]
|
50
|
+
iter[0]=row["ctime"]
|
51
|
+
iter[1]=row["nick"]
|
52
|
+
iter[2]=row["operation"]
|
53
|
+
end
|
54
|
+
if row["operation"] == "u"
|
55
|
+
iter=@store.append(piter)
|
56
|
+
iter[3]=row["header"]
|
57
|
+
iter[4]=row["data"]
|
58
|
+
end
|
59
|
+
}
|
60
|
+
show_all
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,37 @@
|
|
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
|
+
public
|
6
|
+
class ArchiveButton < Gtk::ToggleButton
|
7
|
+
include Conf
|
8
|
+
def initialize(list_holder)
|
9
|
+
@list_holder=list_holder
|
10
|
+
@auto_update=false
|
11
|
+
super()
|
12
|
+
set_relief(Gtk::ReliefStyle::NONE)
|
13
|
+
set_image(Gtk::Image.new(Gtk::Stock::BOLD,Gtk::IconSize.from_name(get_conf(0,0,"button-size"))))
|
14
|
+
signal_connect('toggled'){|me|
|
15
|
+
me.list_holder.list.list_model.set_show_archive(me.active?)
|
16
|
+
if @auto_update
|
17
|
+
set_conf(list_holder.list.get_id,0,"archive",me.active?.to_s)
|
18
|
+
@list_holder.notebook.lists{|list|
|
19
|
+
list.archive_button.set_active(me.active?)
|
20
|
+
} if @list_holder.notebook
|
21
|
+
@list_holder.list.update(self)
|
22
|
+
end
|
23
|
+
}
|
24
|
+
end
|
25
|
+
attr_accessor :list_holder
|
26
|
+
|
27
|
+
def update
|
28
|
+
@auto_update=false
|
29
|
+
set_no_show_all(@list_holder.list.list_model.archive_key.nil?)
|
30
|
+
set_visible(!@list_holder.list.list_model.archive_key.nil?)
|
31
|
+
set_active(get_conf(@list_holder.list.list_id,0,"archive")=="true")
|
32
|
+
@auto_update=true
|
33
|
+
end
|
34
|
+
def to_s
|
35
|
+
"ArchiveButton of #{@list_holder}"
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
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 ButtonGroup < Gtk::Button
|
6
|
+
include Conf
|
7
|
+
def initialize(holder,group)
|
8
|
+
@holder=holder
|
9
|
+
@group=group
|
10
|
+
super(@group)
|
11
|
+
set_image(Gtk::Image.new(Gtk::Stock::DIRECTORY,Gtk::IconSize.from_name(get_conf(0,0,"button-size"))))
|
12
|
+
set_relief(Gtk::ReliefStyle::NONE)
|
13
|
+
# set_shadow_type(Gtk::SHADOW_NONE)
|
14
|
+
@popup=Gtk::Window.new(Gtk::Window::POPUP).add(@widget=Gtk::VBox.new).set_modal(true).set_has_frame(false).
|
15
|
+
set_transient_for(@holder.list_holder.get_ancestor(Gtk::Window))
|
16
|
+
|
17
|
+
@popup.signal_connect('leave-notify-event'){|me,e| me.hide if e.window == me.window}
|
18
|
+
|
19
|
+
signal_connect('clicked'){|me|
|
20
|
+
x,y=get_ancestor(Gtk::Window).position
|
21
|
+
xd,yd=translate_coordinates(get_ancestor(Gtk::Window),x,y+allocation.height)
|
22
|
+
@popup.move(xd,yd).show_all
|
23
|
+
}
|
24
|
+
end
|
25
|
+
def pack_start(*args)
|
26
|
+
@widget.pack_start(*args)
|
27
|
+
end
|
28
|
+
def update(notifier)
|
29
|
+
@widget.each{|button| button.update(notifier)}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,28 @@
|
|
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
|
+
public
|
6
|
+
class AdvancedFilterButton < Gtk::ToggleButton
|
7
|
+
include Conf
|
8
|
+
def initialize(list_holder)
|
9
|
+
@list_holder=list_holder
|
10
|
+
super()
|
11
|
+
set_relief(Gtk::ReliefStyle::NONE)
|
12
|
+
set_image(Gtk::Image.new(Gtk::Stock::FIND,Gtk::IconSize.from_name(get_conf(0,0,"button-size"))))
|
13
|
+
signal_connect('toggled'){|me|
|
14
|
+
me.list_holder.list_panel.set_visibility
|
15
|
+
set_conf(list_holder.list.get_id,0,"advanced-filter",me.active?.to_s)
|
16
|
+
}
|
17
|
+
end
|
18
|
+
attr_accessor :list_holder
|
19
|
+
|
20
|
+
def update(notifier=nil)
|
21
|
+
#we have fixed ordering, we disable filtering
|
22
|
+
if @list_holder.list.gtk_attribute("ordering")
|
23
|
+
set_conf(list_holder.list.get_id,0,"advanced-filter","false")
|
24
|
+
set_sensitive(false)
|
25
|
+
end
|
26
|
+
set_active(get_conf(list_holder.list.get_id,0,"advanced-filter")=="true")
|
27
|
+
end
|
28
|
+
end
|