1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the examples of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
9 | ** You may use this file under the terms of the BSD license as follows: |
10 | ** |
11 | ** "Redistribution and use in source and binary forms, with or without |
12 | ** modification, are permitted provided that the following conditions are |
13 | ** met: |
14 | ** * Redistributions of source code must retain the above copyright |
15 | ** notice, this list of conditions and the following disclaimer. |
16 | ** * Redistributions in binary form must reproduce the above copyright |
17 | ** notice, this list of conditions and the following disclaimer in |
18 | ** the documentation and/or other materials provided with the |
19 | ** distribution. |
20 | ** * Neither the name of The Qt Company Ltd nor the names of its |
21 | ** contributors may be used to endorse or promote products derived |
22 | ** from this software without specific prior written permission. |
23 | ** |
24 | ** |
25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
36 | ** |
37 | ** $QT_END_LICENSE$ |
38 | ** |
39 | ****************************************************************************/ |
40 | #include "eventeditpage.h" |
41 | |
42 | #include <QtWidgets> |
43 | #include <QtOrganizer/qorganizer.h> |
44 | |
45 | QTORGANIZER_USE_NAMESPACE |
46 | |
47 | EventEditPage::EventEditPage(QWidget *parent) |
48 | :QWidget(parent), |
49 | m_manager(0), |
50 | m_alarmComboBox(0), |
51 | m_typeComboBox(0), |
52 | m_subjectEdit(0), |
53 | m_countSpinBox(0), |
54 | m_repeatUntilDate(0) |
55 | { |
56 | //create asynch request to save an item |
57 | m_saveItemRequest = new QOrganizerItemSaveRequest(this); |
58 | // Create widgets |
59 | QLabel *subjectLabel = new QLabel("Subject:" , this); |
60 | m_subjectEdit = new QLineEdit(this); |
61 | QLabel *startTimeLabel = new QLabel("Start time:" , this); |
62 | m_startTimeEdit = new QDateTimeEdit(this); |
63 | m_startTimeEdit->setDisplayFormat(QString("yyyy-MM-dd hh:mm:ss AP" )); |
64 | QLabel *endTimeLabel = new QLabel("End time:" , this); |
65 | m_endTimeEdit = new QDateTimeEdit(this); |
66 | m_endTimeEdit->setDisplayFormat(QString("yyyy-MM-dd hh:mm:ss AP" )); |
67 | QLabel *repeatLabel = new QLabel("Repeat:" , this); |
68 | QLabel *alarmLabel = new QLabel("Alarm:" , this); |
69 | QLabel *calendarLabel = new QLabel("Calendar:" , this); |
70 | m_alarmComboBox = new QComboBox(this); |
71 | m_typeComboBox = new QComboBox(this); |
72 | m_typeComboBox->addItem(atext: "None" ); |
73 | m_typeComboBox->addItem(atext: "Daily" ); |
74 | m_typeComboBox->addItem(atext: "Weekly" ); |
75 | m_typeComboBox->addItem(atext: "Monthly" ); |
76 | m_typeComboBox->addItem(atext: "Yearly" ); |
77 | connect(sender: m_typeComboBox, SIGNAL(currentIndexChanged(const QString&)), receiver: this, |
78 | SLOT(frequencyChanged(const QString&))); |
79 | QStringList alarmList; |
80 | alarmList << "None" |
81 | << "0 minutes before" |
82 | << "5 minutes before" |
83 | << "15 minutes before" |
84 | << "30 minutes before" |
85 | << "1 hour before" ; |
86 | m_alarmComboBox->addItems(texts: alarmList); |
87 | connect(sender: m_alarmComboBox, SIGNAL(currentIndexChanged(const QString)), receiver: this, |
88 | SLOT(alarmIndexChanged(const QString))); |
89 | |
90 | m_endConditionComboBox = new QComboBox(this); |
91 | m_endConditionComboBox->addItem(atext: "Forever" ); |
92 | m_endConditionComboBox->addItem(atext: "Until a date" ); |
93 | m_endConditionComboBox->addItem(atext: "For a number of occurrences" ); |
94 | m_endConditionComboBox->setVisible(false); |
95 | connect(sender: m_endConditionComboBox, SIGNAL(currentIndexChanged(const QString&)), |
96 | receiver: this, SLOT(endConditionChanged(const QString&))); |
97 | |
98 | m_countSpinBox = new QSpinBox(this); |
99 | m_countSpinBox->setRange(min: 1, max: 100); |
100 | m_countSpinBox->setSingleStep(1); |
101 | m_countSpinBox->setVisible(false); |
102 | connect(sender: m_countSpinBox, SIGNAL(valueChanged(int)), receiver: this, SLOT(countChanged(int))); |
103 | |
104 | m_repeatUntilDate = new QDateEdit(this); |
105 | m_repeatUntilDate->setVisible(false); |
106 | connect(sender: m_repeatUntilDate, SIGNAL(dateChanged(QDate)), receiver: this, SLOT(untilChanged(QDate))); |
107 | |
108 | m_calendarComboBox = new QComboBox(this); |
109 | // the calendar names are not know here, fill the combo box later... |
110 | |
111 | // Add push buttons |
112 | QHBoxLayout* hbLayout = new QHBoxLayout(); |
113 | QPushButton *okButton = new QPushButton("Save" , this); |
114 | connect(sender: okButton,SIGNAL(clicked()),receiver: this,SLOT(saveClicked())); |
115 | hbLayout->addWidget(okButton); |
116 | QPushButton *cancelButton = new QPushButton("Cancel" , this); |
117 | connect(sender: cancelButton,SIGNAL(clicked()),receiver: this,SLOT(cancelClicked())); |
118 | hbLayout->addWidget(cancelButton); |
119 | |
120 | // check to see whether we support alarms. |
121 | QOrganizerManager defaultManager; |
122 | QList<QOrganizerItemDetail::DetailType> supportedDetails = defaultManager.supportedItemDetails(itemType: QOrganizerItemType::TypeEvent); |
123 | |
124 | QVBoxLayout *scrollAreaLayout = new QVBoxLayout(); |
125 | scrollAreaLayout->addWidget(subjectLabel); |
126 | scrollAreaLayout->addWidget(m_subjectEdit); |
127 | scrollAreaLayout->addWidget(startTimeLabel); |
128 | scrollAreaLayout->addWidget(m_startTimeEdit); |
129 | scrollAreaLayout->addWidget(endTimeLabel); |
130 | scrollAreaLayout->addWidget(m_endTimeEdit); |
131 | if (supportedDetails.contains(t: QOrganizerItemDetail::TypeVisualReminder)) { |
132 | scrollAreaLayout->addWidget(alarmLabel); |
133 | scrollAreaLayout->addWidget(m_alarmComboBox); |
134 | } |
135 | scrollAreaLayout->addWidget(repeatLabel); |
136 | scrollAreaLayout->addWidget(m_typeComboBox); |
137 | scrollAreaLayout->addWidget(m_endConditionComboBox); |
138 | scrollAreaLayout->addWidget(m_countSpinBox); |
139 | scrollAreaLayout->addWidget(m_repeatUntilDate); |
140 | scrollAreaLayout->addWidget(calendarLabel); |
141 | scrollAreaLayout->addWidget(m_calendarComboBox); |
142 | scrollAreaLayout->addStretch(); |
143 | scrollAreaLayout->addLayout(layout: hbLayout); |
144 | |
145 | QScrollArea *scrollArea = new QScrollArea(this); |
146 | scrollArea->setWidgetResizable(true); |
147 | QWidget *formContainer = new QWidget(scrollArea); |
148 | formContainer->setLayout(scrollAreaLayout); |
149 | scrollArea->setWidget(formContainer); |
150 | |
151 | QVBoxLayout *mainLayout = new QVBoxLayout(); |
152 | mainLayout->addWidget(scrollArea); |
153 | setLayout(mainLayout); |
154 | |
155 | m_listOfEvents.clear(); |
156 | } |
157 | |
158 | EventEditPage::~EventEditPage() |
159 | { |
160 | |
161 | } |
162 | |
163 | void EventEditPage::eventChanged(QOrganizerManager *manager, const QOrganizerEvent &event) |
164 | { |
165 | m_manager = manager; |
166 | m_organizerEvent = event; |
167 | m_subjectEdit->setText(event.displayLabel()); |
168 | m_startTimeEdit->setDateTime(event.startDateTime()); |
169 | m_endTimeEdit->setDateTime(event.endDateTime()); |
170 | QSet<QOrganizerRecurrenceRule> rrules(m_organizerEvent.recurrenceRules()); |
171 | // Check whether existing entry and if it is repeating. |
172 | if (rrules.count() != 0) { |
173 | QOrganizerRecurrenceRule rrule(rrules.values().at(i: 0)); |
174 | QOrganizerRecurrenceRule::Frequency freq(rrule.frequency()); |
175 | switch (freq) { |
176 | case QOrganizerRecurrenceRule::Daily: |
177 | m_typeComboBox->setCurrentIndex(1); |
178 | break; |
179 | case QOrganizerRecurrenceRule::Weekly: |
180 | m_typeComboBox->setCurrentIndex(2); |
181 | break; |
182 | case QOrganizerRecurrenceRule::Monthly: |
183 | m_typeComboBox->setCurrentIndex(3); |
184 | break; |
185 | case QOrganizerRecurrenceRule::Yearly: |
186 | m_typeComboBox->setCurrentIndex(4); |
187 | break; |
188 | case QOrganizerRecurrenceRule::Invalid: |
189 | m_typeComboBox->setCurrentIndex(0); // No repeat |
190 | return; |
191 | } |
192 | if (rrule.limitType() == QOrganizerRecurrenceRule::DateLimit) { |
193 | m_endConditionComboBox->setCurrentIndex(1); // End date specified |
194 | m_repeatUntilDate->setDate(rrule.limitDate()); |
195 | } else if (rrule.limitType() == QOrganizerRecurrenceRule::CountLimit) { |
196 | m_endConditionComboBox->setCurrentIndex(2); // Count specified |
197 | m_countSpinBox->setValue(rrule.limitCount()); |
198 | } |
199 | } else { |
200 | m_typeComboBox->setCurrentIndex(0); // No repeat |
201 | } |
202 | |
203 | // set calendar selection |
204 | m_calendarComboBox->clear(); |
205 | |
206 | QOrganizerItemReminder reminder = event.detail(detailType: QOrganizerItemDetail::TypeReminder); |
207 | if (!reminder.isEmpty()) { |
208 | // Alarm combo is only able to handle certain time limits correctly; for example time |
209 | // limit 3 minutes is rounded up to 5 minutes |
210 | if (reminder.secondsBeforeStart() == 0) |
211 | m_alarmComboBox->setCurrentIndex(1); |
212 | else if (reminder.secondsBeforeStart() < 300) |
213 | m_alarmComboBox->setCurrentIndex(2); |
214 | else if (reminder.secondsBeforeStart() < 900) |
215 | m_alarmComboBox->setCurrentIndex(3); |
216 | else if (reminder.secondsBeforeStart() < 1800) |
217 | m_alarmComboBox->setCurrentIndex(4); |
218 | else |
219 | m_alarmComboBox->setCurrentIndex(5); |
220 | } else { |
221 | m_alarmComboBox->setCurrentIndex(0); |
222 | } |
223 | |
224 | // resolve metadata field that contains calendar name (if any) |
225 | m_collections = m_manager->collections(); |
226 | int index = 0; |
227 | int eventCalendarIndex = -1; |
228 | foreach(QOrganizerCollection collection, m_collections) { |
229 | // We currently have no way of stringifying ids |
230 | //QString visibleName = "Calendar id = " + QString::number(collection.id().localId()); |
231 | QString visibleName = collection.metaData(key: QOrganizerCollection::KeyName).toString(); |
232 | if (visibleName.isEmpty()) |
233 | visibleName = "Calendar " + QString::number(index); |
234 | |
235 | m_calendarComboBox->addItem(atext: visibleName); |
236 | if (collection.id() == event.collectionId()) |
237 | eventCalendarIndex = index; |
238 | ++index; |
239 | } |
240 | |
241 | if (eventCalendarIndex > -1) { |
242 | m_calendarComboBox->setCurrentIndex(eventCalendarIndex); |
243 | m_calendarComboBox->setEnabled(false); // when modifying existing events, the calendar can't be changed anymore |
244 | } |
245 | else { |
246 | m_calendarComboBox->setEnabled(true); |
247 | } |
248 | } |
249 | |
250 | void EventEditPage::cancelClicked() |
251 | { |
252 | emit showDayPage(); |
253 | } |
254 | |
255 | void EventEditPage::saveClicked() |
256 | { |
257 | QDateTime start(m_startTimeEdit->dateTime()); |
258 | QDateTime end(m_endTimeEdit->dateTime()); |
259 | if (start > end) { |
260 | QMessageBox::warning(parent: this, title: "Failed!" , text: "Start date is not before end date" ); |
261 | return; |
262 | } |
263 | |
264 | m_organizerEvent.setDisplayLabel(m_subjectEdit->text()); |
265 | m_organizerEvent.setStartDateTime(start); |
266 | m_organizerEvent.setEndDateTime(end); |
267 | m_listOfEvents.append(t: m_organizerEvent); |
268 | if (m_calendarComboBox->currentIndex() > 0) { |
269 | m_organizerEvent.setCollectionId(m_collections[m_calendarComboBox->currentIndex()].id()); |
270 | } |
271 | m_manager->saveItem(item: &m_organizerEvent); |
272 | if (m_manager->error()) |
273 | QMessageBox::warning(parent: this, title: "Failed!" , text: QString("Failed to save event!\n(error code %1)" ).arg(a: m_manager->error())); |
274 | else |
275 | emit showDayPage(); |
276 | } |
277 | |
278 | void EventEditPage::frequencyChanged(const QString& frequency) |
279 | { |
280 | QOrganizerRecurrenceRule rrule; |
281 | |
282 | if (frequency != "None" ) { |
283 | m_endConditionComboBox->setVisible(true); |
284 | |
285 | if (frequency == "Daily" ) { |
286 | rrule.setFrequency(QOrganizerRecurrenceRule::Daily); |
287 | } else if (frequency == "Weekly" ) { |
288 | rrule.setFrequency(QOrganizerRecurrenceRule::Weekly); |
289 | } else if (frequency == "Monthly" ) { |
290 | rrule.setFrequency(QOrganizerRecurrenceRule::Monthly); |
291 | } else if (frequency == "Yearly" ) { |
292 | rrule.setFrequency(QOrganizerRecurrenceRule::Yearly); |
293 | } |
294 | m_organizerEvent.setRecurrenceRule(rrule); |
295 | } else { |
296 | m_endConditionComboBox->setCurrentIndex(0); |
297 | m_endConditionComboBox->setVisible(false); |
298 | } |
299 | } |
300 | |
301 | void EventEditPage::alarmIndexChanged(const QString time) |
302 | { |
303 | bool noVisualReminders = !m_manager->supportedItemDetails(itemType: QOrganizerItemType::TypeEvent).contains(t: QOrganizerItemDetail::TypeVisualReminder); |
304 | |
305 | QScopedPointer<QOrganizerItemReminder> reminder; |
306 | if (noVisualReminders) { |
307 | reminder.reset(other: new QOrganizerItemReminder()); |
308 | } else { |
309 | reminder.reset(other: new QOrganizerItemVisualReminder()); |
310 | static_cast<QOrganizerItemVisualReminder *>(reminder.data())->setMessage(m_subjectEdit->text()); |
311 | } |
312 | |
313 | if (time == "None" ) { |
314 | QOrganizerItemVisualReminder fetchedReminder = m_organizerEvent.detail(detailType: QOrganizerItemDetail::TypeVisualReminder); |
315 | m_organizerEvent.removeDetail(detail: &fetchedReminder); |
316 | return; |
317 | } else if (time == "0 minutes before" ) { |
318 | reminder->setSecondsBeforeStart(0); |
319 | } else if (time == "5 minutes before" ) { |
320 | reminder->setSecondsBeforeStart(5*60); |
321 | } else if (time == "15 minutes before" ) { |
322 | reminder->setSecondsBeforeStart(15*60); |
323 | } else if (time == "30 minutes before" ) { |
324 | reminder->setSecondsBeforeStart(30*60); |
325 | } else if (time == "1 hour before" ) { |
326 | reminder->setSecondsBeforeStart(60*60); |
327 | } |
328 | |
329 | m_organizerEvent.saveDetail(detail: reminder.data()); |
330 | } |
331 | |
332 | void EventEditPage::showEvent(QShowEvent *event) |
333 | { |
334 | window()->setWindowTitle("Edit event" ); |
335 | QWidget::showEvent(event); |
336 | } |
337 | |
338 | void EventEditPage::countChanged(int i) |
339 | { |
340 | QOrganizerRecurrenceRule rrule; |
341 | rrule.setFrequency(m_organizerEvent.recurrenceRules().values().at(i: 0).frequency()); |
342 | rrule.setLimit(i); |
343 | m_organizerEvent.setRecurrenceRule(rrule); |
344 | } |
345 | |
346 | void EventEditPage::untilChanged(QDate date) |
347 | { |
348 | QOrganizerRecurrenceRule rrule; |
349 | rrule.setFrequency(m_organizerEvent.recurrenceRules().values().at(i: 0).frequency()); |
350 | rrule.setLimit(date); |
351 | m_organizerEvent.setRecurrenceRule(rrule); |
352 | } |
353 | |
354 | void EventEditPage::endConditionChanged(const QString& endCondition) { |
355 | if (endCondition == "Forever" ) { |
356 | m_countSpinBox->setVisible(false); |
357 | m_repeatUntilDate->setVisible(false); |
358 | } else if (endCondition == "Until a date" ) { |
359 | setRepeatUntilField(); |
360 | } else if (endCondition == "For a number of occurrences" ) { |
361 | setCountField(); |
362 | } |
363 | } |
364 | |
365 | void EventEditPage::setCountField() |
366 | { |
367 | m_countSpinBox->setVisible(true); |
368 | m_repeatUntilDate->setVisible(false); |
369 | m_countSpinBox->setValue(5); |
370 | countChanged(i: 5); // default value. |
371 | } |
372 | |
373 | void EventEditPage::setRepeatUntilField() |
374 | { |
375 | m_countSpinBox->setVisible(false); |
376 | m_repeatUntilDate->setVisible(true); |
377 | m_repeatUntilDate->setDate(m_endTimeEdit->date()); |
378 | untilChanged(date: m_endTimeEdit->date()); // default value. |
379 | } |
380 | |