tmis 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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,6 @@
1
+ class SpecialitySubject < ActiveRecord::Base
2
+ belongs_to :subject
3
+ belongs_to :semester
4
+ belongs_to :speciality
5
+ belongs_to :lecturer
6
+ end
@@ -0,0 +1,56 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'contracts'
4
+ #include Contracts
5
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6
+ class Study < ActiveRecord::Base
7
+ belongs_to :groupable, :polymorphic => true
8
+ belongs_to :subject
9
+ belongs_to :lecturer
10
+ belongs_to :cabinet
11
+
12
+ # Use Model#scoped instead of Model#all
13
+ #Contract ActiveRecord::Relation => ActiveRecord::Relation::ActiveRecord_Relation_Group
14
+ def self.of_groups_and_its_subgroups(groups)
15
+ where_groups_or_subgroups(groups.select(:id), Subgroup.where(group_id: groups.select(:id)))
16
+ end
17
+
18
+ #Contract Group => ActiveRecord::Relation
19
+ def self.of_group_and_its_subgroups(group)
20
+ where_groups_or_subgroups(group.id, Subgroup.where(group_id: group.id))
21
+ end
22
+
23
+ def validate
24
+ end
25
+
26
+ def get_group
27
+ groupable.get_group
28
+ end
29
+
30
+ def to_group?
31
+ groupable_type == 'Group'
32
+ end
33
+
34
+ def to_subgroup?
35
+ groupable_type == 'Subgroup'
36
+ end
37
+
38
+ def to_s
39
+ begin
40
+ if to_subgroup?
41
+ "#{subject.title}\n#{lecturer}" + " (#{groupable.number}п)"
42
+ else
43
+ "#{subject.title}\n#{lecturer}"
44
+ end
45
+ rescue #FIXME
46
+ 'ERROR'
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def self.where_groups_or_subgroups(ids_of_groups, ids_of_subroups)
53
+ where('(groupable_type = "Group" AND groupable_id in (?)) OR (groupable_type = "Subgroup" AND groupable_id in (?))', ids_of_groups, ids_of_subroups)
54
+ end
55
+ private_class_method :where_groups_or_subgroups
56
+ end
@@ -0,0 +1,21 @@
1
+ # coding: UTF-8
2
+ class Subgroup < ActiveRecord::Base
3
+ belongs_to :group
4
+ has_many :studies, :as => :groupable, :dependent => :destroy
5
+
6
+ def group?
7
+ false
8
+ end
9
+
10
+ def subgroup?
11
+ true
12
+ end
13
+
14
+ def get_group
15
+ self.group
16
+ end
17
+
18
+ def to_s
19
+ "#{group.title} #{number} подгруппа"
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ class Subject < ActiveRecord::Base
2
+ has_many :studies
3
+ has_many :speciality_subjects
4
+
5
+ before_destroy :set_stubs_for_studies
6
+
7
+ def to_s
8
+ title
9
+ end
10
+
11
+ def set_stubs_for_studies
12
+ raise "Stub can't be destroyed!" if self.stub
13
+ stub = Subject.where(stub: true).first
14
+ studies.each do |s|
15
+ s.subject = stub
16
+ s.save
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,96 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ class Verificator
4
+
5
+ def initialize(dates)
6
+ @dates = dates.to_a
7
+ end
8
+
9
+ def verify(verification)
10
+ case verification
11
+ when :lecturer_studies
12
+ lecturer_studies
13
+ when :cabinet_studies
14
+ cabinet_studies
15
+ when :lecturer_stubs
16
+ lecturer_stubs
17
+ when :cabinet_stubs
18
+ cabinet_stubs
19
+ when :subject_stubs
20
+ subject_stubs
21
+ when :group_and_subgroups
22
+ group_and_subgroups
23
+ when :preferred_days
24
+ preferred_days
25
+ when :computer_cabinets
26
+ computer_cabinet
27
+ else
28
+ raise ArgumentError, 'No such verification'
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def lecturer_studies
35
+ @dates.map do |date|
36
+ Study.select('date, number, lecturer_id, count(*)').where(date: date).group('number, lecturer_id').having('count(*) > 1')
37
+ end.flatten.map{|x| Study.where(date: x.date, number: x.number, lecturer_id: x.lecturer_id )}.flatten.group_by{|x| [x.date, x.lecturer_id, x.number] }
38
+ #@dates.map{ |date| Study.select('id, date, number, lecturer_id, count(*)').where(date: date).group('number, lecturer_id').having('count(*) > 1').to_a }
39
+ end
40
+
41
+ def cabinet_studies
42
+ @dates.map do |date|
43
+ Study.select('date, number, cabinet_id, count(*)').where(date: date).group('number, cabinet_id').having('count(*) > 1')
44
+ end.flatten.map{|x| Study.where(date: x.date, number: x.number, cabinet_id: x.cabinet_id )}.flatten.group_by{|x| [x.date, x.cabinet_id, x.number] }
45
+ end
46
+
47
+ def lecturer_stubs
48
+ @dates.map do |date|
49
+ [date, Study.joins(:lecturer).where('lecturers.stub = ?', true).where(date: date)]
50
+ end
51
+ end
52
+
53
+ def cabinet_stubs
54
+ @dates.map do |date|
55
+ [date, Study.joins(:cabinet).where('cabinets.stub = ?', true).where(date: date)]
56
+ end
57
+ end
58
+
59
+ def subject_stubs
60
+ @dates.map do |date|
61
+ [date, Study.joins(:subject).where('subjects.stub = ?', true).where(date: date)]
62
+ end
63
+ end
64
+
65
+ def computer_cabinet
66
+ @dates.map do |date|
67
+ [date, Study.joins(:cabinet).where(groupable_type: 'Subgroup').where("cabinets.with_computers = ?", false).where(date: date)]
68
+ end
69
+ end
70
+
71
+ def preferred_days
72
+ @dates.map do |date|
73
+ #[date, Study.joins(:lecturer).where(date: date).where("NOT instr(preferred_days, strftime('%w', date))")] # doesn't work on windows
74
+ #[date, Study.joins(:lecturer).where(date: date).where("NOT preferred_days like strftime('%w', date)")]
75
+ [date, Lecturer.all.map do |l|
76
+ if l.preferred_days
77
+ l.studies.where(date: date).where("NOT strftime('%w', date) in (#{l.preferred_days.split(/,\s*/).map{|s| '\'' << s << '\'' }.join(',')})", ).to_a
78
+ end
79
+ end.flatten.compact]
80
+ end
81
+ end
82
+
83
+ #- занятия для группы и подгруппы на одной паре
84
+ #def group_and_subgroup
85
+ # @dates.map do |date|
86
+ # Study.select('date, number, groupable_type, count(*)').where(date: date).group('number, groupable_type').having('count(*) > 1')
87
+ # end.flatten.map{|x| Study.where(date: x.date, number: x.number, cabinet_id: x.cabinet_id )}.flatten.group_by{|x| [x.date, x.cabinet_id, x.number] }
88
+ #end
89
+ end
90
+
91
+ # SELECT surname, count(surname)
92
+ # FROM "lecturers"
93
+ # group by surname
94
+ # having count(surname) > 1
95
+ # Lecturer.select('surname, count(surname)').group(:surname).having('count(surname) > 1')
96
+ # select lecturer_id, number, count(*) from studies where date = '2013-06-03' group by number, lecturer_id having count(*) > 1
@@ -0,0 +1,24 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require_relative 'ui_about'
5
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6
+ require 'contracts'
7
+ #include Contracts
8
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
+ class AboutDialog < Qt::Dialog
10
+
11
+ def initialize(parent = nil)
12
+ super parent
13
+ @ui = Ui::AboutDialog.new
14
+ @ui.setup_ui self
15
+ @ui.textBrowser.html += <<-HEREDOC.gsub(/^ {4}/, '')
16
+ <p>Timetable Management Information System</p>
17
+ Версия: 0.1
18
+ <p>Информационная система управления расписанием, предназначенная для учебных заведений среднего профессионального образования.</p>
19
+ <p>Copyright © 2012 Милешкин Владислав noein93@gmail.com</p>
20
+ <p>TMIS является свободным программным обеспечением и распространяется на условиях GNU GPLv3. Текст лицензии можно найти в файле COPYING, а также по ссылке: www.gnu.org/licenses/gpl.</p>
21
+ HEREDOC
22
+ end
23
+
24
+ end
@@ -0,0 +1,28 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'ui_console'
6
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7
+ require 'contracts'
8
+ #include Contracts
9
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
+ class ConsoleDialog < Qt::Dialog
11
+
12
+ signals 'dialogClosed()'
13
+
14
+ attr_accessor :browser
15
+
16
+ def initialize(parent = nil)
17
+ super parent
18
+ @ui = Ui::ConsoleDialog.new
19
+ @ui.setup_ui self
20
+ @browser = @ui.textBrowser
21
+ end
22
+
23
+ def closeEvent(event)
24
+ emit dialogClosed
25
+ event.accept
26
+ end
27
+
28
+ end
@@ -0,0 +1,32 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'ui_debug_console'
6
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7
+ require 'contracts'
8
+ #include Contracts
9
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
+ class DebugConsoleDialog < Qt::Dialog
11
+
12
+ slots 'on_enterPushButton_pressed()'
13
+
14
+ attr_accessor :browser
15
+
16
+ def initialize(parent = nil)
17
+ super parent
18
+ @ui = Ui::DebugConsoleDialog.new
19
+ @ui.setup_ui self
20
+ end
21
+
22
+ def on_enterPushButton_pressed
23
+ res = '$'
24
+ begin
25
+ res = "#{Database.instance.instance_eval(@ui.lineEdit.text)}"
26
+ rescue Exception => detail
27
+ @ui.textEdit.setText("Error on #{@ui.lineEdit.text}")
28
+ end
29
+ @ui.textEdit.setText(res)
30
+ end
31
+
32
+ end
@@ -0,0 +1,110 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'ui_edit_study'
6
+ require_relative '../../engine/database'
7
+ require_relative '../../engine/models/lecturer'
8
+ #require_relative '../../engine/models/group'
9
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
+ require 'contracts'
11
+ #include Contracts
12
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13
+ class EditStudyDialog < Qt::Dialog
14
+
15
+ slots 'on_groupComboBox_currentIndexChanged(int)'
16
+ slots 'on_selectColorPushButton_clicked()'
17
+ slots 'on_defaultColorPushButton_clicked()'
18
+ slots 'reset()'
19
+ slots 'save()'
20
+
21
+ def initialize(parent = nil)
22
+ super parent
23
+ @ui = Ui::EditStudyDialog.new
24
+ @ui.setup_ui self
25
+ end
26
+
27
+ #Contract Study => EditStudyDialog
28
+ def setupData(study)
29
+ @study = study
30
+ setWindowTitle 'Новое занятие' if @study.new_record?
31
+ @color = Qt::Color.new(study.color || "#ffffff")
32
+ @ui.selectColorPushButton.setPalette(Qt::Palette.new(@color))
33
+ # set group
34
+ Group.all.sort_by(&:title_for_sort).each{|x| @ui.groupComboBox.addItem(x.title, x.id.to_v)}
35
+ @ui.groupComboBox.setCurrentIndex(@ui.groupComboBox.findData(@study.groupable.get_group.id.to_v))
36
+ # set subject
37
+ Subject.all.sort_by(&:title).each{|x| @ui.subjectComboBox.addItem(x.title, x.id.to_v)}
38
+ @ui.subjectComboBox.setCurrentIndex(@ui.subjectComboBox.findData(@study.subject.id.to_v)) unless @study.new_record?
39
+ # set lecturer
40
+ Lecturer.all.sort_by(&:surname).each{|x| @ui.lecturerComboBox.addItem(x.to_s, x.id.to_v)}
41
+ @ui.lecturerComboBox.setCurrentIndex(@ui.lecturerComboBox.findData(@study.lecturer.id.to_v)) unless @study.new_record?
42
+ # set cabinet
43
+ Cabinet.all.sort_by(&:title).each{|x| @ui.cabinetComboBox.addItem(x.title.to_s, x.id.to_v)}
44
+ @ui.cabinetComboBox.setCurrentIndex(@ui.cabinetComboBox.findData(@study.cabinet.id.to_v)) unless @study.new_record?
45
+ # set number
46
+ (1..6).each{|x| @ui.numberComboBox.addItem(x.to_s, x.to_v)}
47
+ @ui.numberComboBox.setCurrentIndex(@ui.numberComboBox.findData(@study.number.to_v))
48
+ @ui.dateDateEdit.setDate(Qt::Date.fromString(@study.date.to_s, Qt::ISODate))
49
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Reset), SIGNAL('clicked()'), self, SLOT('reset()'))
50
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Save), SIGNAL('clicked()'), self, SLOT('save()'))
51
+ connect(@ui.buttonBox.button(Qt::DialogButtonBox::Cancel), SIGNAL('clicked()')){ close }
52
+ self
53
+ end
54
+
55
+ def on_groupComboBox_currentIndexChanged(index)
56
+ @ui.subgroupComboBox.clear
57
+ @ui.subgroupComboBox.addItem('Вся группа', 0.to_v)
58
+ Subgroup.where(group_id: @study.groupable.get_group).each{|x| @ui.subgroupComboBox.addItem(x.number.to_s, x.id.to_v)}
59
+ if @study.groupable.subgroup? && !@study.new_record?
60
+ @ui.subgroupComboBox.setCurrentIndex(@ui.subgroupComboBox.findData(@study.groupable.id.to_v))
61
+ else
62
+ @ui.subgroupComboBox.setCurrentIndex(0)
63
+ end
64
+ end
65
+
66
+ def reset
67
+ [@ui.groupComboBox, @ui.subgroupComboBox, @ui.subjectComboBox, @ui.lecturerComboBox, @ui.cabinetComboBox,
68
+ @ui.numberComboBox].each(&:clear)
69
+ setupData(@study)
70
+ end
71
+
72
+ def save
73
+ if @ui.subgroupComboBox.currentIndex == 0
74
+ group = Group.where(id: @ui.groupComboBox.itemData(@ui.groupComboBox.currentIndex).to_i).first
75
+ @study.groupable_id = group.id
76
+ @study.groupable_type = 'Group'
77
+ else
78
+ subgroup = Subgroup.where(id: @ui.subgroupComboBox.itemData(@ui.subgroupComboBox.currentIndex).to_i).first
79
+ @study.groupable_id = subgroup.id
80
+ @study.groupable_type = 'Subgroup'
81
+ end
82
+ @study.subject = Subject.where(id: @ui.subjectComboBox.itemData(@ui.subjectComboBox.currentIndex).to_i).first
83
+ @study.lecturer = Lecturer.where(id: @ui.lecturerComboBox.itemData(@ui.lecturerComboBox.currentIndex).to_i).first
84
+ @study.cabinet = Cabinet.where(id: @ui.cabinetComboBox.itemData(@ui.cabinetComboBox.currentIndex).to_i).first
85
+ @study.number = @ui.numberComboBox.currentIndex + 1
86
+ @study.date = Date.parse(@ui.dateDateEdit.date.toString(Qt::ISODate))
87
+ @study.color = @color.name
88
+ @study.save
89
+ close
90
+ end
91
+
92
+ def on_defaultColorPushButton_clicked
93
+ @color = Qt::Color.new("#ffffff")
94
+ @ui.selectColorPushButton.setPalette(Qt::Palette.new(@color))
95
+ end
96
+
97
+ def on_selectColorPushButton_clicked
98
+ color = Qt::ColorDialog.getColor(@color, self)
99
+ if color.valid?
100
+ @ui.selectColorPushButton.setPalette(Qt::Palette.new(color))
101
+ @color = color
102
+ end
103
+ end
104
+
105
+ def show_message(text)
106
+ box = Qt::MessageBox.new
107
+ box.setText text
108
+ box.exec
109
+ end
110
+ end
@@ -0,0 +1,128 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'ui_expand_changes'
6
+ require_relative '../../engine/database'
7
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
+ require 'contracts'
9
+ #include Contracts
10
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11
+ class ExpandChangesDialog < Qt::Dialog
12
+
13
+ slots 'on_buttonBox_accepted()'
14
+ slots 'on_buttonBox_rejected()'
15
+
16
+ def initialize(parent = nil)
17
+ super(parent)
18
+ @ui = Ui::ExpandChangesDialog.new
19
+ @ui.setup_ui self
20
+ @date = Date.parse(parent.ui.dateDateEdit.date.toString(Qt::ISODate))
21
+ monday = Qt::Date.fromString(@date.monday.to_s, Qt::ISODate)
22
+ @ui.fromDateDateEdit.setDate monday
23
+ @ui.toDateDateEdit.setDate monday
24
+ end
25
+
26
+ def on_buttonBox_accepted
27
+ from_monday = Date.parse(@ui.fromDateDateEdit.date.toString(Qt::ISODate)).monday
28
+ to_date = Date.parse(@ui.toDateDateEdit.date.toString(Qt::ISODate))
29
+ week_studies = Study.where(date: from_monday..(from_monday + 6))
30
+
31
+ Database.instance.transaction do
32
+ case @ui.evennessComboBox.currentIndex
33
+ when 0
34
+ if from_monday == to_date
35
+ elsif to_date > from_monday
36
+ dates = (from_monday + 7).upto(to_date).select{|date| (1..6).include? date.cwday }.to_a
37
+ Study.where(date: (from_monday + 7)..to_date).each{|study| study.destroy }
38
+ week_studies.each do |study|
39
+ dates.each do |date|
40
+ if study.date.cwday == date.cwday
41
+ study = study.dup
42
+ study.date = date
43
+ study.save
44
+ end
45
+ end
46
+ end
47
+ elsif to_date < from_monday
48
+ dates = (from_monday - 1).downto(to_date).select{|date| (1..6).include? date.cwday }.to_a
49
+ Study.where(date: to_date...from_monday).each{|study| study.destroy }
50
+ week_studies.each do |study|
51
+ dates.each do |date|
52
+ if study.date.cwday == date.cwday
53
+ study = study.dup
54
+ study.date = date
55
+ study.save
56
+ end
57
+ end
58
+ end
59
+ end
60
+ when 1
61
+ if from_monday == to_date
62
+ elsif to_date > from_monday
63
+ dates = (from_monday + 7).upto(to_date).select{|date| date.cweek.even? && ((1..6).include? date.cwday) }.to_a
64
+ Study.where(date: (from_monday + 7)..to_date).each{|study| study.destroy }
65
+ week_studies.each do |study|
66
+ dates.each do |date|
67
+ if study.date.cwday == date.cwday
68
+ study = study.dup
69
+ study.date = date
70
+ study.save
71
+ end
72
+ end
73
+ end
74
+ elsif to_date < from_monday
75
+ dates = (from_monday - 1).downto(to_date).select{|date| date.cweek.even? && ((1..6).include? date.cwday) }.to_a
76
+ Study.where(date: to_date...from_monday).each{|study| study.destroy }
77
+ week_studies.each do |study|
78
+ dates.each do |date|
79
+ if study.date.cwday == date.cwday
80
+ study = study.dup
81
+ study.date = date
82
+ study.save
83
+ end
84
+ end
85
+ end
86
+ end
87
+ when 2
88
+ if from_monday == to_date
89
+ elsif to_date > from_monday
90
+ dates = (from_monday + 7).upto(to_date).select{|date| date.cweek.odd? && ((1..6).include? date.cwday) }.to_a
91
+ Study.where(date: (from_monday + 7)..to_date).each{|study| study.destroy }
92
+ week_studies.each do |study|
93
+ dates.each do |date|
94
+ if study.date.cwday == date.cwday
95
+ study = study.dup
96
+ study.date = date
97
+ study.save
98
+ end
99
+ end
100
+ end
101
+ elsif to_date < from_monday
102
+ dates = (from_monday - 1).downto(to_date).select{|date| date.cweek.odd? && ((1..6).include? date.cwday) }.to_a
103
+ Study.where(date: to_date...from_monday).each{|study| study.destroy }
104
+ week_studies.each do |study|
105
+ dates.each do |date|
106
+ if study.date.cwday == date.cwday
107
+ study = study.dup
108
+ study.date = date
109
+ study.save
110
+ end
111
+ end
112
+ end
113
+ end
114
+ else
115
+ end
116
+ end
117
+ end
118
+
119
+ def on_buttonBox_rejected
120
+ close
121
+ end
122
+
123
+ def show_message(text)
124
+ box = Qt::MessageBox.new
125
+ box.setText text
126
+ box.exec
127
+ end
128
+ end
@@ -0,0 +1,68 @@
1
+ # coding: UTF-8
2
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
+ require 'Qt'
4
+ require 'date'
5
+ require_relative 'ui_export_general_timetable'
6
+ require_relative '../../engine/database'
7
+ require_relative '../../engine/export/timetable_exporter.rb'
8
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9
+ require 'contracts'
10
+ #include Contracts
11
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12
+ class ExportGeneralTimetableDialog < Qt::Dialog
13
+
14
+ slots 'on_exportButtonBox_accepted()'
15
+ slots 'on_exportButtonBox_rejected()'
16
+ slots 'on_browsePushButton_clicked()'
17
+
18
+ def initialize(initial_date, parent = nil)
19
+ super parent
20
+ @ui = Ui::ExportGeneralTimetableDialog.new
21
+ @ui.setup_ui self
22
+ @ui.dateDateEdit.setDate Qt::Date.fromString(initial_date.to_s, Qt::ISODate)
23
+ end
24
+
25
+ def on_browsePushButton_clicked
26
+ @ui.pathLineEdit.text = Qt::FileDialog::getSaveFileName(self, 'Save File', 'NewTimetable', 'XLS Spreadsheet(*.xls)')
27
+ end
28
+
29
+ def on_exportButtonBox_accepted
30
+ filename = @ui.pathLineEdit.text.force_encoding 'UTF-8'
31
+ if filename.empty?
32
+ show_message 'Выберите путь к файлу'
33
+ else
34
+ path = Pathname.new(filename)
35
+ if path.dirname.writable?
36
+ date = Date.parse @ui.dateDateEdit.date.toString(Qt::ISODate)
37
+ export(date, path)
38
+ close
39
+ else
40
+ show_message 'Файл не может быть записан!'
41
+ end
42
+ end
43
+ end
44
+
45
+ def on_exportButtonBox_rejected
46
+ close
47
+ end
48
+
49
+ def export(date, path)
50
+ if path.exist?
51
+ path.delete
52
+ spreadsheet = SpreadsheetCreater.create path.to_s
53
+ else
54
+ spreadsheet = SpreadsheetCreater.create path.to_s
55
+ end
56
+ if @ui.weeklyRadioButton.isChecked
57
+ TimetableExporter.new(spreadsheet, GeneralTimetableExportStratagy.new(date.monday..date.monday + 5)).export.save
58
+ else
59
+ TimetableExporter.new(spreadsheet, GeneralTimetableExportStratagy.new([date])).export.save
60
+ end
61
+ end
62
+
63
+ def show_message(text)
64
+ box = Qt::MessageBox.new
65
+ box.setText text
66
+ box.exec
67
+ end
68
+ end