tmis 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +674 -0
- data/README.md +44 -0
- data/Rakefile +64 -0
- data/bin/tmis +4 -0
- data/lib/tmis/engine/database.rb +58 -0
- data/lib/tmis/engine/export/timetable_exporter.rb +366 -0
- data/lib/tmis/engine/import/abstract_spreadsheet.rb +53 -0
- data/lib/tmis/engine/import/spreadsheet_roo.rb +136 -0
- data/lib/tmis/engine/import/timetable_manager.rb +110 -0
- data/lib/tmis/engine/import/timetable_reader.rb +79 -0
- data/lib/tmis/engine/mailer/mailer.rb +51 -0
- data/lib/tmis/engine/migrations/10_create_speciality_subjects.rb +17 -0
- data/lib/tmis/engine/migrations/11_create_emails.rb +10 -0
- data/lib/tmis/engine/migrations/12_add_indexes.rb +32 -0
- data/lib/tmis/engine/migrations/1_create_groups.rb +11 -0
- data/lib/tmis/engine/migrations/2_create_subgroups.rb +10 -0
- data/lib/tmis/engine/migrations/3_create_subjects.rb +11 -0
- data/lib/tmis/engine/migrations/4_create_cabinets.rb +12 -0
- data/lib/tmis/engine/migrations/5_create_lecturers.rb +14 -0
- data/lib/tmis/engine/migrations/6_create_studies.rb +15 -0
- data/lib/tmis/engine/migrations/7_create_courses.rb +9 -0
- data/lib/tmis/engine/migrations/8_create_specialities.rb +9 -0
- data/lib/tmis/engine/migrations/9_create_semesters.rb +10 -0
- data/lib/tmis/engine/models/cabinet.rb +18 -0
- data/lib/tmis/engine/models/course.rb +11 -0
- data/lib/tmis/engine/models/email.rb +19 -0
- data/lib/tmis/engine/models/group.rb +31 -0
- data/lib/tmis/engine/models/lecturer.rb +45 -0
- data/lib/tmis/engine/models/semester.rb +4 -0
- data/lib/tmis/engine/models/speciality.rb +3 -0
- data/lib/tmis/engine/models/speciality_subject.rb +6 -0
- data/lib/tmis/engine/models/study.rb +56 -0
- data/lib/tmis/engine/models/subgroup.rb +21 -0
- data/lib/tmis/engine/models/subject.rb +19 -0
- data/lib/tmis/engine/verificator.rb +96 -0
- data/lib/tmis/interface/forms/about.rb +24 -0
- data/lib/tmis/interface/forms/console.rb +28 -0
- data/lib/tmis/interface/forms/debug_console.rb +32 -0
- data/lib/tmis/interface/forms/edit_study.rb +110 -0
- data/lib/tmis/interface/forms/expand_changes.rb +128 -0
- data/lib/tmis/interface/forms/export_general_timetable.rb +68 -0
- data/lib/tmis/interface/forms/export_group_timetable.rb +158 -0
- data/lib/tmis/interface/forms/export_lecturer_timetable.rb +171 -0
- data/lib/tmis/interface/forms/find.rb +71 -0
- data/lib/tmis/interface/forms/import.rb +36 -0
- data/lib/tmis/interface/forms/settings.rb +125 -0
- data/lib/tmis/interface/forms/ui_about.rb +88 -0
- data/lib/tmis/interface/forms/ui_console.rb +68 -0
- data/lib/tmis/interface/forms/ui_debug_console.rb +82 -0
- data/lib/tmis/interface/forms/ui_edit_study.rb +202 -0
- data/lib/tmis/interface/forms/ui_expand_changes.rb +134 -0
- data/lib/tmis/interface/forms/ui_export_general_timetable.rb +142 -0
- data/lib/tmis/interface/forms/ui_export_group_timetable.rb +160 -0
- data/lib/tmis/interface/forms/ui_export_lecturer_timetable.rb +160 -0
- data/lib/tmis/interface/forms/ui_find.rb +77 -0
- data/lib/tmis/interface/forms/ui_import.rb +134 -0
- data/lib/tmis/interface/forms/ui_settings.rb +417 -0
- data/lib/tmis/interface/mainwindow.rb +933 -0
- data/lib/tmis/interface/models/cabinet_table_model.rb +133 -0
- data/lib/tmis/interface/models/course_table_model.rb +87 -0
- data/lib/tmis/interface/models/group_table_model.rb +190 -0
- data/lib/tmis/interface/models/lecturer_table_model.rb +111 -0
- data/lib/tmis/interface/models/semester_table_model.rb +137 -0
- data/lib/tmis/interface/models/speciality_subject_table_model.rb +288 -0
- data/lib/tmis/interface/models/speciality_table_model.rb +87 -0
- data/lib/tmis/interface/models/study_table_model.rb +323 -0
- data/lib/tmis/interface/models/subgroup_table_model.rb +136 -0
- data/lib/tmis/interface/models/subject_table_model.rb +90 -0
- data/lib/tmis/interface/ui_mainwindow.rb +928 -0
- data/lib/tmis.rb +45 -0
- data/spec/config.rb +49 -0
- data/spec/database_spec.rb +18 -0
- data/spec/export/timetable_exporter_mocks.rb +20 -0
- data/spec/export/timetable_exporter_spec.rb +34 -0
- data/spec/factories/factories.rb +65 -0
- data/spec/import/test_data/raspisanie_2013.csv +104 -0
- data/spec/import/timetable_importer_mocks.rb +6 -0
- data/spec/import/timetable_manager_spec.rb +16 -0
- data/spec/import/timetable_reader_spec.rb +111 -0
- data/spec/import/timetable_roo_spec.rb +48 -0
- data/spec/mailer/mailer_spec.rb +37 -0
- data/spec/mainwindow_spec.rb +18 -0
- data/spec/models/cabinet_spec.rb +33 -0
- data/spec/models/course_spec.rb +26 -0
- data/spec/models/group_spec.rb +33 -0
- data/spec/models/lecturer_spec.rb +38 -0
- data/spec/models/semester_spec.rb +26 -0
- data/spec/models/speciality_spec.rb +26 -0
- data/spec/models/speciality_subject_spec.rb +9 -0
- data/spec/models/study_spec.rb +9 -0
- data/spec/models/subgroup_spec.rb +26 -0
- data/spec/models/subject_spec.rb +39 -0
- metadata +290 -0
@@ -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
|