This repository has been archived by the owner on Aug 28, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
group_constraints.rb
270 lines (225 loc) · 7.88 KB
/
group_constraints.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
require 'ttime/constraints'
require 'ttime/gettext_settings'
require 'set'
module TTime
module Constraints
class GroupConstraint < AbstractConstraint
settings_name :group_constraints
default_settings :enabled => true, :forbidden_groups => {}
RIGHT_BUTTON = 3
COLUMNS = [
[ :text, String ],
[ :show_checkbox, TrueClass ],
[ :marked, TrueClass ],
[ :course, String ],
[ :group, Fixnum ],
[ :time, String ],
[ :lecturer, String ],
]
def col_index(column_name)
COLUMNS.each_index do |i|
return i if COLUMNS[i][0] == column_name
end
raise Exception("Column not found")
end
def column_classes
COLUMNS.collect { |col| col[1] }
end
menu_item :mark_this_group, _("Mark this group"), true
def mark_this_group params
group = params[:data][:event].group
course = group.course
course.groups.each do |grp|
if grp.type == group.type
disallow_group course.number, grp.number
end
end
allow_group course.number, group.number
TTime::GUI::MainWindow.instance.reject_events_from_calendar! do |data|
ev = data[:event]
ev.course.number == course.number and \
ev.group.type == group.type and \
ev.group.number != group.number
end
update_forbidden_marks
end
def each_selection_iter(start_at = nil, &block)
block.call start_at if start_at
if start_at
iter = start_at.first_child
if iter
each_selection_iter(iter, &block)
while iter.next!
each_selection_iter iter, &block
end
end
else
iter = @model.iter_first
if iter
each_selection_iter(iter, &block)
while iter.next!
each_selection_iter iter, &block
end
end
end
end
def update_forbidden_marks
each_selection_iter do |iter|
course_number = iter[col_index(:course)]
group_number = iter[col_index(:group)]
iter[col_index(:marked)] = \
!group_is_forbidden?(course_number, group_number)
end
end
def forbidden_groups
return settings[:forbidden_groups]
end
def evaluate_schedule
true
end
def evaluate_group(grp)
return true unless settings[:enabled]
return !(group_is_forbidden?(grp.course.number, grp.number))
end
def name
_('Group Constraints')
end
def allow_group(course_number, group_number)
forbidden_groups[course_number].delete group_number
end
def update_courses(course_list)
@model.clear
for course in course_list
course_iter = @model.append(nil)
course_iter[col_index(:text)] = course.name
for group_type in course.groups.collect { |g| g.type }.uniq
group_type_iter = @model.append(course_iter)
group_type_iter[col_index(:text)] = TTime::Data::GROUP_TYPES[group_type] or group_type
for group in course.groups.select { |g| g.type == group_type }
group_iter = @model.append(group_type_iter)
group_iter[col_index(:text)] = group.number.to_s
group_iter[col_index(:course)] = course.number
group_iter[col_index(:group)] = group.number
group_iter[col_index(:show_checkbox)] = true
group_iter[col_index(:time)] = group.time_as_text
if group.description
group_iter[col_index(:lecturer)] = group.description
else
group_iter[col_index(:lecturer)] = group.lecturer
end
if group_is_forbidden?(course.number, group.number)
group_iter[col_index(:marked)] = false
else
group_iter[col_index(:marked)] = true
end
end
end
end
end
def group_is_forbidden?(course_number, group_number)
return false unless forbidden_groups.include?(course_number)
return forbidden_groups[course_number].include?(group_number)
end
def disallow_group(course_number, group_number)
forbidden_groups[course_number] ||= Set.new
forbidden_groups[course_number].add group_number
end
def recursively_mark iter, marked
args = iter[col_index(:course)], iter[col_index(:group)]
if marked
allow_group *args
else
disallow_group *args
end
iter[col_index(:marked)] = marked
if iter.has_child?
sub_iter = iter.first_child
recursively_mark sub_iter, marked
while sub_iter.next!
recursively_mark sub_iter, marked
end
end
end
def select_all mark_with = true
selection = @treeview.selection
return if selection.nil?
if selection.selected.has_child?
iter = selection.selected
else
iter = selection.selected.parent
end
recursively_mark iter, mark_with
end
def select_none
select_all false
end
def tree_setup
@model = Gtk::TreeStore.new(*column_classes)
@treeview = Gtk::TreeView.new(@model)
@treeview.rules_hint = true
@treeview.selection.mode = Gtk::SELECTION_SINGLE
@treeview.signal_connect("button-press-event") do |treeview, e|
if e.button == RIGHT_BUTTON
menu = Gtk::Menu.new
[
[ _("Select all"), lambda { select_all } ],
[ _("Select none"), lambda { select_none } ],
].each do |label, block|
mi = Gtk::MenuItem.new label
mi.signal_connect("activate", &block)
menu.append mi
end
menu.show_all
menu.popup nil, nil, 3, e.time
false
end
end
cellrend = Gtk::CellRendererToggle.new
cellrend.signal_connect("toggled") do |renderer, path|
iter = @model.get_iter(path)
args = iter[col_index(:course)], iter[col_index(:group)]
if iter[col_index(:marked)]
disallow_group(*args)
else
allow_group(*args)
end
iter[col_index(:marked)] ^= true
end
@treeview.insert_column(-1, _('Allowed'),
cellrend,
'visible' => col_index(:show_checkbox),
'active' => col_index(:marked))
@treeview.insert_column(-1, _('Group'),
Gtk::CellRendererText.new,
'text' => col_index(:text))
@treeview.insert_column(-1, _('Time'),
Gtk::CellRendererText.new,
'text' => col_index(:time))
@treeview.insert_column(-1, _('Lecturer'),
Gtk::CellRendererText.new,
'text' => col_index(:lecturer))
end
def enabled?
settings[:enabled]
end
def preferences_panel
vbox = Gtk::VBox.new
sw = Gtk::ScrolledWindow.new(nil, nil)
sw.shadow_type = Gtk::SHADOW_ETCHED_IN
sw.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
tree_setup
@treeview.sensitive = settings[:enabled]
sw.add(@treeview)
btn_enabled = Gtk::CheckButton.new(_('Use group constraints'))
btn_enabled.active = settings[:enabled]
btn_enabled.signal_connect('toggled') do
settings[:enabled] = btn_enabled.active?
@treeview.sensitive = settings[:enabled]
end
vbox.pack_start btn_enabled, false, false
vbox.pack_end sw, true, true, 0
vbox
end
end
end
end