tmis 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +674 -0
  3. data/README.md +44 -0
  4. data/Rakefile +64 -0
  5. data/bin/tmis +4 -0
  6. data/lib/tmis/engine/database.rb +58 -0
  7. data/lib/tmis/engine/export/timetable_exporter.rb +366 -0
  8. data/lib/tmis/engine/import/abstract_spreadsheet.rb +53 -0
  9. data/lib/tmis/engine/import/spreadsheet_roo.rb +136 -0
  10. data/lib/tmis/engine/import/timetable_manager.rb +110 -0
  11. data/lib/tmis/engine/import/timetable_reader.rb +79 -0
  12. data/lib/tmis/engine/mailer/mailer.rb +51 -0
  13. data/lib/tmis/engine/migrations/10_create_speciality_subjects.rb +17 -0
  14. data/lib/tmis/engine/migrations/11_create_emails.rb +10 -0
  15. data/lib/tmis/engine/migrations/12_add_indexes.rb +32 -0
  16. data/lib/tmis/engine/migrations/1_create_groups.rb +11 -0
  17. data/lib/tmis/engine/migrations/2_create_subgroups.rb +10 -0
  18. data/lib/tmis/engine/migrations/3_create_subjects.rb +11 -0
  19. data/lib/tmis/engine/migrations/4_create_cabinets.rb +12 -0
  20. data/lib/tmis/engine/migrations/5_create_lecturers.rb +14 -0
  21. data/lib/tmis/engine/migrations/6_create_studies.rb +15 -0
  22. data/lib/tmis/engine/migrations/7_create_courses.rb +9 -0
  23. data/lib/tmis/engine/migrations/8_create_specialities.rb +9 -0
  24. data/lib/tmis/engine/migrations/9_create_semesters.rb +10 -0
  25. data/lib/tmis/engine/models/cabinet.rb +18 -0
  26. data/lib/tmis/engine/models/course.rb +11 -0
  27. data/lib/tmis/engine/models/email.rb +19 -0
  28. data/lib/tmis/engine/models/group.rb +31 -0
  29. data/lib/tmis/engine/models/lecturer.rb +45 -0
  30. data/lib/tmis/engine/models/semester.rb +4 -0
  31. data/lib/tmis/engine/models/speciality.rb +3 -0
  32. data/lib/tmis/engine/models/speciality_subject.rb +6 -0
  33. data/lib/tmis/engine/models/study.rb +56 -0
  34. data/lib/tmis/engine/models/subgroup.rb +21 -0
  35. data/lib/tmis/engine/models/subject.rb +19 -0
  36. data/lib/tmis/engine/verificator.rb +96 -0
  37. data/lib/tmis/interface/forms/about.rb +24 -0
  38. data/lib/tmis/interface/forms/console.rb +28 -0
  39. data/lib/tmis/interface/forms/debug_console.rb +32 -0
  40. data/lib/tmis/interface/forms/edit_study.rb +110 -0
  41. data/lib/tmis/interface/forms/expand_changes.rb +128 -0
  42. data/lib/tmis/interface/forms/export_general_timetable.rb +68 -0
  43. data/lib/tmis/interface/forms/export_group_timetable.rb +158 -0
  44. data/lib/tmis/interface/forms/export_lecturer_timetable.rb +171 -0
  45. data/lib/tmis/interface/forms/find.rb +71 -0
  46. data/lib/tmis/interface/forms/import.rb +36 -0
  47. data/lib/tmis/interface/forms/settings.rb +125 -0
  48. data/lib/tmis/interface/forms/ui_about.rb +88 -0
  49. data/lib/tmis/interface/forms/ui_console.rb +68 -0
  50. data/lib/tmis/interface/forms/ui_debug_console.rb +82 -0
  51. data/lib/tmis/interface/forms/ui_edit_study.rb +202 -0
  52. data/lib/tmis/interface/forms/ui_expand_changes.rb +134 -0
  53. data/lib/tmis/interface/forms/ui_export_general_timetable.rb +142 -0
  54. data/lib/tmis/interface/forms/ui_export_group_timetable.rb +160 -0
  55. data/lib/tmis/interface/forms/ui_export_lecturer_timetable.rb +160 -0
  56. data/lib/tmis/interface/forms/ui_find.rb +77 -0
  57. data/lib/tmis/interface/forms/ui_import.rb +134 -0
  58. data/lib/tmis/interface/forms/ui_settings.rb +417 -0
  59. data/lib/tmis/interface/mainwindow.rb +933 -0
  60. data/lib/tmis/interface/models/cabinet_table_model.rb +133 -0
  61. data/lib/tmis/interface/models/course_table_model.rb +87 -0
  62. data/lib/tmis/interface/models/group_table_model.rb +190 -0
  63. data/lib/tmis/interface/models/lecturer_table_model.rb +111 -0
  64. data/lib/tmis/interface/models/semester_table_model.rb +137 -0
  65. data/lib/tmis/interface/models/speciality_subject_table_model.rb +288 -0
  66. data/lib/tmis/interface/models/speciality_table_model.rb +87 -0
  67. data/lib/tmis/interface/models/study_table_model.rb +323 -0
  68. data/lib/tmis/interface/models/subgroup_table_model.rb +136 -0
  69. data/lib/tmis/interface/models/subject_table_model.rb +90 -0
  70. data/lib/tmis/interface/ui_mainwindow.rb +928 -0
  71. data/lib/tmis.rb +45 -0
  72. data/spec/config.rb +49 -0
  73. data/spec/database_spec.rb +18 -0
  74. data/spec/export/timetable_exporter_mocks.rb +20 -0
  75. data/spec/export/timetable_exporter_spec.rb +34 -0
  76. data/spec/factories/factories.rb +65 -0
  77. data/spec/import/test_data/raspisanie_2013.csv +104 -0
  78. data/spec/import/timetable_importer_mocks.rb +6 -0
  79. data/spec/import/timetable_manager_spec.rb +16 -0
  80. data/spec/import/timetable_reader_spec.rb +111 -0
  81. data/spec/import/timetable_roo_spec.rb +48 -0
  82. data/spec/mailer/mailer_spec.rb +37 -0
  83. data/spec/mainwindow_spec.rb +18 -0
  84. data/spec/models/cabinet_spec.rb +33 -0
  85. data/spec/models/course_spec.rb +26 -0
  86. data/spec/models/group_spec.rb +33 -0
  87. data/spec/models/lecturer_spec.rb +38 -0
  88. data/spec/models/semester_spec.rb +26 -0
  89. data/spec/models/speciality_spec.rb +26 -0
  90. data/spec/models/speciality_subject_spec.rb +9 -0
  91. data/spec/models/study_spec.rb +9 -0
  92. data/spec/models/subgroup_spec.rb +26 -0
  93. data/spec/models/subject_spec.rb +39 -0
  94. metadata +290 -0
@@ -0,0 +1,158 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'settings'
6
+ require_relative 'ui_export_group_timetable'
7
+ require_relative '../../engine/database'
8
+ require_relative '../../engine/models/group'
9
+ require_relative '../../engine/export/timetable_exporter.rb'
10
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11
+ require 'contracts'
12
+ #include Contracts
13
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14
+ class ExportGroupTimetableDialog < Qt::Dialog
15
+
16
+ slots 'on_exportButtonBox_accepted()'
17
+ slots 'on_exportButtonBox_rejected()'
18
+ slots 'on_selectAllPushButton_pressed()'
19
+ slots 'on_deselectAllPushButton_pressed()'
20
+ slots 'on_saveCheckBox_toggled(bool)'
21
+
22
+ def initialize(initial_date, parent = nil)
23
+ super parent
24
+ @ui = Ui::ExportGroupTimetableDialog.new
25
+ @ui.setup_ui self
26
+ @ui.dayDateEdit.setDate(Qt::Date.fromString(initial_date.to_s, Qt::ISODate))
27
+ @ui.progressBar.visible = false
28
+ Group.all.each do |g|
29
+ item = Qt::ListWidgetItem.new(g.to_s, @ui.groupsListWidget)
30
+ item.setData(Qt::UserRole, Qt::Variant.new(g.id))
31
+ item.checkState = Qt::Unchecked
32
+ end
33
+ end
34
+
35
+ def on_saveCheckBox_stateChanged
36
+ checkbox_actions(sender, chk, unchk)
37
+ end
38
+
39
+ def on_saveCheckBox_toggled(checked)
40
+ if checked
41
+ if (path = Qt::FileDialog::getExistingDirectory(self, 'Open Directory', '/home', Qt::FileDialog::ShowDirsOnly | Qt::FileDialog::DontResolveSymlinks))
42
+ @ui.folderPathLineEdit.text = path # force_encoding doesn't help because Qt changes the encoding to ASCII anyway
43
+ else
44
+ @ui.folderPathLineEdit.text = Dir.home
45
+ end
46
+ else
47
+ @ui.folderPathLineEdit.text = ''
48
+ end
49
+ end
50
+
51
+ def on_selectAllPushButton_pressed
52
+ @ui.groupsListWidget.count.times{|i| @ui.groupsListWidget.item(i).setCheckState(Qt::Checked) }
53
+ end
54
+
55
+ def on_deselectAllPushButton_pressed
56
+ @ui.groupsListWidget.count.times{|i| @ui.groupsListWidget.item(i).setCheckState(Qt::Unchecked) }
57
+ end
58
+
59
+ def on_exportButtonBox_accepted
60
+ if @ui.modeComboBox.currentIndex == 0
61
+ date = Date.parse(@ui.dayDateEdit.date.toString(Qt::ISODate)).monday
62
+ export(date..date + 5)
63
+ close
64
+ elsif @ui.modeComboBox.currentIndex == 1
65
+ export([Date.parse(@ui.dayDateEdit.date.toString(Qt::ISODate))])
66
+ close
67
+ end
68
+ end
69
+
70
+ def export(dates)
71
+ # TODO распараллелить
72
+ # TODO progressBar в процентах
73
+ @ui.progressBar.visible = true
74
+ @ui.progressBar.setRange(0, @ui.groupsListWidget.count)
75
+ if @ui.saveCheckBox.checkState == Qt::Checked and @ui.mailCheckBox.checkState == Qt::Checked
76
+ @ui.groupsListWidget.count.times do |i|
77
+ @ui.progressBar.setValue(i)
78
+ Qt::Application::processEvents
79
+ if @ui.groupsListWidget.item(i).checkState == Qt::Checked
80
+ id = @ui.groupsListWidget.item(i).data(Qt::UserRole)
81
+ group = Group.where(id: id.to_i).first
82
+ path = @ui.folderPathLineEdit.text.force_encoding('UTF-8')
83
+ if File.writable? path
84
+ filename = File.join(path, "#{group.title}_timetable.xls")
85
+ if File.exist? filename
86
+ File.delete filename
87
+ spreadsheet = SpreadsheetCreater.create filename
88
+ else
89
+ spreadsheet = SpreadsheetCreater.create filename
90
+ end
91
+ TimetableExporter.new(spreadsheet, GroupTimetableExportStratagy.new(dates, group)).export.save
92
+ mail(group, filename)
93
+ end
94
+ end
95
+ end
96
+ elsif @ui.saveCheckBox.checkState == Qt::Checked
97
+ @ui.groupsListWidget.count.times do |i|
98
+ @ui.progressBar.setValue(i)
99
+ Qt::Application::processEvents
100
+ if @ui.groupsListWidget.item(i).checkState == Qt::Checked
101
+ id = @ui.groupsListWidget.item(i).data(Qt::UserRole)
102
+ group = Group.where(id: id.to_i).first
103
+ path = @ui.folderPathLineEdit.text.force_encoding('UTF-8')
104
+ if File.writable? path
105
+ filename = File.join(path, "#{group.title}_timetable.xls")
106
+ if File.exist? filename
107
+ File.delete filename
108
+ spreadsheet = SpreadsheetCreater.create filename
109
+ else
110
+ spreadsheet = SpreadsheetCreater.create filename
111
+ end
112
+ TimetableExporter.new(spreadsheet, GroupTimetableExportStratagy.new(dates, group)).export.save
113
+ mail(group, filename)
114
+ end
115
+ end
116
+ end
117
+ elsif @ui.mailCheckBox.checkState == Qt::Checked
118
+ @ui.groupsListWidget.count.times do |i|
119
+ @ui.progressBar.setValue(i)
120
+ Qt::Application::processEvents
121
+ if @ui.groupsListWidget.item(i).checkState == Qt::Checked
122
+ id = @ui.groupsListWidget.item(i).data(Qt::UserRole)
123
+ group = Group.where(id: id.to_i).first
124
+ filename = Dir.mktmpdir('tmis') + "/#{group.title}_timetable.xls"
125
+ spreadsheet = SpreadsheetCreater.create filename
126
+ TimetableExporter.new(spreadsheet, GroupTimetableExportStratagy.new(dates, group)).export.save
127
+ mail(group, filename)
128
+ end
129
+ end
130
+ end
131
+ # thread.join
132
+ @ui.progressBar.visible = false
133
+ end
134
+
135
+ def mail(group, filename)
136
+ group.emails.select(&:email_valid?).each do |email|
137
+ text = "Здравствуйте, куратор группы #{group.to_s}!\n" +
138
+ "В прикреплённой электронной таблице находится расписание для вашей группы.\n"
139
+ Mailer.new(Settings[:mailer, :email], Settings[:mailer, :password]) do
140
+ from 'tmis@kp11.ru'
141
+ to email.email
142
+ subject 'Расписание'
143
+ body text
144
+ add_file filename
145
+ end.send!
146
+ end
147
+ end
148
+
149
+ def on_exportButtonBox_rejected
150
+ close
151
+ end
152
+
153
+ def show_message(text)
154
+ box = Qt::MessageBox.new
155
+ box.setText text
156
+ box.exec
157
+ end
158
+ end
@@ -0,0 +1,171 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'settings'
6
+ require_relative 'ui_export_lecturer_timetable'
7
+ require_relative '../../engine/database'
8
+ require_relative '../../engine/models/lecturer'
9
+ require_relative '../../engine/export/timetable_exporter.rb'
10
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11
+ require 'contracts'
12
+ #include Contracts
13
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14
+ class ExportLecturerTimetableDialog < Qt::Dialog
15
+
16
+ slots 'on_exportButtonBox_accepted()'
17
+ slots 'on_exportButtonBox_rejected()'
18
+ slots 'on_selectAllPushButton_pressed()'
19
+ slots 'on_deselectAllPushButton_pressed()'
20
+ slots 'on_saveCheckBox_toggled(bool)'
21
+
22
+ def initialize(initial_date, parent = nil)
23
+ super parent
24
+ @ui = Ui::ExportLecturerTimetableDialog.new
25
+ @ui.setup_ui self
26
+ @ui.dayDateEdit.setDate(Qt::Date.fromString(initial_date.to_s, Qt::ISODate))
27
+ @ui.progressBar.visible = false
28
+ Lecturer.all.each do |l|
29
+ item = Qt::ListWidgetItem.new(l.to_s, @ui.lecturersListWidget)
30
+ item.setData(Qt::UserRole, Qt::Variant.new(l.id))
31
+ item.checkState = Qt::Unchecked
32
+ end
33
+ end
34
+
35
+ def on_saveCheckBox_stateChanged
36
+ checkbox_actions(sender, chk, unchk)
37
+ end
38
+
39
+ def on_saveCheckBox_toggled(checked)
40
+ if checked
41
+ if (path = Qt::FileDialog::getExistingDirectory(self, 'Open Directory', '/home', Qt::FileDialog::ShowDirsOnly | Qt::FileDialog::DontResolveSymlinks))
42
+ @ui.folderPathLineEdit.text = path # force_encoding doesn't help because Qt changes the encoding to ASCII anyway
43
+ else
44
+ @ui.folderPathLineEdit.text = Dir.home
45
+ end
46
+ else
47
+ @ui.folderPathLineEdit.text = ''
48
+ end
49
+ end
50
+
51
+ def on_selectAllPushButton_pressed
52
+ @ui.lecturersListWidget.count.times{|i| @ui.lecturersListWidget.item(i).setCheckState(Qt::Checked) }
53
+ end
54
+
55
+ def on_deselectAllPushButton_pressed
56
+ @ui.lecturersListWidget.count.times{|i| @ui.lecturersListWidget.item(i).setCheckState(Qt::Unchecked) }
57
+ end
58
+
59
+ def on_exportButtonBox_accepted
60
+ if @ui.modeComboBox.currentIndex == 0
61
+ date = Date.parse(@ui.dayDateEdit.date.toString(Qt::ISODate)).monday
62
+ export(date..date + 5)
63
+ close
64
+ elsif @ui.modeComboBox.currentIndex == 1
65
+ export([Date.parse(@ui.dayDateEdit.date.toString(Qt::ISODate))])
66
+ close
67
+ end
68
+ end
69
+
70
+ def export(dates)
71
+ # TODO распараллелить
72
+ # TODO progressBar в процентах
73
+ @ui.progressBar.visible = true
74
+ @ui.progressBar.setRange(0, @ui.lecturersListWidget.count)
75
+ if @ui.saveCheckBox.checkState == Qt::Checked and @ui.mailCheckBox.checkState == Qt::Checked
76
+ #if !@ui.folderPathLineEdit.text.empty? && Dir.exist?(File.expand_path(@ui.folderPathLineEdit.text.force_encoding('UTF-8')))
77
+ @ui.lecturersListWidget.count.times do |i|
78
+ @ui.progressBar.setValue(i)
79
+ Qt::Application::processEvents
80
+ if @ui.lecturersListWidget.item(i).checkState == Qt::Checked
81
+ id = @ui.lecturersListWidget.item(i).data(Qt::UserRole)
82
+ lecturer = Lecturer.where(id: id.to_i).first
83
+ path = @ui.folderPathLineEdit.text.force_encoding('UTF-8')
84
+ if File.writable? path
85
+ filename = File.join(path, "#{lecturer.surname}_timetable.xls")
86
+ if File.exist? filename
87
+ File.delete filename
88
+ spreadsheet = SpreadsheetCreater.create filename
89
+ else
90
+ spreadsheet = SpreadsheetCreater.create filename
91
+ end
92
+ TimetableExporter2.new(spreadsheet, LecturerTimetableExportStratagy2.new(dates, lecturer)).export.save
93
+ mail(lecturer, filename)
94
+ end
95
+ end
96
+ end
97
+ #else
98
+ # show_message 'Директория не существует выберите другую.'
99
+ #end
100
+ elsif @ui.saveCheckBox.checkState == Qt::Checked
101
+ @ui.lecturersListWidget.count.times do |i|
102
+ @ui.progressBar.setValue(i)
103
+ Qt::Application::processEvents
104
+ if @ui.lecturersListWidget.item(i).checkState == Qt::Checked
105
+ id = @ui.lecturersListWidget.item(i).data(Qt::UserRole)
106
+ lecturer = Lecturer.where(id: id.to_i).first
107
+ path = @ui.folderPathLineEdit.text.force_encoding('UTF-8')
108
+ if File.writable? path
109
+ filename = File.join(path, "#{lecturer.surname}_timetable.xls")
110
+ if File.exist? filename
111
+ File.delete filename
112
+ spreadsheet = SpreadsheetCreater.create filename
113
+ else
114
+ spreadsheet = SpreadsheetCreater.create filename
115
+ end
116
+ TimetableExporter2.new(spreadsheet, LecturerTimetableExportStratagy2.new(dates, lecturer)).export.save
117
+ mail(lecturer, filename)
118
+ end
119
+ end
120
+ end
121
+ elsif @ui.mailCheckBox.checkState == Qt::Checked
122
+ @ui.lecturersListWidget.count.times do |i|
123
+ @ui.progressBar.setValue(i)
124
+ Qt::Application::processEvents
125
+ if @ui.lecturersListWidget.item(i).checkState == Qt::Checked
126
+ id = @ui.lecturersListWidget.item(i).data(Qt::UserRole)
127
+ lecturer = Lecturer.where(id: id.to_i).first
128
+ filename = Dir.mktmpdir('tmis') + "/#{lecturer.surname}_timetable.xls"
129
+ spreadsheet = SpreadsheetCreater.create filename
130
+ TimetableExporter2.new(spreadsheet, LecturerTimetableExportStratagy2.new(dates, lecturer)).export.save
131
+ mail(lecturer, filename)
132
+ end
133
+ end
134
+ end
135
+ # thread.join
136
+ @ui.progressBar.visible = false
137
+ end
138
+
139
+ def mail(lecturer, filename)
140
+ lecturer.emails.select(&:email_valid?).each do |email|
141
+ text = "Здравствуйте, #{lecturer.to_s}! Ваши пары на этой неделе:\n\n"
142
+ grouped = lecturer.studies.group(:date, :number).group_by(&:date)
143
+ grouped.each do |date, studies|
144
+ text += "Дата: #{date}\n\n"
145
+ studies.each do |s|
146
+ text += "\t Номер: #{s.number}, группа: #{s.groupable.to_s}, предмет #{s.subject.title}, кабинет: #{s.cabinet.title}\n"
147
+ end
148
+ end
149
+ text += "\nИтого пар: #{lecturer.studies.count}\n"
150
+ # lecturer.emails.map do
151
+ Mailer.new(Settings[:mailer, :email], Settings[:mailer, :password]) do
152
+ from 'tmis@kp11.ru'
153
+ to email.email
154
+ subject 'Расписание'
155
+ body text
156
+ add_file filename
157
+ end.send!
158
+ #add_file :filename => 'timetable.xls', :content => File.read(filename, "r:UTF-8")
159
+ end
160
+ end
161
+
162
+ def on_exportButtonBox_rejected
163
+ close
164
+ end
165
+
166
+ def show_message(text)
167
+ box = Qt::MessageBox.new
168
+ box.setText text
169
+ box.exec
170
+ end
171
+ end
@@ -0,0 +1,71 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require_relative 'ui_find'
5
+ require_relative '../../engine/database'
6
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7
+ require 'contracts'
8
+ #include Contracts
9
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
+ class FindDialog < Qt::Dialog
11
+
12
+ def initialize(entity, parent = nil)
13
+ super parent
14
+ @main = parent
15
+ @ui = Ui::FindDialog.new
16
+ @ui.setup_ui self
17
+ @entity = entity
18
+ case @entity
19
+ when :lecturer
20
+ @ui.findByLabel.text = "Фамилия преподавателя:"
21
+ Lecturer.all.sort_by(&:surname).each{|x| @ui.findByComboBox.addItem(x.surname, x.id.to_v)}
22
+ @ui.findByComboBox.setCurrentIndex(0)
23
+ when :subject
24
+ @ui.findByLabel.text = "Название предмета:"
25
+ Subject.all.sort_by(&:title).each{|x| @ui.findByComboBox.addItem(x.title, x.id.to_v)}
26
+ @ui.findByComboBox.setCurrentIndex(0)
27
+ when :cabinet
28
+ @ui.findByLabel.text = "Название кабинета:"
29
+ Cabinet.all.sort_by(&:title).each{|x| @ui.findByComboBox.addItem(x.title, x.id.to_v)}
30
+ @ui.findByComboBox.setCurrentIndex(0)
31
+ else
32
+ raise ArgumentError
33
+ end
34
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Ok), SIGNAL('clicked()')){ ok }
35
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Cancel), SIGNAL('clicked()')){ cancel }
36
+ end
37
+
38
+ def ok
39
+ @main.study_table_models.each do |model|
40
+ model.cancelColoring
41
+ end
42
+ case @entity
43
+ when :lecturer
44
+ studies = Study.where(lecturer_id: @ui.findByComboBox.itemData(@ui.findByComboBox.currentIndex).to_i)
45
+ when :subject
46
+ studies = Study.where(subject_id: @ui.findByComboBox.itemData(@ui.findByComboBox.currentIndex).to_i)
47
+ when :cabinet
48
+ studies = Study.where(cabinet_id: @ui.findByComboBox.itemData(@ui.findByComboBox.currentIndex).to_i)
49
+ else
50
+ raise ArgumentError
51
+ end
52
+ studies.each do |study|
53
+ @main.study_table_models.each do |model|
54
+ model.setColor(study.id, Qt::green)
55
+ end
56
+ end
57
+ end
58
+
59
+ def cancel
60
+ @main.study_table_models.each do |model|
61
+ model.cancelColoring
62
+ end
63
+ close
64
+ end
65
+
66
+ def show_message(text)
67
+ box = Qt::MessageBox.new
68
+ box.setText text
69
+ box.exec
70
+ end
71
+ end
@@ -0,0 +1,36 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'ui_import'
6
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7
+ require 'contracts'
8
+ #include Contracts
9
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
+ class ImportDialog < Qt::Dialog
11
+
12
+ attr_reader :params
13
+
14
+ slots 'on_buttonBox_accepted()'
15
+ slots 'on_buttonBox_rejected()'
16
+
17
+ def initialize(initial_date, parent = nil)
18
+ super parent
19
+ @ui = Ui::ImportDialog.new
20
+ @ui.setup_ui self
21
+ monday = Qt::Date.fromString(initial_date.monday.to_s, Qt::ISODate)
22
+ @ui.dateEdit.setDate(monday)
23
+ @params = {}
24
+ end
25
+
26
+ def on_buttonBox_accepted
27
+ date = Date.parse(@ui.dateEdit.date.toString(Qt::ISODate)).monday
28
+ @params[:sheet] = @ui.sheetNumberSpinBox.value
29
+ @params[:date] = date
30
+ close
31
+ end
32
+
33
+ def on_buttonBox_rejected
34
+ close
35
+ end
36
+ end
@@ -0,0 +1,125 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require_relative 'ui_settings'
5
+ require_relative '../../engine/mailer/mailer.rb'
6
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7
+ require 'contracts'
8
+ #include Contracts
9
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
+ class Settings
11
+
12
+ @@settings = Qt::Settings.new('settings.ini', 'Qt::Settings::IniFormat')
13
+
14
+ #Contract Symbol, Symbol => String
15
+ def self.[](group, key)
16
+ @@settings.beginGroup group.to_s
17
+ result = @@settings.value key.to_s
18
+ @@settings.endGroup()
19
+ result.value.to_s.force_encoding('UTF-8')
20
+ end
21
+
22
+ #Contract Symbol, Symbol, Any => Any
23
+ def self.[]=(group, key, value)
24
+ @@settings.beginGroup group.to_s
25
+ @@settings.setValue(key.to_s, Qt::Variant.new(value))
26
+ @@settings.endGroup()
27
+ @@settings.sync
28
+ end
29
+
30
+ def self.reset!(group)
31
+ case group
32
+ when :mailer
33
+ self[:mailer, :email] = 'email@example.com'
34
+ self[:mailer, :password] = '12345'
35
+ when :stubs
36
+ self[:stubs, :lecturer] = 'Вакансия'
37
+ self[:stubs, :cabinet] = 'Не назначен'
38
+ self[:stubs, :subject] = 'Не назначен'
39
+ else
40
+ raise ArgumentError, 'No such settings group!'
41
+ end
42
+ end
43
+
44
+ def self.set_defaults_if_first_run
45
+ if Settings[:app, :first_run].empty?
46
+ Settings[:app, :first_run] = 'false'
47
+ self.reset! :mailer
48
+ self.reset! :stubs
49
+ end
50
+ end
51
+ end
52
+
53
+ class SettingsDialog < Qt::Dialog
54
+
55
+ slots 'apply()'
56
+ slots 'ok()'
57
+ slots 'restore()'
58
+ slots 'help()'
59
+
60
+ def initialize(parent = nil)
61
+ super(parent)
62
+ @ui = Ui::SettingsDialog.new
63
+ @ui.setup_ui self
64
+ @ui.stackedWidget.setCurrentIndex(0)
65
+ setup
66
+ connect(@ui.actionsListWidget, SIGNAL('currentRowChanged(int)'), @ui.stackedWidget, SLOT('setCurrentIndex(int)'))
67
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Ok), SIGNAL('clicked()'), self, SLOT('ok()'))
68
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Apply), SIGNAL('clicked()'), self, SLOT('apply()'))
69
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Help), SIGNAL('clicked()'), self, SLOT('help()'))
70
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::RestoreDefaults), SIGNAL('clicked()'), self, SLOT('restore()'))
71
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Cancel), SIGNAL('clicked()')){ close }
72
+
73
+ end
74
+
75
+ def setup
76
+ @ui.emailLineEdit.text = Settings[:mailer, :email]
77
+ @ui.passwordLineEdit.text = Settings[:mailer, :password]
78
+ @ui.lecturerStubLineEdit.text = Settings[:stubs, :lecturer]
79
+ @ui.cabinetStubLineEdit.text = Settings[:stubs, :cabinet]
80
+ @ui.subjectStubLineEdit.text = Settings[:stubs, :subject]
81
+ end
82
+
83
+ def apply
84
+ if Mailer.email_valid? @ui.emailLineEdit.text
85
+ Settings[:mailer, :email] = @ui.emailLineEdit.text.force_encoding('UTF-8')
86
+ Settings[:mailer, :password] = @ui.passwordLineEdit.text.force_encoding('UTF-8')
87
+ else
88
+ show_message 'Email имеет неправильный формат!'
89
+ return false
90
+ end
91
+ Settings[:stubs, :lecturer] = @ui.lecturerStubLineEdit.text.force_encoding('UTF-8')
92
+ Settings[:stubs, :cabinet] = @ui.cabinetStubLineEdit.text.force_encoding('UTF-8')
93
+ Settings[:stubs, :subject] = @ui.subjectStubLineEdit.text.force_encoding('UTF-8')
94
+ return true
95
+ end
96
+
97
+ def ok
98
+ close if apply
99
+ end
100
+
101
+ def restore
102
+ #case @ui.stackedWidget.currentWidget.objectName
103
+ #when 'database'
104
+ # Settings.reset! :stubs
105
+ #when 'email'
106
+ # Settings.reset! :mailer
107
+ #when 'interface'
108
+ #when 'verify'
109
+ #when 'export'
110
+ #when 'import'
111
+ #else
112
+ #end
113
+ Settings.reset! :stubs
114
+ Settings.reset! :mailer
115
+ end
116
+
117
+ def help
118
+ end
119
+
120
+ def show_message(text)
121
+ box = Qt::MessageBox.new(self)
122
+ box.setText text
123
+ box.exec
124
+ end
125
+ end
@@ -0,0 +1,88 @@
1
+ =begin
2
+ ** Form generated from reading ui file 'about.ui'
3
+ **
4
+ ** Created: Wed Sep 4 00:30:33 2013
5
+ ** by: Qt User Interface Compiler version 4.8.5
6
+ **
7
+ ** WARNING! All changes made in this file will be lost when recompiling ui file!
8
+ =end
9
+
10
+ class Ui_AboutDialog
11
+ attr_reader :gridLayout_2
12
+ attr_reader :gridLayout
13
+ attr_reader :horizontalLayout
14
+ attr_reader :line
15
+ attr_reader :textBrowser
16
+ attr_reader :buttonBox
17
+
18
+ def setupUi(aboutDialog)
19
+ if aboutDialog.objectName.nil?
20
+ aboutDialog.objectName = "aboutDialog"
21
+ end
22
+ aboutDialog.resize(562, 271)
23
+ @gridLayout_2 = Qt::GridLayout.new(aboutDialog)
24
+ @gridLayout_2.objectName = "gridLayout_2"
25
+ @gridLayout = Qt::GridLayout.new()
26
+ @gridLayout.objectName = "gridLayout"
27
+ @horizontalLayout = Qt::HBoxLayout.new()
28
+ @horizontalLayout.objectName = "horizontalLayout"
29
+ @line = Qt::Frame.new(aboutDialog)
30
+ @line.objectName = "line"
31
+ @line.setFrameShape(Qt::Frame::VLine)
32
+ @line.setFrameShadow(Qt::Frame::Sunken)
33
+
34
+ @horizontalLayout.addWidget(@line)
35
+
36
+ @textBrowser = Qt::TextBrowser.new(aboutDialog)
37
+ @textBrowser.objectName = "textBrowser"
38
+ @textBrowser.enabled = true
39
+ @textBrowser.styleSheet = "background: transparent;"
40
+ @textBrowser.frameShape = Qt::Frame::NoFrame
41
+ @textBrowser.frameShadow = Qt::Frame::Plain
42
+
43
+ @horizontalLayout.addWidget(@textBrowser)
44
+
45
+
46
+ @gridLayout.addLayout(@horizontalLayout, 1, 0, 1, 1)
47
+
48
+ @buttonBox = Qt::DialogButtonBox.new(aboutDialog)
49
+ @buttonBox.objectName = "buttonBox"
50
+ @buttonBox.orientation = Qt::Horizontal
51
+ @buttonBox.standardButtons = Qt::DialogButtonBox::Cancel
52
+
53
+ @gridLayout.addWidget(@buttonBox, 2, 0, 1, 1)
54
+
55
+
56
+ @gridLayout_2.addLayout(@gridLayout, 1, 0, 1, 1)
57
+
58
+
59
+ retranslateUi(aboutDialog)
60
+ Qt::Object.connect(@buttonBox, SIGNAL('rejected()'), aboutDialog, SLOT('close()'))
61
+
62
+ Qt::MetaObject.connectSlotsByName(aboutDialog)
63
+ end # setupUi
64
+
65
+ def setup_ui(aboutDialog)
66
+ setupUi(aboutDialog)
67
+ end
68
+
69
+ def retranslateUi(aboutDialog)
70
+ aboutDialog.windowTitle = Qt::Application.translate("AboutDialog", "\320\236 \320\277\321\200\320\276\320\263\321\200\320\260\320\274\320\274\320\265", nil, Qt::Application::UnicodeUTF8)
71
+ @textBrowser.html = Qt::Application.translate("AboutDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" \
72
+ "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" \
73
+ "p, li { white-space: pre-wrap; }\n" \
74
+ "</style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\">\n" \
75
+ "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>", nil, Qt::Application::UnicodeUTF8)
76
+ end # retranslateUi
77
+
78
+ def retranslate_ui(aboutDialog)
79
+ retranslateUi(aboutDialog)
80
+ end
81
+
82
+ end
83
+
84
+ module Ui
85
+ class AboutDialog < Ui_AboutDialog
86
+ end
87
+ end # module Ui
88
+