1 /*
2 Copyright (c) 2012-2020 Maarten Baert <maarten-baert@hotmail.com>
3 
4 This file is part of SimpleScreenRecorder.
5 
6 SimpleScreenRecorder is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 SimpleScreenRecorder is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with SimpleScreenRecorder.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "DialogRecordSchedule.h"
21 
22 #include "EnumStrings.h"
23 #include "PageRecord.h"
24 
25 ENUMSTRINGS(enum_schedule_time_zone) = {
26 	{SCHEDULE_TIME_ZONE_LOCAL, "local"},
27 	{SCHEDULE_TIME_ZONE_UTC, "utc"},
28 };
29 ENUMSTRINGS(enum_schedule_action) = {
30 	{SCHEDULE_ACTION_START, "start"},
31 	{SCHEDULE_ACTION_PAUSE, "pause"},
32 };
33 
34 const Qt::TimeSpec SCHEDULE_TIME_ZONE_TIMESPECS[SCHEDULE_TIME_ZONE_COUNT] = {
35 	Qt::LocalTime,
36 	Qt::UTC,
37 };
38 const QString SCHEDULE_ACTION_TEXT[SCHEDULE_ACTION_COUNT] {
39 	RecordScheduleEntryWidget::tr("Start"),
40 	RecordScheduleEntryWidget::tr("Pause"),
41 };
42 
RecordScheduleEntryWidget(QWidget * parent)43 RecordScheduleEntryWidget::RecordScheduleEntryWidget(QWidget* parent)
44 	: QWidget(parent) {
45 
46 	QLabel *label_time = new QLabel(tr("Time:"), this);
47 	m_datetimeedit_time = new QDateTimeEdit(this);
48 	m_datetimeedit_time->setDisplayFormat("yyyy-MM-dd hh:mm:ss");
49 	m_datetimeedit_time->setCalendarPopup(true);
50 
51 	QLabel *label_action = new QLabel(tr("Action:"), this);
52 	m_combobox_action = new QComboBox(this);
53 	for(unsigned int i = 0; i < SCHEDULE_ACTION_COUNT; ++i) {
54 		m_combobox_action->addItem(SCHEDULE_ACTION_TEXT[i]);
55 	}
56 
57 	QHBoxLayout *layout = new QHBoxLayout(this);
58 	layout->setMargin(5);
59 	layout->addWidget(label_time);
60 	layout->addWidget(m_datetimeedit_time);
61 	layout->addSpacing(10);
62 	layout->addWidget(label_action);
63 	layout->addWidget(m_combobox_action);
64 
65 }
66 
~RecordScheduleEntryWidget()67 RecordScheduleEntryWidget::~RecordScheduleEntryWidget() {
68 	// nothing
69 }
70 
DialogRecordSchedule(PageRecord * parent)71 DialogRecordSchedule::DialogRecordSchedule(PageRecord* parent)
72 	: QDialog(parent) {
73 
74 	m_parent = parent;
75 
76 	m_clock_time = QDateTime();
77 
78 	setWindowTitle(tr("Recording schedule"));
79 
80 	QLabel *label_info = new QLabel(tr("Time zone:"), this);
81 	m_combobox_timezone = new QComboBox(this);
82 	m_combobox_timezone->addItem(tr("Local time"));
83 	m_combobox_timezone->addItem(tr("UTC"));
84 	m_combobox_timezone->setCurrentIndex(m_parent->GetScheduleTimeZone());
85 	QLabel *label_time = new QLabel(tr("Current time:"), this);
86 	m_label_time = new QLabel(this);
87 	m_label_time->setMinimumWidth(GetTextWidth(m_label_time->fontMetrics(), "0000-00-00 00:00:00 XXXXX") + 10);
88 	m_label_time->setAlignment((m_label_time->alignment() & ~Qt::AlignHorizontal_Mask) | Qt::AlignRight);
89 
90 	m_widgetrack_schedule = new WidgetRack(this);
91 	m_widgetrack_schedule->setMinimumSize(500, 300);
92 	{
93 		std::vector<ScheduleEntry> schedule = m_parent->GetScheduleEntries();
94 		for(unsigned int i = 0; i < schedule.size(); ++i) {
95 			RecordScheduleEntryWidget *widget = new RecordScheduleEntryWidget(m_widgetrack_schedule->viewport());
96 			widget->SetTime(schedule[i].time);
97 			widget->SetAction(schedule[i].action);
98 			m_widgetrack_schedule->AddWidget(i, widget);
99 		}
100 	}
101 
102 	QPushButton *pushbutton_add = new QPushButton(QIcon::fromTheme("list-add"), tr("Add"), this); // TODO icons
103 	QPushButton *pushbutton_remove = new QPushButton(QIcon::fromTheme("list-remove"), tr("Remove"), this);
104 	QPushButton *pushbutton_move_up = new QPushButton(QIcon::fromTheme("go-up"), tr("Move up"), this);
105 	QPushButton *pushbutton_move_down = new QPushButton(QIcon::fromTheme("go-down"), tr("Move down"), this);
106 
107 	QPushButton *pushbutton_close = new QPushButton(tr("Close"), this);
108 	pushbutton_close->setDefault(true);
109 
110 	connect(m_combobox_timezone, SIGNAL(activated(int)), this, SLOT(OnTimeZoneChanged()));
111 	connect(pushbutton_add, SIGNAL(clicked()), this, SLOT(OnAdd()));
112 	connect(pushbutton_remove, SIGNAL(clicked()), this, SLOT(OnRemove()));
113 	connect(pushbutton_move_up, SIGNAL(clicked()), this, SLOT(OnMoveUp()));
114 	connect(pushbutton_move_down, SIGNAL(clicked()), this, SLOT(OnMoveDown()));
115 	connect(pushbutton_close, SIGNAL(clicked()), this, SLOT(accept()));
116 	connect(this, SIGNAL(accepted()), this, SLOT(OnWriteBack()));
117 	connect(this, SIGNAL(rejected()), this, SLOT(OnWriteBack()));
118 
119 	QVBoxLayout *layout = new QVBoxLayout(this);
120 	{
121 		QHBoxLayout *layout2 = new QHBoxLayout();
122 		layout->addLayout(layout2);
123 		layout2->addWidget(label_info);
124 		layout2->addWidget(m_combobox_timezone);
125 		layout2->addSpacing(10);
126 		layout2->addStretch();
127 		layout2->addWidget(label_time);
128 		layout2->addWidget(m_label_time);
129 	}
130 	layout->addWidget(m_widgetrack_schedule);
131 	{
132 		QHBoxLayout *layout2 = new QHBoxLayout();
133 		layout->addLayout(layout2);
134 		layout2->addWidget(pushbutton_add);
135 		layout2->addWidget(pushbutton_remove);
136 		layout2->addWidget(pushbutton_move_up);
137 		layout2->addWidget(pushbutton_move_down);
138 	}
139 	{
140 		QHBoxLayout *layout2 = new QHBoxLayout();
141 		layout->addLayout(layout2);
142 		layout2->addStretch();
143 		layout2->addWidget(pushbutton_close);
144 		layout2->addStretch();
145 	}
146 
147 	m_timer_clock = new QTimer(this);
148 	m_timer_clock->setSingleShot(true);
149 	connect(m_timer_clock, SIGNAL(timeout()), this, SLOT(OnUpdateTime()));
150 
151 	OnTimeZoneChanged();
152 	OnUpdateTime();
153 
154 	setMinimumSize(minimumSizeHint()); // workaround for Qt bug
155 
156 }
157 
~DialogRecordSchedule()158 DialogRecordSchedule::~DialogRecordSchedule() {
159 
160 }
161 
OnTimeZoneChanged()162 void DialogRecordSchedule::OnTimeZoneChanged() {
163 	m_clock_time = QDateTime();
164 	Qt::TimeSpec spec = SCHEDULE_TIME_ZONE_TIMESPECS[m_combobox_timezone->currentIndex()];
165 	for(unsigned int i = 0; i < m_widgetrack_schedule->GetWidgetCount(); ++i) {
166 		RecordScheduleEntryWidget *widget = static_cast<RecordScheduleEntryWidget*>(m_widgetrack_schedule->GetWidget(i));
167 		widget->SetTimeSpec(spec);
168 	}
169 	OnUpdateTime();
170 }
171 
OnUpdateTime()172 void DialogRecordSchedule::OnUpdateTime() {
173 	QDateTime now = QDateTime::currentDateTimeUtc();
174 	if(m_clock_time.isNull() || now > m_clock_time || now.msecsTo(m_clock_time) > 100)
175 		m_clock_time = now.addMSecs(-now.time().msec());
176 	Qt::TimeSpec spec = SCHEDULE_TIME_ZONE_TIMESPECS[m_combobox_timezone->currentIndex()];
177 	m_label_time->setText(m_clock_time.toTimeSpec(spec).toString("yyyy-MM-dd hh:mm:ss t"));
178 	m_clock_time = m_clock_time.addSecs(1);
179 	m_timer_clock->start(now.msecsTo(m_clock_time));
180 }
181 
OnAdd()182 void DialogRecordSchedule::OnAdd() {
183 	unsigned int selected = m_widgetrack_schedule->GetSelected();
184 	unsigned int index = (selected == WidgetRack::NO_SELECTION)? m_widgetrack_schedule->GetWidgetCount() : selected + 1;
185 	RecordScheduleEntryWidget *widget = new RecordScheduleEntryWidget(m_widgetrack_schedule->viewport());
186 	Qt::TimeSpec spec = SCHEDULE_TIME_ZONE_TIMESPECS[m_combobox_timezone->currentIndex()];
187 	if(selected == WidgetRack::NO_SELECTION) {
188 		QDateTime time = QDateTime::currentDateTimeUtc().toTimeSpec(spec).addSecs(60);
189 		time.setTime(QTime(time.time().hour(), 0, 0, 0));
190 		widget->SetTime(time.addSecs(60 * 60));
191 	} else {
192 		widget->SetTime(static_cast<RecordScheduleEntryWidget*>(m_widgetrack_schedule->GetWidget(selected))->GetTime());
193 	}
194 	m_widgetrack_schedule->AddWidget(index, widget);
195 	m_widgetrack_schedule->SetSelected(index);
196 	m_widgetrack_schedule->MakeVisible(widget);
197 }
198 
OnRemove()199 void DialogRecordSchedule::OnRemove() {
200 	unsigned int selected = m_widgetrack_schedule->GetSelected();
201 	if(selected != WidgetRack::NO_SELECTION) {
202 		m_widgetrack_schedule->RemoveWidget(selected);
203 		if(selected < m_widgetrack_schedule->GetWidgetCount()) {
204 			m_widgetrack_schedule->SetSelected(selected);
205 		} else if(m_widgetrack_schedule->GetWidgetCount() != 0) {
206 			m_widgetrack_schedule->SetSelected(m_widgetrack_schedule->GetWidgetCount() - 1);
207 		}
208 	}
209 }
210 
OnMoveUp()211 void DialogRecordSchedule::OnMoveUp() {
212 	unsigned int selected = m_widgetrack_schedule->GetSelected();
213 	if(selected != WidgetRack::NO_SELECTION && selected > 0) {
214 		m_widgetrack_schedule->MoveWidget(selected, selected - 1);
215 		m_widgetrack_schedule->MakeVisible(m_widgetrack_schedule->GetWidget(selected - 1));
216 	}
217 }
218 
OnMoveDown()219 void DialogRecordSchedule::OnMoveDown() {
220 	unsigned int selected = m_widgetrack_schedule->GetSelected();
221 	if(selected != WidgetRack::NO_SELECTION && selected < m_widgetrack_schedule->GetWidgetCount() - 1) {
222 		m_widgetrack_schedule->MoveWidget(selected, selected + 1);
223 		m_widgetrack_schedule->MakeVisible(m_widgetrack_schedule->GetWidget(selected + 1));
224 	}
225 }
226 
OnWriteBack()227 void DialogRecordSchedule::OnWriteBack() {
228 	m_parent->SetScheduleTimeZone((enum_schedule_time_zone) m_combobox_timezone->currentIndex());
229 	std::vector<ScheduleEntry> schedule(m_widgetrack_schedule->GetWidgetCount());
230 	for(unsigned int i = 0; i < m_widgetrack_schedule->GetWidgetCount(); ++i) {
231 		RecordScheduleEntryWidget *widget = static_cast<RecordScheduleEntryWidget*>(m_widgetrack_schedule->GetWidget(i));
232 		schedule[i].time = widget->GetTime();
233 		schedule[i].action = widget->GetAction();
234 	}
235 	m_parent->SetScheduleEntries(schedule);
236 }
237