#include "calendardemo.h"
#include "monthpage.h"
#include "daypage.h"
#include "eventeditpage.h"
#include "todoeditpage.h"
#include "journaleditpage.h"
#include "eventoccurrenceeditpage.h"
#include "addcalendarpage.h"
#include "editcalendarspage.h"
#ifdef BUILD_VERSIT
#include "qversitreader.h"
#include "qversitwriter.h"
#include "qversitorganizerimporter.h"
#include "qversitorganizerexporter.h"
#endif
#include <QtWidgets>
#include <QDesktopServices>
#include <qorganizer.h>
QTORGANIZER_USE_NAMESPACE
CalendarDemo::CalendarDemo(QWidget *parent)
:QMainWindow(parent),
m_stackedWidget(0),
m_monthPage(0),
m_dayPage(0),
m_eventEditPage(0),
m_eventOccurrenceEditPage(0)
{
m_stackedWidget = new QStackedWidget(this);
m_dayPage = new DayPage(m_stackedWidget);
m_monthPage = new MonthPage(m_stackedWidget);
m_eventEditPage = new EventEditPage(m_stackedWidget);
m_todoEditPage = new TodoEditPage(m_stackedWidget);
m_journalEditPage = new JournalEditPage(m_stackedWidget);
m_eventOccurrenceEditPage = new EventOccurrenceEditPage(m_stackedWidget);
m_addCalendarPage = new AddCalendarPage(m_stackedWidget);
m_editCalendarsPage = new EditCalendarsPage(m_stackedWidget);
qRegisterMetaType<QOrganizerItem>("QOrganizerItem");
qRegisterMetaType<QOrganizerItemId>("QOrganizerItemId");
qRegisterMetaType<QOrganizerCollection>("QOrganizerCollection");
qRegisterMetaType<QOrganizerAbstractRequest::State>("QOrganizerAbstractRequest::State");
connect(m_monthPage, SIGNAL(showDayPage(QDate)), this, SLOT(activateDayPage()), Qt::QueuedConnection);
connect(m_monthPage, SIGNAL(showEditPage(const QOrganizerItem &)), this, SLOT(activateEditPage(const QOrganizerItem &)), Qt::QueuedConnection);
connect(m_monthPage, SIGNAL(addNewEvent()), this, SLOT(addNewEvent()), Qt::QueuedConnection);
connect(m_monthPage, SIGNAL(addNewTodo()), this, SLOT(addNewTodo()), Qt::QueuedConnection);
connect(m_monthPage, SIGNAL(managerChanged(QOrganizerManager*)), this, SLOT(changeManager(QOrganizerManager*)), Qt::QueuedConnection);
connect(m_monthPage, SIGNAL(managerChanged(QOrganizerManager*)), m_dayPage, SLOT(changeManager(QOrganizerManager*)), Qt::QueuedConnection);
connect(m_monthPage, SIGNAL(currentDayChanged(QDate)), this, SLOT(updateSelectedDay(QDate)));
connect(m_dayPage, SIGNAL(showMonthPage()), this, SLOT(activateMonthPage()), Qt::QueuedConnection);
connect(m_dayPage, SIGNAL(showEditPage(const QOrganizerItem &)), this, SLOT(activateEditPage(const QOrganizerItem &)), Qt::QueuedConnection);
connect(m_dayPage, SIGNAL(addNewEvent()), this, SLOT(addNewEvent()), Qt::QueuedConnection);
connect(m_dayPage, SIGNAL(addNewTodo()), this, SLOT(addNewTodo()), Qt::QueuedConnection);
connect(m_eventEditPage, SIGNAL(showDayPage()), this, SLOT(activateDayPage()), Qt::QueuedConnection);
connect(m_todoEditPage, SIGNAL(showDayPage()), this, SLOT(activateDayPage()), Qt::QueuedConnection);
connect(m_journalEditPage, SIGNAL(showDayPage()), this, SLOT(activateDayPage()), Qt::QueuedConnection);
connect(m_eventOccurrenceEditPage, SIGNAL(showDayPage()), this, SLOT(activateDayPage()), Qt::QueuedConnection);
connect(m_addCalendarPage, SIGNAL(showPreviousPage()), this, SLOT(activatePreviousPage()), Qt::QueuedConnection);
connect(m_editCalendarsPage, SIGNAL(showAddCalendarPage(QOrganizerManager*,QOrganizerCollection*)), this, SLOT(editExistingCalendar(QOrganizerManager*,QOrganizerCollection*)), Qt::QueuedConnection);
connect(m_editCalendarsPage, SIGNAL(showPreviousPage()), this, SLOT(activateMonthPage()), Qt::QueuedConnection);
connect(m_editCalendarsPage, SIGNAL(addClicked()), this, SLOT(addCalendar()), Qt::QueuedConnection);
connect(&m_saveReq, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)),
this, SLOT(saveReqStateChanged(QOrganizerAbstractRequest::State)));
connect(&m_remReq, SIGNAL(stateChanged(QOrganizerAbstractRequest::State)),
this, SLOT(removeReqStateChanged(QOrganizerAbstractRequest::State)));
m_monthPage->init();
m_stackedWidget->addWidget(m_monthPage);
m_stackedWidget->addWidget(m_dayPage);
m_stackedWidget->addWidget(m_eventEditPage);
m_stackedWidget->addWidget(m_todoEditPage);
m_stackedWidget->addWidget(m_journalEditPage);
m_stackedWidget->addWidget(m_eventOccurrenceEditPage);
m_stackedWidget->addWidget(m_addCalendarPage);
m_stackedWidget->addWidget(m_editCalendarsPage);
m_stackedWidget->setCurrentIndex(0);
setCentralWidget(m_stackedWidget);
buildMenu();
activateMonthPage();
}
CalendarDemo::~CalendarDemo()
{
}
void CalendarDemo::buildMenu()
{
QMenu *optionsMenu = new QMenu("&Options", this);
menuBar()->addMenu(optionsMenu);
QOrganizerManager defaultManager;
QList<QOrganizerItemType::ItemType> supportedItemTypes = defaultManager.supportedItemTypes();
if (supportedItemTypes.contains(QOrganizerItemType::TypeEvent)) {
QAction* addEventAction = optionsMenu->addAction("Add E&vent");
connect(addEventAction, SIGNAL(triggered(bool)), this, SLOT(addNewEvent()));
}
if (supportedItemTypes.contains(QOrganizerItemType::TypeTodo)) {
QAction* addTodoAction = optionsMenu->addAction("Add &Todo");
connect(addTodoAction, SIGNAL(triggered(bool)), this, SLOT(addNewTodo()));
}
if (supportedItemTypes.contains(QOrganizerItemType::TypeJournal)) {
QAction* addJournalAction = optionsMenu->addAction("Add &Journal");
connect(addJournalAction, SIGNAL(triggered(bool)), this, SLOT(addNewJournal()));
}
optionsMenu->addSeparator();
QAction* editAction = optionsMenu->addAction("&Edit");
connect(editAction, SIGNAL(triggered(bool)), this, SLOT(editItem()));
QAction* removeAction = optionsMenu->addAction("&Remove");
connect(removeAction, SIGNAL(triggered(bool)), this, SLOT(removeItem()));
optionsMenu->addSeparator();
m_switchViewAction = optionsMenu->addAction("&Open Day");
connect(m_switchViewAction, SIGNAL(triggered(bool)), this, SLOT(switchView()));
optionsMenu->addSeparator();
QAction* addHugeEntries = optionsMenu->addAction("Add Test Events");
connect(addHugeEntries, SIGNAL(triggered(bool)), this, SLOT(addEvents()));
QAction* importItems = optionsMenu->addAction("&Import Items...");
connect(importItems, SIGNAL(triggered(bool)), this, SLOT(importItems()));
QAction* exportItems = optionsMenu->addAction("Ex&port Items...");
connect(exportItems, SIGNAL(triggered(bool)), this, SLOT(exportItems()));
QAction* deleteAllEntries = optionsMenu->addAction("Delete All Items");
connect(deleteAllEntries, SIGNAL(triggered(bool)), this, SLOT(deleteAllEntries()));
QAction* addCalendar = optionsMenu->addAction("New calendar");
connect(addCalendar, SIGNAL(triggered(bool)), this, SLOT(addCalendar()));
QAction* editCalendar = optionsMenu->addAction("Edit calendars");
connect(editCalendar, SIGNAL(triggered(bool)), this, SLOT(editCalendar()));
}
void CalendarDemo::activateMonthPage()
{
menuBar()->setVisible(true);
m_monthPage->refresh();
m_stackedWidget->setCurrentWidget(m_monthPage);
m_switchViewAction->setText("&Open Day");
}
void CalendarDemo::activateDayPage()
{
menuBar()->setVisible(true);
m_dayPage->refresh();
m_stackedWidget->setCurrentWidget(m_dayPage);
m_switchViewAction->setText("View &Month");
}
void CalendarDemo::activateEditPage(const QOrganizerItem &item)
{
m_previousItem = item;
menuBar()->setVisible(false);
if (item.type() == QOrganizerItemType::TypeEvent) {
QOrganizerEvent event = static_cast<QOrganizerEvent>(item);
m_dayPage->dayChanged(event.startDateTime().date());
m_eventEditPage->eventChanged(m_manager, event);
m_stackedWidget->setCurrentWidget(m_eventEditPage);
} else if (item.type() == QOrganizerItemType::TypeTodo) {
QOrganizerTodo todo = static_cast<QOrganizerTodo>(item);
m_dayPage->dayChanged(todo.startDateTime().date());
m_todoEditPage->todoChanged(m_manager, todo);
m_stackedWidget->setCurrentWidget(m_todoEditPage);
} else if (item.type() == QOrganizerItemType::TypeJournal) {
QOrganizerJournal journal = static_cast<QOrganizerJournal>(item);
m_dayPage->dayChanged(journal.dateTime().date());
m_journalEditPage->journalChanged(m_manager, journal);
m_stackedWidget->setCurrentWidget(m_journalEditPage);
} else if (item.type() == QOrganizerItemType::TypeEventOccurrence) {
QOrganizerEventOccurrence eventOccurrence = static_cast<QOrganizerEventOccurrence>(item);
QMessageBox msgBox;
msgBox.setText(tr("This is a recurring event"));
msgBox.setInformativeText(tr("Do you want to open this occurrence or the recurring event series?"));
QAbstractButton *occurrenceButton = msgBox.addButton(tr("Occurrence"), QMessageBox::ActionRole);
QAbstractButton *seriesButton = msgBox.addButton(tr("Series"), QMessageBox::ActionRole);
msgBox.exec();
if (msgBox.clickedButton() == seriesButton) {
QOrganizerItemId parentEventId = eventOccurrence.parentId();
QOrganizerEvent parentEvent = m_manager->item(parentEventId);
m_dayPage->dayChanged(parentEvent.startDateTime().date());
m_eventEditPage->eventChanged(m_manager, parentEvent);
m_stackedWidget->setCurrentWidget(m_eventEditPage);
} else if (msgBox.clickedButton() == occurrenceButton) {
m_dayPage->dayChanged(eventOccurrence.startDateTime().date());
m_eventOccurrenceEditPage->eventOccurrenceChanged(m_manager, eventOccurrence);
m_stackedWidget->setCurrentWidget(m_eventOccurrenceEditPage);
}
}
}
void CalendarDemo::activatePreviousPage()
{
if (m_previousPage == m_stackedWidget->indexOf(m_monthPage))
activateMonthPage();
else if (m_previousPage == m_stackedWidget->indexOf(m_dayPage))
activateDayPage();
else if (m_previousPage == m_stackedWidget->indexOf(m_editCalendarsPage))
editCalendar();
else
activateEditPage(m_previousItem);
}
void CalendarDemo::addNewEvent()
{
QOrganizerEvent newEvent;
QDateTime time(m_currentDate);
newEvent.setStartDateTime(time);
time = time.addSecs(60*30);
newEvent.setEndDateTime(time);
activateEditPage(newEvent);
}
void CalendarDemo::addNewTodo()
{
QOrganizerTodo newTodo;
QDateTime time(m_currentDate);
newTodo.setStartDateTime(time);
time = time.addSecs(60*30);
newTodo.setDueDateTime(time);
activateEditPage(newTodo);
}
void CalendarDemo::addNewJournal()
{
QOrganizerJournal newJournal;
QDateTime time(m_currentDate);
newJournal.setDateTime(time);
activateEditPage(newJournal);
}
void CalendarDemo::switchView()
{
if (m_stackedWidget->currentWidget() == m_dayPage) {
activateMonthPage();
} else if (m_stackedWidget->currentWidget() == m_monthPage) {
activateDayPage();
}
}
void CalendarDemo::editItem()
{
if (m_stackedWidget->currentWidget() == m_dayPage) {
m_dayPage->editItem();
} else if (m_stackedWidget->currentWidget() == m_monthPage) {
m_monthPage->editItem();
}
}
void CalendarDemo::removeItem()
{
if (m_stackedWidget->currentWidget() == m_dayPage) {
m_dayPage->removeItem();
} else if (m_stackedWidget->currentWidget() == m_monthPage) {
m_monthPage->removeItem();
}
}
void CalendarDemo::addEvents()
{
QList<QOrganizerItem> items;
QOrganizerCollectionId defaultCollectionId = m_manager->defaultCollection().id();
for(int index=0 ; index < 100 ; index++) {
QOrganizerItem item;
item.setType(QOrganizerItemType::TypeEvent);
item.setDescription(QString("Event %1").arg(index));
item.setDisplayLabel(QString("Subject for event %1").arg(index + 1));
QOrganizerEventTime timeRange;
timeRange.setStartDateTime(QDateTime::currentDateTime().addDays(index));
timeRange.setEndDateTime(QDateTime::currentDateTime().addDays(index).addSecs(60 * 60));
item.saveDetail(&timeRange);
item.setCollectionId(defaultCollectionId);
items.append(item);
}
m_saveReq.setItems(items);
m_saveReq.setManager(m_manager);
m_saveReq.start();
}
void CalendarDemo::importItems()
{
#ifdef BUILD_VERSIT
QString messageTitle(tr("Import of Items failed"));
if (!m_manager) {
QMessageBox::warning(this, messageTitle, tr("No manager selected; cannot import"));
return;
}
QString docPath = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
if (docPath.isEmpty())
docPath = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
if (docPath.isEmpty())
docPath = ".";
QString fileName = QFileDialog::getOpenFileName(this,
tr("Select iCalendar file"), docPath, tr("iCalendar files (*.ics)"));
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly) || !file.isReadable()){
QMessageBox::warning(this, messageTitle, tr("Unable to read from file: %1").arg(fileName));
return;
}
QVersitReader reader;
reader.setDevice(&file);
if (!reader.startReading() || !reader.waitForFinished()) {
QMessageBox::warning(this, messageTitle, tr("Versit reader failed: %1").arg(reader.error()));
return;
}
QVersitOrganizerImporter importer;
QList<QOrganizerItem> allItems;
QString errorMessage;
foreach (const QVersitDocument& document, reader.results()) {
if (!importer.importDocument(document)) {
errorMessage += tr("Import failed,");
QMap<int, QVersitOrganizerImporter::Error>::const_iterator iterator = importer.errorMap().constBegin();
while(iterator != importer.errorMap().constEnd()){
switch (iterator.value()){
case QVersitOrganizerImporter::InvalidDocumentError:
errorMessage += QString(" index %1:").arg(iterator.key());
errorMessage += tr("One of the documents is not an iCalendar file");
break;
case QVersitOrganizerImporter::EmptyDocumentError:
errorMessage += QString(" index %1:").arg(iterator.key());
errorMessage += tr("One of the documents is empty");
break;
default:
errorMessage += QString(" index %1:").arg(iterator.key());
errorMessage += tr("Unknown error");
}
++iterator;
}
errorMessage += QLatin1String("\n");
continue;
}
QList<QOrganizerItem> items = importer.items();
foreach (const QOrganizerItem& item, items) {
allItems.append(item);
}
}
if (!errorMessage.isEmpty())
QMessageBox::warning(this, messageTitle, errorMessage);
m_manager->saveItems(&allItems);
m_monthPage->refresh();
m_dayPage->refresh();
#endif
}
void CalendarDemo::exportItems()
{
#ifdef BUILD_VERSIT
QString messageTitle(tr("Export of Items failed"));
if (!m_manager) {
QMessageBox::warning(this, messageTitle, tr("No manager selected; cannot export"));
return;
}
QString docPath = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
if (docPath.isEmpty())
docPath = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
if (docPath.isEmpty())
docPath = ".";
docPath.append("/calendar.ics");
QString fileName = QFileDialog::getSaveFileName(this, tr("Save iCalendar"),
docPath,
tr("iCalendar files (*.ics)"));
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly) || !file.isWritable()) {
QMessageBox::warning(this, messageTitle, tr("Unable to write to file: %1").arg(fileName));
return;
}
QList<QOrganizerItem> items(m_manager->itemsForExport());
QVersitOrganizerExporter exporter;
QString errorMessage;
if (!exporter.exportItems(items)) {
errorMessage += tr("Export failed,");
QMap<int, QVersitOrganizerExporter::Error>::const_iterator iterator = exporter.errorMap().constBegin();
while(iterator != exporter.errorMap().constEnd()){
switch (iterator.value()){
case QVersitOrganizerExporter::EmptyOrganizerError:
errorMessage += QString(" index %1:").arg(iterator.key());
errorMessage += tr("One of the documents is not an iCalendar file");
break;
case QVersitOrganizerExporter::UnknownComponentTypeError:
errorMessage += QString(" index %1:").arg(iterator.key());
errorMessage += tr("One of the components in the iCalendar file is"
" not supported");
break;
case QVersitOrganizerExporter::UnderspecifiedOccurrenceError:
errorMessage += QString(" index %1:").arg(iterator.key());
errorMessage += tr("An event or todo exception was found which"
" did not specify both its parent and a specifier for"
" which instance to override");
break;
default:
errorMessage += QString(" index %1:%2 ").arg(iterator.key())
.arg(tr("Unknown error"));
}
++iterator;
}
errorMessage += QLatin1String("\n");
if (!errorMessage.isEmpty()){
QMessageBox::warning(this, messageTitle, errorMessage);
return;
}
}
QVersitDocument document = exporter.document();
QVersitWriter writer;
writer.setDevice(&file);
if (!writer.startWriting(QList<QVersitDocument>() << document)
|| !writer.waitForFinished()) {
QMessageBox::warning(this, messageTitle,
tr("Versit writing of organizer items failed: %1").arg(writer.error()));
}
#endif
}
void CalendarDemo::deleteAllEntries()
{
QList<QOrganizerItemId> ids = m_manager->itemIds();
if(ids.count()) {
m_remReq.setItemIds(ids);
m_remReq.setManager(m_manager);
m_remReq.start();
}
}
void CalendarDemo::addCalendar()
{
QOrganizerCollection defaultCollection = m_manager->defaultCollection();
QOrganizerCollection newCollection = defaultCollection;
newCollection.setId(QOrganizerCollectionId());
m_addCalendarPage->calendarChanged(m_manager, newCollection);
m_previousPage = m_stackedWidget->currentIndex();
m_stackedWidget->setCurrentWidget(m_addCalendarPage);
}
void CalendarDemo::editCalendar()
{
m_editCalendarsPage->showPage(m_manager);
m_previousPage = m_stackedWidget->currentIndex();
m_stackedWidget->setCurrentWidget(m_editCalendarsPage);
}
void CalendarDemo::editExistingCalendar(QOrganizerManager *manager, QOrganizerCollection* calendar)
{
m_addCalendarPage->calendarChanged(manager, *calendar);
m_previousPage = m_stackedWidget->currentIndex();
m_stackedWidget->setCurrentWidget(m_addCalendarPage);
}
void CalendarDemo::saveReqStateChanged(QOrganizerAbstractRequest::State reqState)
{
if(QOrganizerAbstractRequest::ActiveState == reqState) {
m_progressDlg = new QProgressDialog("Saving events..", "Cancel", 100, 100, this);
connect(m_progressDlg, SIGNAL(canceled()), &m_saveReq, SLOT(cancel()));
m_progressDlg->show();
} else if (QOrganizerAbstractRequest::FinishedState == reqState ||
QOrganizerAbstractRequest::CanceledState == reqState) {
m_progressDlg->hide();
m_monthPage->refresh();
m_dayPage->refresh();
}
}
void CalendarDemo::removeReqStateChanged(QOrganizerAbstractRequest::State reqState)
{
if(QOrganizerAbstractRequest::ActiveState == reqState) {
m_progressDlg = new QProgressDialog("Removing events..", "Cancel", 100, 100, this);
connect(m_progressDlg, SIGNAL(canceled()), &m_remReq, SLOT(cancel()));
m_progressDlg->show();
} else if (QOrganizerAbstractRequest::FinishedState == reqState ||
QOrganizerAbstractRequest::CanceledState == reqState) {
m_progressDlg->hide();
m_monthPage->refresh();
m_dayPage->refresh();
}
}
void CalendarDemo::changeManager(QOrganizerManager *manager)
{
m_manager = manager;
}
void CalendarDemo::updateSelectedDay(const QDate& date)
{
m_dayPage->dayChanged(date);
m_currentDate = date;
}