From 218e501cb1531ee7f99a87da54e38b5470577979 Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Sat, 10 Jul 2010 17:53:32 +0200 Subject: [PATCH] Major new release: Several events can now be defined and one can set events to occur only on given days. Brand new UI too. --- Changelog | 5 ++ TimedSilencer.pro | 20 ++++- TimedSilencer.pro.user | 2 +- alarmd_backend.h | 170 +++++++++++++++++++++++++---------- checklistdelegate.cpp | 52 +++++++++++ checklistdelegate.h | 31 +++++++ eventlistdelegate.cpp | 50 +++++++++++ eventlistdelegate.h | 30 +++++++ main.cpp | 2 +- mainwindow.cpp | 99 ++++----------------- mainwindow.h | 15 ++-- newalarmdlg.cpp | 185 +++++++++++++++++++++++++++++++++++++++ newalarmdlg.h | 57 ++++++++++++ profileevent.h | 161 ++++++++++++++++++++++++++++++++++ qmaemo5weekdayspickselector.cpp | 50 +++++++++++ qmaemo5weekdayspickselector.h | 44 ++++++++++ qmaemo5weekdayspickwidget.cpp | 139 +++++++++++++++++++++++++++++ qmaemo5weekdayspickwidget.h | 48 ++++++++++ switchingeventlist.cpp | 164 ++++++++++++++++++++++++++++++++++ switchingeventlist.h | 51 +++++++++++ 20 files changed, 1232 insertions(+), 143 deletions(-) create mode 100644 checklistdelegate.cpp create mode 100644 checklistdelegate.h create mode 100644 eventlistdelegate.cpp create mode 100644 eventlistdelegate.h create mode 100644 newalarmdlg.cpp create mode 100644 newalarmdlg.h create mode 100644 profileevent.h create mode 100644 qmaemo5weekdayspickselector.cpp create mode 100644 qmaemo5weekdayspickselector.h create mode 100644 qmaemo5weekdayspickwidget.cpp create mode 100644 qmaemo5weekdayspickwidget.h create mode 100644 switchingeventlist.cpp create mode 100644 switchingeventlist.h diff --git a/Changelog b/Changelog index 5a4ed5a..52ddda4 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,8 @@ +* Unreleased - Christophe Dumez - v0.6 + - Entirely new UI + - Several profile switching events can now be set + - Events can be defined for given days only + * Mon Jul 7 2010 - Christophe Dumez - v0.5 - Make sure settings are only saved when the "Save" button is pressed - Daily profile switching is now deactivated as a default diff --git a/TimedSilencer.pro b/TimedSilencer.pro index c7b33e3..9b76a78 100644 --- a/TimedSilencer.pro +++ b/TimedSilencer.pro @@ -16,12 +16,25 @@ TEMPLATE = app SOURCES += main.cpp\ - mainwindow.cpp + mainwindow.cpp \ + newalarmdlg.cpp \ + switchingeventlist.cpp \ + qmaemo5weekdayspickselector.cpp \ + qmaemo5weekdayspickwidget.cpp \ + checklistdelegate.cpp \ + eventlistdelegate.cpp HEADERS += mainwindow.h \ alarmd_backend.h \ dbus_backend.h \ - phone_profile.h + phone_profile.h \ + newalarmdlg.h \ + switchingeventlist.h \ + qmaemo5weekdayspickselector.h \ + qmaemo5weekdayspickwidget.h \ + checklistdelegate.h \ + profileevent.h \ + eventlistdelegate.h # Translations TRANSLATIONS = $$LANG_PATH/timedsilencer_en.ts \ @@ -30,7 +43,7 @@ TRANSLATIONS = $$LANG_PATH/timedsilencer_en.ts \ RESOURCES = lang.qrc -DEFINES += QT_NO_DEBUG_OUTPUT +#DEFINES += QT_NO_DEBUG_OUTPUT # INSTALL unix { @@ -64,4 +77,3 @@ unix { icon64.path = $$DATADIR/icons/hicolor/64x64/apps icon64.files += ico/64x64/$${TARGET}.png } - diff --git a/TimedSilencer.pro.user b/TimedSilencer.pro.user index 8f553ad..0a399d8 100644 --- a/TimedSilencer.pro.user +++ b/TimedSilencer.pro.user @@ -138,7 +138,7 @@ 16 2010-06-29T00:09:20 - 2010-07-07T09:57:55 + 2010-07-10T17:45:09 1 diff --git a/alarmd_backend.h b/alarmd_backend.h index 68b7fe9..8d8746b 100644 --- a/alarmd_backend.h +++ b/alarmd_backend.h @@ -21,11 +21,14 @@ #include #include #include +#include #include #include #include #include "phone_profile.h" +#include "dbus_backend.h" +#include "profileevent.h" // Alarmd documentation found at: // http://wiki.maemo.org/Documentation/Maemo_5_Developer_Guide/Using_Generic_Platform_Components/Alarm_Framework @@ -42,45 +45,117 @@ private: return (time_t) time(0) + time_diff; } + static uint32_t daysToMask(QList days) { + uint32_t mask = 0; + foreach(const int& d, days) { + switch(d) { + case MON: + mask |= ALARM_RECUR_WDAY_MON; + break; + case TUE: + mask |= ALARM_RECUR_WDAY_TUE; + break; + case WED: + mask |= ALARM_RECUR_WDAY_WED; + break; + case THU: + mask |= ALARM_RECUR_WDAY_THU; + break; + case FRI: + mask |= ALARM_RECUR_WDAY_FRI; + break; + case SAT: + mask |= ALARM_RECUR_WDAY_SAT; + break; + case SUN: + mask |= ALARM_RECUR_WDAY_SUN; + break; + default: + Q_ASSERT(0); // Should never go here + mask |= ALARM_RECUR_WDAY_ALL; + break; + } + } + return mask; + } + public: - static void deleteEvents() { - // Get events cookies + // Is only called on program uninstall + static void deleteAllEvents() { QSettings settings("TimedSilencer", "TimedSilencer"); - const cookie_t silent_cookie = settings.value("silencing_cookie", 0).toLongLong(); - if(silent_cookie != 0) { - qDebug("Deleting silent profile event with cookie %ld", (long) silent_cookie); - alarmd_event_del(silent_cookie); + QHash events = settings.value("events").toHash(); + foreach(QVariant var_ev, events) { + ProfileEvent *pe = ProfileEvent::load(var_ev); + foreach(const long &cookie, pe->alarmd_cookies) { + qDebug("Unregistering event with cookie %ld", cookie); + alarmd_event_del(cookie); + } + delete pe; } - const cookie_t general_cookie = settings.value("unsilencing_cookie", 0).toLongLong(); - if(general_cookie != 0) { - qDebug("Deleting general profile event with cookie %ld", (long) general_cookie); - alarmd_event_del(general_cookie); + // Save in QSettings + events.clear(); + settings.setValue("events", events); + } + + static void deleteEvents(QByteArray event_id) { + deleteEvents(ProfileEvent::findByID(event_id)); + } + + static void deleteEvents(ProfileEvent *pe) { + // unregistering events + foreach(const long &cookie, pe->alarmd_cookies) { + qDebug("Unregistering event with cookie %ld", cookie); + alarmd_event_del(cookie); } + pe->alarmd_cookies.clear(); + ProfileEvent::clearCookies(pe->getID()); } - static void setProfileEvent(Profile p, const QTime &event_time) { - // Get event cookie - QSettings settings("TimedSilencer", "TimedSilencer"); - cookie_t cookie; - if(p == SILENT) - cookie = settings.value("silencing_cookie", 0).toLongLong(); - else - cookie = settings.value("unsilencing_cookie", 0).toLongLong(); - alarm_event_t *eve = 0; - if(cookie == 0 || (eve = alarmd_event_get(cookie)) == 0) { - qDebug("Profile event does not exist yet, creating it..."); - // The event does not exist yet - newProfileEvent(p, event_time); - return; + static void setProfileEvents(QByteArray event_id) { + setProfileEvents(ProfileEvent::findByID(event_id)); + } + + static bool checkIfStillActive(ProfileEvent *pe) { + Q_ASSERT(pe->activated); + foreach(const long &cookie, pe->alarmd_cookies) { + alarm_event_t *eve = 0; + if((eve = alarmd_event_get(cookie)) != 0) { + // Free all dynamic memory associated with the alarm event + alarm_event_delete(eve); + return true; + } + } + return false; + } + + static void setProfileEvents(ProfileEvent *pe) { + Q_ASSERT(pe->activated); + // First clear old alarmd events + foreach(const long &cookie, pe->alarmd_cookies) { + qDebug("Unregistering event with cookie %ld", cookie); + alarmd_event_del(cookie); } - // Update existing event - qDebug("Updating profile event with cookie %ld", (long)cookie); - eve->alarm_time = toTime_t(event_time); - alarmd_event_update(eve); + pe->alarmd_cookies.clear(); + // Then setting new events + long c1 = newProfileEvent(SILENT, pe->from_time, pe->days); + Q_ASSERT(c1 > 0); + if(c1 > 0) + pe->alarmd_cookies << c1; + long c2 = newProfileEvent(GENERAL, pe->to_time, pe->days); + Q_ASSERT(c2 > 0); + if(c2 > 0) + pe->alarmd_cookies << c2; + // Save in QSettings + ProfileEvent::setCookies(pe->getID(), pe->alarmd_cookies); + // Set Profile to SILENT if we are currently in the silent time slot + if(pe->affectsCurrentTime()) + DBusBackend::setProfile(SILENT); } protected: - static void newProfileEvent(Profile p, const QTime &event_time) { + static long newProfileEvent(Profile p, const QTime &event_time, QList days) { + Q_ASSERT(!days.empty()); + if(days.empty()) days << NEVER; // Create the default alarm struct. alarm_event_t *newEvent = alarm_event_create(); // Set the APP ID @@ -91,9 +166,22 @@ protected: else alarm_event_set_title(newEvent, "general_profile"); // Timing - newEvent->recur_secs = 86400; // 24 hours interval - newEvent->recur_count = -1; // Reoccur infinitely - newEvent->alarm_time = toTime_t(event_time); + if(days.first() == EVERY_DAY) { + newEvent->recur_secs = 86400; // 24 hours + newEvent->recur_count = -1; // Reoccur infinitely + newEvent->alarm_time = toTime_t(event_time); // Set event time + } else { + if(days.first() == NEVER) { + newEvent->alarm_time = toTime_t(event_time); // Set event time + } else { + newEvent->recur_secs = 0; // We re not using this way for recurrence + alarm_recur_t* recur = alarm_event_add_recurrences(newEvent, 1); + // Set event time + recur->mask_hour |= (1ul << event_time.hour()); + recur->mask_min |= (1ull << event_time.minute()); + recur->mask_wday |= daysToMask(days); + } + } //Add 1 action to our alarm event, and assign it to the "act" variable alarm_action_t *act = alarm_event_add_actions(newEvent, 1); // Actions are documented here: @@ -116,20 +204,10 @@ protected: } // Finally with everything setup, try to add your event to the alarm queue - const cookie_t &cookie = alarmd_event_add(newEvent); - if(cookie != 0) { - // Save cookie - QSettings settings("TimedSilencer", "TimedSilencer"); - if(p == SILENT) { - qDebug("Saving silent profile event cookie: %ld", (long)cookie); - settings.setValue("silencing_cookie", static_cast(cookie)); - } else { - qDebug("Saving silent general event cookie: %ld", (long)cookie); - settings.setValue("unsilencing_cookie", static_cast(cookie)); - } - return; - } - qDebug("ERROR: Failed to add profile event to the queue!"); + long cookie = alarmd_event_add(newEvent); + // Free all dynamic memory associated with the alarm event + alarm_event_delete(newEvent); + return cookie; } }; diff --git a/checklistdelegate.cpp b/checklistdelegate.cpp new file mode 100644 index 0000000..427d628 --- /dev/null +++ b/checklistdelegate.cpp @@ -0,0 +1,52 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#include +#include +#include "checklistdelegate.h" + +CheckListDelegate::CheckListDelegate() +{ + +} + +void CheckListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { + // Save painter + painter->save(); + + QStyleOptionViewItem opt = option; + opt.displayAlignment = Qt::AlignCenter; + QStyledItemDelegate::paint(painter, opt, index); + + if (option.state & QStyle::State_Selected) { + // Is selected + // Draw checkbox + QIcon cbIco = QIcon::fromTheme("widgets_tickmark_list"); + QPixmap cbPix = cbIco.pixmap(cbIco.actualSize(option.decorationSize)); + //qDebug("Pix size: (%d, %d)", cbPix.width(), cbPix.height()); + QRect cbRect = option.rect; + cbRect.setLeft(cbRect.left()+(cbRect.width()-cbPix.width())); + int diff_height = cbRect.height() - cbPix.height(); + cbRect.setHeight(cbPix.height()); + cbRect.moveBottom(cbRect.bottom()+(diff_height/2.)); + //qDebug("Rect size: (%d, %d)", cbRect.width(), cbRect.height()); + painter->drawPixmap(cbRect, cbPix); + } + + // Restore painter + painter->restore(); +} diff --git a/checklistdelegate.h b/checklistdelegate.h new file mode 100644 index 0000000..22bc5f0 --- /dev/null +++ b/checklistdelegate.h @@ -0,0 +1,31 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#ifndef CHECKLISTDELEGATE_H +#define CHECKLISTDELEGATE_H + +#include + +class CheckListDelegate : public QStyledItemDelegate +{ +public: + CheckListDelegate(); + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + +}; + +#endif // CHECKLISTDELEGATE_H diff --git a/eventlistdelegate.cpp b/eventlistdelegate.cpp new file mode 100644 index 0000000..600d547 --- /dev/null +++ b/eventlistdelegate.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#include +#include +#include "eventlistdelegate.h" +#include "switchingeventlist.h" + +EventListDelegate::EventListDelegate() +{ +} + +void EventListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + if(index.column() == EV_STATUS) { + // Draw checkbox + QIcon::fromTheme("general_tickmark_checked"); + // Is selected + // Draw checkbox + QIcon cbIco; + if(index.data().toBool()) { + cbIco = QIcon::fromTheme("clock_alarm_on"); + } else { + cbIco = QIcon::fromTheme("clock_alarm_off"); + } + QPixmap cbPix = cbIco.pixmap(cbIco.actualSize(option.decorationSize)); + QRect cbRect = option.rect; + cbRect.setWidth(cbPix.width()); + cbRect.setHeight(cbPix.height()); + cbRect.moveCenter(option.rect.center());; + painter->drawPixmap(cbRect, cbPix); + } else { + QStyleOptionViewItem opt = option; + opt.displayAlignment = Qt::AlignCenter; + QStyledItemDelegate::paint(painter, opt, index); + } +} diff --git a/eventlistdelegate.h b/eventlistdelegate.h new file mode 100644 index 0000000..f477490 --- /dev/null +++ b/eventlistdelegate.h @@ -0,0 +1,30 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#ifndef EVENTLISTDELEGATE_H +#define EVENTLISTDELEGATE_H + +#include + +class EventListDelegate : public QStyledItemDelegate +{ +public: + EventListDelegate(); + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; +}; + +#endif // EVENTLISTDELEGATE_H diff --git a/main.cpp b/main.cpp index 796dfd4..431ab19 100644 --- a/main.cpp +++ b/main.cpp @@ -37,7 +37,7 @@ int main(int argc, char *argv[]) QString param = QString::fromLocal8Bit(argv[1]); if(param == "--disable") { std::cout << "Disabling the timed silencer events..." << std::endl; - AlarmdBackend::deleteEvents(); + AlarmdBackend::deleteAllEvents(); return 0; } } diff --git a/mainwindow.cpp b/mainwindow.cpp index e4ed214..89392a3 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -26,102 +26,39 @@ #include #include #include - +#include #include "mainwindow.h" -#include "alarmd_backend.h" -#include "dbus_backend.h" +#include "switchingeventlist.h" +#include "newalarmdlg.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setCentralWidget(new QWidget()); - QHBoxLayout *hori_layout = new QHBoxLayout(centralWidget()); - QVBoxLayout *verticalLayoutL = new QVBoxLayout(); - verticalLayoutL->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); - QLabel *from_lbl = new QLabel(tr("Use the silent profile between")); - from_lbl->setAlignment(Qt::AlignHCenter); - verticalLayoutL->addWidget(from_lbl); - from_button = new QMaemo5ValueButton(); - from_button->setPickSelector(new QMaemo5TimePickSelector()); - verticalLayoutL->addWidget(from_button); - QLabel *to_lbl = new QLabel(tr("and")); - to_lbl->setAlignment(Qt::AlignHCenter); - verticalLayoutL->addWidget(to_lbl); - to_button = new QMaemo5ValueButton(); - to_button->setPickSelector(new QMaemo5TimePickSelector()); - verticalLayoutL->addWidget(to_button); - // Status - verticalLayoutL->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); - cb_enable = new QCheckBox(tr("Activated")); - verticalLayoutL->addWidget(cb_enable); - hori_layout->addLayout(verticalLayoutL); - QVBoxLayout *verticalLayoutR = new QVBoxLayout; - verticalLayoutR->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); - done_btn = new QPushButton(tr("Save")); - done_btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - connect(done_btn, SIGNAL(clicked()), this, SLOT(saveAndClose())); - verticalLayoutR->addWidget(done_btn); - hori_layout->addLayout(verticalLayoutR); - // Load settings - loadSettings(); + QVBoxLayout *vLayout = new QVBoxLayout(centralWidget()); + addEventBtn = new QPushButton(QIcon::fromTheme("general_add"), tr("New profile switching event")); + connect(addEventBtn, SIGNAL(clicked()), this, SLOT(addEvent())); + vLayout->addWidget(addEventBtn); + eventList = new SwitchingEventList; + vLayout->addWidget(eventList); // Auto rotation setAttribute(Qt::WA_Maemo5AutoOrientation, true); } MainWindow::~MainWindow() { - delete from_button; - delete to_button; - delete cb_enable; - delete done_btn; + delete addEventBtn; + delete eventList; } -void MainWindow::saveAndClose() { - // Save the settings and set the events - if(cb_enable->isChecked()) { - setProfileEvents(); - QMaemo5InformationBox::information(this, tr("The daily profile switching is activated"), 0); - } else { - AlarmdBackend::deleteEvents(); - QMaemo5InformationBox::information(this, tr("The daily profile switching is deactivated"), 0); - } - saveSettings(); - // Close the window - close(); +void MainWindow::loadSettings() { + } void MainWindow::saveSettings() { - QSettings settings("TimedSilencer", "TimedSilencer"); - settings.setValue("from_time", static_cast(from_button->pickSelector())->currentTime()); - settings.setValue("to_time", static_cast(to_button->pickSelector())->currentTime()); - settings.setValue("enabled", cb_enable->isChecked()); -} -void MainWindow::loadSettings() { - QSettings settings("TimedSilencer", "TimedSilencer"); - QTime from_time = settings.value("from_time", QTime(22, 0)).toTime(); - static_cast(from_button->pickSelector())->setCurrentTime(from_time); - QTime to_time = settings.value("to_time", QTime(8, 0)).toTime(); - static_cast(to_button->pickSelector())->setCurrentTime(to_time); - cb_enable->setChecked(settings.value("enabled", false).toBool()); } -void MainWindow::setProfileEvents() { - // Set profile events in Alarmd - QTime from_time = static_cast(from_button->pickSelector())->currentTime(); - qDebug("From time: %s", qPrintable(from_time.toString())); - AlarmdBackend::setProfileEvent(SILENT, from_time); - QTime to_time = static_cast(to_button->pickSelector())->currentTime(); - AlarmdBackend::setProfileEvent(GENERAL, to_time); - qDebug("To time: %s", qPrintable(to_time.toString())); - // Update current profile - bool in_silent_mode = false; - QTime ctime = QTime::currentTime(); - if(from_time < to_time) { - in_silent_mode = (ctime > from_time && ctime < to_time); - } else { - // to_time is the next day - in_silent_mode = (ctime > from_time || (ctime < from_time && ctime < to_time)); - } - if(in_silent_mode) - DBusBackend::setProfile(SILENT); - /*else - DBusBackend::setProfile(GENERAL);*/ +void MainWindow::addEvent() { + NewAlarmDlg dlg(this); + connect(&dlg, SIGNAL(newEvent(QVariant)), eventList, SLOT(addNewEvent(QVariant))); + dlg.exec(); } + diff --git a/mainwindow.h b/mainwindow.h index 1242af8..8d66bc3 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -20,10 +20,8 @@ #include -struct QMaemo5ValueButton; -struct QAction; -struct QCheckBox; struct QPushButton; +struct SwitchingEventList; class MainWindow : public QMainWindow { Q_OBJECT @@ -33,16 +31,13 @@ public: ~MainWindow(); protected slots: - void saveSettings(); void loadSettings(); - void setProfileEvents(); - void saveAndClose(); + void saveSettings(); + void addEvent(); private: - QMaemo5ValueButton *from_button, *to_button; - QAction *active_action; - QCheckBox *cb_enable; - QPushButton *done_btn; + QPushButton *addEventBtn; + SwitchingEventList *eventList; }; #endif // MAINWINDOW_H diff --git a/newalarmdlg.cpp b/newalarmdlg.cpp new file mode 100644 index 0000000..8f7f21a --- /dev/null +++ b/newalarmdlg.cpp @@ -0,0 +1,185 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "newalarmdlg.h" +#include "alarmd_backend.h" +#include "qmaemo5weekdayspickselector.h" +#include "profileevent.h" + +NewAlarmDlg::NewAlarmDlg(QWidget *parent, QByteArray edited_id) : + QDialog(parent) +{ + if(!edited_id.isNull()) { + pe = ProfileEvent::findByID(edited_id); + } else { + pe = 0; + } + if(pe) { + setWindowTitle(tr("Edit profile switching event")); + } else { + setWindowTitle(tr("New profile switching event")); + } + QHBoxLayout *hori_layout = new QHBoxLayout(this); + QVBoxLayout *verticalLayoutL = new QVBoxLayout(); + verticalLayoutL->addWidget(new QLabel(tr("Use the silent profile"))); + from_button = new QMaemo5ValueButton(tr("From")); + QMaemo5TimePickSelector *from_selector = new QMaemo5TimePickSelector(); + if(pe) { + from_selector->setCurrentTime(pe->from_time); + } else { + from_selector->setCurrentTime(QTime(22, 30)); + } + from_button->setPickSelector(from_selector); + from_button->setValueLayout(QMaemo5ValueButton::ValueBesideText); + verticalLayoutL->addWidget(from_button); + to_button = new QMaemo5ValueButton(tr("To")); + QMaemo5TimePickSelector *to_selector = new QMaemo5TimePickSelector(); + if(pe) { + to_selector->setCurrentTime(pe->to_time); + } else { + to_selector->setCurrentTime(QTime(8, 0)); + } + to_button->setPickSelector(to_selector); + to_button->setValueLayout(QMaemo5ValueButton::ValueBesideText); + verticalLayoutL->addWidget(to_button); + // Status + verticalLayoutL->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); + repeat_button = new QMaemo5ValueButton(tr("Repeat")); + repeat_button->setValueLayout(QMaemo5ValueButton::ValueBesideText); + QMaemo5WeekDaysPickSelector *weekDaysSelector = new QMaemo5WeekDaysPickSelector; + if(pe) { + weekDaysSelector->updateSelection(pe->days); + } + repeat_button->setPickSelector(weekDaysSelector); + verticalLayoutL->addWidget(repeat_button); + if(pe) { + cb_enable = new QCheckBox(tr("Activated")); + cb_enable->setChecked(pe->activated); + verticalLayoutL->addWidget(cb_enable); + } else { + cb_enable = 0; + } + hori_layout->addLayout(verticalLayoutL); + QVBoxLayout *verticalLayoutR = new QVBoxLayout; + verticalLayoutR->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); + button_box = new QDialogButtonBox(Qt::Vertical); + // Delete button + if(pe) { + delete_btn = new QPushButton(tr("Delete")); + connect(delete_btn, SIGNAL(clicked()), this, SLOT(deleteAndClose())); + button_box->addButton(delete_btn, QDialogButtonBox::ActionRole); + } else { + delete_btn = 0; + } + // Save button + done_btn = new QPushButton(tr("Save")); + connect(done_btn, SIGNAL(clicked()), this, SLOT(saveAndClose())); + button_box->addButton(done_btn, QDialogButtonBox::ActionRole); + verticalLayoutR->addWidget(button_box); + hori_layout->addLayout(verticalLayoutR); +} + +NewAlarmDlg::~NewAlarmDlg() { + if(pe) delete pe; + delete button_box; +} + +void NewAlarmDlg::saveAndClose() { + // Save QSettings + ProfileEvent *new_pe = saveEvent(); + if(new_pe) { + // Update Alarmd events + if(pe && pe->activated) { + // Delete old alarmd events + AlarmdBackend::deleteEvents(pe); + } + if(new_pe->activated) { + // Add new alarmd events + AlarmdBackend::setProfileEvents(new_pe); + } + delete new_pe; + } + // Close the window + close(); +} + +void NewAlarmDlg::deleteAndClose() { + Q_ASSERT(pe); + // Remove Alarmd events + AlarmdBackend::deleteEvents(pe); + // Update QSettings + QSettings settings("TimedSilencer", "TimedSilencer"); + QHash events = settings.value("events").toHash(); + Q_ASSERT(events.contains(pe->getID())); + events.remove(pe->getID()); + settings.setValue("events", events); + // Notify MainWindow + emit deletedEvent(pe->getID()); + close(); +} + +ProfileEvent* NewAlarmDlg::saveEvent() { + QSettings settings("TimedSilencer", "TimedSilencer"); + ProfileEvent *new_pe = new ProfileEvent; + new_pe->from_time = static_cast(from_button->pickSelector())->currentTime(); + new_pe->to_time = static_cast(to_button->pickSelector())->currentTime(); + new_pe->days = static_cast(repeat_button->pickSelector())->selectedDays(); + if(cb_enable) + new_pe->activated = cb_enable->isChecked(); + QHash events = settings.value("events").toHash(); + if(pe && new_pe->getID() != pe->getID()) { + events.remove(pe->getID()); + } + // Save + qDebug("Saving event..."); + QVariant var_pe = new_pe->save(); + if(pe) { + if(pe->getID() == new_pe->getID()) { + qDebug("ID did not change"); + if(pe->activated != new_pe->activated) { + // Only the activated status may change without altering the ID + emit editedEvent(new_pe->getID(), new_pe->activated); + } + } else { + qDebug("ID changed"); + emit deletedEvent(pe->getID()); + emit newEvent(var_pe); + } + } else { + qDebug("New event"); + if(events.contains(new_pe->getID())) { + QMaemo5InformationBox::information(parentWidget(), tr("This profile switching event already exists")); + return 0; + } else { + emit newEvent(var_pe); + } + } + events.insert(new_pe->getID(), var_pe); + settings.setValue("events", events); + return new_pe; +} diff --git a/newalarmdlg.h b/newalarmdlg.h new file mode 100644 index 0000000..17a5e0c --- /dev/null +++ b/newalarmdlg.h @@ -0,0 +1,57 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#ifndef NEWALARMDLG_H +#define NEWALARMDLG_H + +#include +#include + +struct QMaemo5ValueButton; +struct QAction; +struct QCheckBox; +struct QPushButton; +struct ProfileEvent; +struct QDialogButtonBox; + +class NewAlarmDlg : public QDialog +{ + Q_OBJECT +public: + explicit NewAlarmDlg(QWidget *parent = 0, QByteArray edited_id = QByteArray()); + ~NewAlarmDlg(); + +signals: + void newEvent(QVariant event); + void editedEvent(QByteArray id, bool new_status); + void deletedEvent(QByteArray id); + +public slots: + ProfileEvent* saveEvent(); + void saveAndClose(); + void deleteAndClose(); + +private: + QMaemo5ValueButton *from_button, *to_button, *repeat_button; + QCheckBox *cb_enable; + QPushButton *delete_btn; + QPushButton *done_btn; + QDialogButtonBox *button_box; + ProfileEvent *pe; +}; + +#endif // NEWALARMDLG_H diff --git a/profileevent.h b/profileevent.h new file mode 100644 index 0000000..643dbfb --- /dev/null +++ b/profileevent.h @@ -0,0 +1,161 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#ifndef PROFILEEVENT_H +#define PROFILEEVENT_H + +#include +#include +#include +#include +#include +#include + +enum WeekDay {NEVER, MON, TUE, WED, THU, FRI, SAT, SUN, EVERY_DAY}; + +class ProfileEvent : public QObject { + Q_OBJECT +private: + QByteArray id; + +public: + QTime from_time; + QTime to_time; + bool activated; + QList days; + QList alarmd_cookies; + + ProfileEvent() { + // Activate as a default + activated = true; + } + + QByteArray getID() { + if(id.isEmpty()) { + QCryptographicHash hasher(QCryptographicHash::Md5); + hasher.addData(from_time.toString().toLocal8Bit()); + hasher.addData(to_time.toString().toLocal8Bit()); + foreach(int i, days) hasher.addData(QByteArray::number(i)); + id = hasher.result(); + } + qDebug("getID(): %s", id.constData()); + return id; + } + + QVariant save() const { + QHash m; + m["from_time"] = from_time; + m["to_time"] = to_time; + m["activated"] = activated; + QVariantList var_days; + foreach(const int& day, days) var_days << day; + m["days"] = var_days; + QVariantList var_cookies; + foreach(const long& c, alarmd_cookies) var_cookies << (qlonglong)c; + m["alarmd_cookies"] = var_cookies; + return m; + } + + bool affectsCurrentTime() { + if(!activated) return false; + Q_ASSERT(!days.empty()); + if(days.empty()) days << NEVER; + if(days.first() != EVERY_DAY && days.first() != NEVER) { + // Check if the current week day is affected by this event + if(!days.contains(QDate::currentDate().dayOfWeek())) return false; + } + // Ok, it is the right day, are we in the interval? + bool in_silent_mode = false; + QTime ctime = QTime::currentTime(); + if(from_time < to_time) { + in_silent_mode = (ctime > from_time && ctime < to_time); + } else { + // to_time is the next day + in_silent_mode = (ctime > from_time || (ctime < from_time && ctime < to_time)); + } + return in_silent_mode; + } + + static ProfileEvent* load(QVariant v) { + QHash m = v.toHash(); + ProfileEvent *pe = new ProfileEvent(); + pe->from_time = m.value("from_time").toTime(); + pe->to_time = m.value("to_time").toTime(); + pe->activated = m.value("activated").toBool(); + QVariantList var_days = m.value("days").toList(); + foreach(const QVariant& var_day, var_days) pe->days << var_day.toInt(); + QVariantList var_cookies = m.value("alarmd_cookies").toList(); + foreach(const QVariant& var_c, var_cookies) pe->alarmd_cookies << var_c.toLongLong(); + return pe; + } + + static QString formatDays(QList selection) { + qDebug("CurrentValueText() called"); + if(selection.isEmpty() || selection.contains(NEVER)) { + return tr("Never"); + } + if(selection.contains(EVERY_DAY)) { + return tr("Every day"); + } + QStringList selectedDays; + foreach(const int &i, selection) { + selectedDays << QDate::shortDayName(i); + } + return selectedDays.join(", "); + } + + static ProfileEvent* findByID(QByteArray myid) { + QSettings settings("TimedSilencer", "TimedSilencer"); + QHash events = settings.value("events").toHash(); + if(events.contains(myid)) { + return load(events.value(myid)); + } + return 0; + } + + static void clearCookies(QByteArray myid) { + QSettings settings("TimedSilencer", "TimedSilencer"); + QHash events = settings.value("events").toHash(); + Q_ASSERT(events.contains(myid)); + if(events.contains(myid)) { + qDebug("Clearing event cookies in QSettings"); + ProfileEvent *pe = load(events.value(myid)); + pe->alarmd_cookies.clear(); + events[myid] = pe->save(); + settings.setValue("events", events); + delete pe; + } + } + + static void setCookies(QByteArray myid, QList cookies) { + QSettings settings("TimedSilencer", "TimedSilencer"); + QHash events = settings.value("events").toHash(); + Q_ASSERT(events.contains(myid)); + if(events.contains(myid)) { + qDebug("Setting event cookies in QSettings"); + ProfileEvent *pe = load(events.value(myid)); + Q_ASSERT(pe->alarmd_cookies.empty()); + pe->alarmd_cookies = cookies; + events[myid] = pe->save(); + settings.setValue("events", events); + delete pe; + } + } + +}; + +#endif // PROFILEEVENT_H diff --git a/qmaemo5weekdayspickselector.cpp b/qmaemo5weekdayspickselector.cpp new file mode 100644 index 0000000..2c87548 --- /dev/null +++ b/qmaemo5weekdayspickselector.cpp @@ -0,0 +1,50 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#include + +#include "qmaemo5weekdayspickselector.h" +#include "qmaemo5weekdayspickwidget.h" +#include "profileevent.h" + +QMaemo5WeekDaysPickSelector::QMaemo5WeekDaysPickSelector(QObject *parent): QMaemo5AbstractPickSelector(parent) +{ + pick_widget = new QMaemo5WeekDaysPickWidget; + connect(pick_widget, SIGNAL(selectedDays(QList)), this, SLOT(updateSelection(QList))); +} + +QWidget* QMaemo5WeekDaysPickSelector::widget(QWidget* parent) { + Q_UNUSED(parent); + return pick_widget; +} + +QString QMaemo5WeekDaysPickSelector::currentValueText() const { + qDebug("CurrentValueText() called"); + return ProfileEvent::formatDays(selection); +} + +void QMaemo5WeekDaysPickSelector::updateSelection(QList new_sel) { + qDebug("New selection size: %d", new_sel.size()); + selection = new_sel; + pick_widget->setSelected(selection); + emit selected(currentValueText()); +} + +QList QMaemo5WeekDaysPickSelector::selectedDays() { + if(selection.empty()) selection << NEVER; + return selection; +} diff --git a/qmaemo5weekdayspickselector.h b/qmaemo5weekdayspickselector.h new file mode 100644 index 0000000..2962c21 --- /dev/null +++ b/qmaemo5weekdayspickselector.h @@ -0,0 +1,44 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#ifndef QMAEMO5WEEKDAYSPICKSELECTOR_H +#define QMAEMO5WEEKDAYSPICKSELECTOR_H + +#include +#include + +struct QMaemo5WeekDaysPickWidget; + +class QMaemo5WeekDaysPickSelector : public QMaemo5AbstractPickSelector +{ + Q_OBJECT + +public: + QMaemo5WeekDaysPickSelector(QObject *parent=0); + QWidget* widget(QWidget* parent); + QString currentValueText() const; + QList selectedDays(); + +public slots: + void updateSelection(QList new_sel); + +private: + QMaemo5WeekDaysPickWidget *pick_widget; + QList selection; +}; + +#endif // QMAEMO5WEEKDAYSPICKSELECTOR_H diff --git a/qmaemo5weekdayspickwidget.cpp b/qmaemo5weekdayspickwidget.cpp new file mode 100644 index 0000000..2a40e52 --- /dev/null +++ b/qmaemo5weekdayspickwidget.cpp @@ -0,0 +1,139 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qmaemo5weekdayspickwidget.h" +#include "checklistdelegate.h" + +QMaemo5WeekDaysPickWidget::QMaemo5WeekDaysPickWidget(QWidget *parent) : + QDialog(parent) +{ + setAttribute(Qt::WA_DeleteOnClose); + setWindowTitle(tr("Repeat")); + QHBoxLayout *hLayout = new QHBoxLayout(this); + QVBoxLayout *vLayoutL = new QVBoxLayout; + QStandardItemModel *model = new QStandardItemModel(9, 1); + model->setItem(NEVER, 0, new QStandardItem(tr("Never"))); + model->setItem(MON, 0, new QStandardItem(tr("Monday"))); + model->setItem(TUE, 0, new QStandardItem(tr("Tuesday"))); + model->setItem(WED, 0, new QStandardItem(tr("Wednesday"))); + model->setItem(THU, 0, new QStandardItem(tr("Thursday"))); + model->setItem(FRI, 0, new QStandardItem(tr("Friday"))); + model->setItem(SAT, 0, new QStandardItem(tr("Saturday"))); + model->setItem(SUN, 0, new QStandardItem(tr("Sunday"))); + model->setItem(EVERY_DAY, 0, new QStandardItem(tr("Every day"))); + daysList = new QListView; + daysList->setModel(model); + daysList->setItemDelegate(new CheckListDelegate); + connect(daysList, SIGNAL(activated(QModelIndex)), this, SLOT(ensureConsistentSelection(QModelIndex))); + // Select NEVER item + daysList->selectionModel()->select(daysList->model()->index(NEVER, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows); + // Height hint + if (daysList->sizeHintForRow(0)>0) + daysList->setMinimumHeight(daysList->sizeHintForRow(0) * 5); + daysList->setSelectionMode(QAbstractItemView::MultiSelection); + daysList->setSelectionBehavior(QAbstractItemView::SelectRows); + vLayoutL->addWidget(daysList); + hLayout->addLayout(vLayoutL); + QVBoxLayout *vLayoutR = new QVBoxLayout; + vLayoutR->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); + button_box = new QDialogButtonBox(Qt::Vertical); + QPushButton *done_btn = new QPushButton(tr("Done")); + connect(done_btn, SIGNAL(clicked()), this, SLOT(emitSelectionAndClose())); + done_btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + button_box->addButton(done_btn, QDialogButtonBox::ActionRole); + vLayoutR->addWidget(button_box); + hLayout->addLayout(vLayoutR); +} + +void QMaemo5WeekDaysPickWidget::setSelected(QList days) { + if(days.empty()) { + daysList->selectionModel()->select(daysList->model()->index(NEVER, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows); + return; + } + daysList->selectionModel()->clearSelection(); + qDebug("setSelected, %d items", days.size()); + foreach(const int &d, days) { + daysList->selectionModel()->select(daysList->model()->index(d, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows); + if(d == EVERY_DAY) + ensureConsistentSelection(daysList->model()->index(d, 0)); + } +} + +void QMaemo5WeekDaysPickWidget::emitSelectionAndClose() { + qDebug("in emitSelectionAndClose()"); + QList selected_rows; + QModelIndexList selected_indexes = daysList->selectionModel()->selectedRows(); + foreach(QModelIndex index, selected_indexes) { + selected_rows << index.row(); + } + emit selectedDays(selected_rows); + close(); +} + +void QMaemo5WeekDaysPickWidget::ensureConsistentSelection(QModelIndex index) { + qDebug("Received a click"); + switch(index.row()) { + case NEVER: + if(!daysList->selectionModel()->isSelected(index)) { + // Prevent unselect + daysList->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows); + return; + } + daysList->selectionModel()->clearSelection(); + daysList->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows); + break; + case EVERY_DAY: + if(!daysList->selectionModel()->isSelected(index)) { + // Prevent unselect + daysList->selectionModel()->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows); + return; + } + if(daysList->selectionModel()->isRowSelected(NEVER, daysList->rootIndex())) { + // Unselect NEVER item + daysList->selectionModel()->select(daysList->model()->index(NEVER, 0), QItemSelectionModel::Deselect | QItemSelectionModel::Rows); + } + // Select all days + for(int i=MON; iselectionModel()->select(daysList->model()->index(i, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows); + } + break; + default: + if(daysList->selectionModel()->isRowSelected(NEVER, daysList->rootIndex())) { + // Unselect NEVER item + daysList->selectionModel()->select(daysList->model()->index(NEVER, 0), QItemSelectionModel::Deselect | QItemSelectionModel::Rows); + } + if(!daysList->selectionModel()->isSelected(index)) { + if(daysList->selectionModel()->isRowSelected(EVERY_DAY, daysList->rootIndex())) { + // A Work day was unselected, unselect EVERY_DAY item + daysList->selectionModel()->select(daysList->model()->index(EVERY_DAY, 0), QItemSelectionModel::Deselect | QItemSelectionModel::Rows); + } + if(!daysList->selectionModel()->hasSelection()) { + // Select NEVER item + daysList->selectionModel()->select(daysList->model()->index(NEVER, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows); + } + } + } +} diff --git a/qmaemo5weekdayspickwidget.h b/qmaemo5weekdayspickwidget.h new file mode 100644 index 0000000..03498e4 --- /dev/null +++ b/qmaemo5weekdayspickwidget.h @@ -0,0 +1,48 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#ifndef QMAEMO5WEEKDAYSPICKWIDGET_H +#define QMAEMO5WEEKDAYSPICKWIDGET_H + +#include +#include + +#include "profileevent.h" + +struct QListView; +struct QDialogButtonBox; + +class QMaemo5WeekDaysPickWidget : public QDialog +{ + Q_OBJECT +public: + explicit QMaemo5WeekDaysPickWidget(QWidget *parent = 0); + +signals: + void selectedDays(QList days); + +public slots: + void ensureConsistentSelection(QModelIndex index); + void emitSelectionAndClose(); + void setSelected(QList days); + +private: + QListView *daysList; + QDialogButtonBox *button_box; +}; + +#endif // QMAEMO5WEEKDAYSPICKWIDGET_H diff --git a/switchingeventlist.cpp b/switchingeventlist.cpp new file mode 100644 index 0000000..abcc147 --- /dev/null +++ b/switchingeventlist.cpp @@ -0,0 +1,164 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#include +#include +#include +#include +#include "profileevent.h" +#include "switchingeventlist.h" +#include "newalarmdlg.h" +#include "eventlistdelegate.h" +#include "alarmd_backend.h" + +SwitchingEventList::SwitchingEventList(QWidget *parent) : + QTableView(parent) +{ + setSelectionBehavior(QAbstractItemView::SelectRows); + model = new QStandardItemModel(0, 5); + // Set Header + model->setHeaderData(EV_STATUS, Qt::Horizontal, tr("Status")); + model->setHeaderData(EV_FROM, Qt::Horizontal, tr("From")); + model->setHeaderData(EV_TO, Qt::Horizontal, tr("To")); + model->setHeaderData(EV_REPEAT, Qt::Horizontal, tr("Repeat")); + setModel(model); + setItemDelegate(new EventListDelegate); + connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(editEvent(QModelIndex))); + // Hide vertical header + verticalHeader()->setVisible(false); + horizontalHeader()->setStretchLastSection(true); + hideColumn(EV_ID); + // Load saved events + loadSavedEvents(); +} + +SwitchingEventList::~SwitchingEventList() { + delete model; +} + +void SwitchingEventList::updateRow(int row, ProfileEvent *pe) { + model->setData(model->index(row, EV_STATUS), pe->activated); + model->setData(model->index(row, EV_FROM), pe->from_time.toString()); + model->setData(model->index(row, EV_TO), pe->to_time.toString()); + model->setData(model->index(row, EV_REPEAT), ProfileEvent::formatDays(pe->days)); + model->setData(model->index(row, EV_ID), pe->getID()); +} + +void SwitchingEventList::editEvent(QModelIndex index) { + if(!index.isValid()) return; + QByteArray edited_id = model->data(model->index(index.row(), EV_ID)).toByteArray(); + if(index.column() == EV_STATUS) { + // Toggle activated state + const bool new_status = !index.data().toBool(); + model->setData(index, new_status); + // Alter Alarmd events + if(new_status) { + // Was activated + AlarmdBackend::setProfileEvents(edited_id); + } else { + // Was deactivated + AlarmdBackend::deleteEvents(edited_id); + } + } else { + NewAlarmDlg dlg(this, edited_id); + connect(&dlg, SIGNAL(editedEvent(QByteArray,bool)), this, SLOT(editEvent(QByteArray,bool))); + connect(&dlg, SIGNAL(deletedEvent(QByteArray)), this, SLOT(deleteEvent(QByteArray))); + connect(&dlg, SIGNAL(newEvent(QVariant)), this, SLOT(addNewEvent(QVariant))); + dlg.exec(); + } +} + +void SwitchingEventList::loadSavedEvents() { + qDebug("Loading saved events"); + QSettings settings("TimedSilencer", "TimedSilencer"); + QHash events = settings.value("events").toHash(); + // Check for < v0.6 settings + if(!settings.value("from_time", QTime()).toTime().isNull()) { + qDebug("Old settings from < v0.6 were detected, importing..."); + ProfileEvent pe; + pe.activated = settings.value("enabled", false).toBool(); + pe.from_time = settings.value("from_time").toTime(); + pe.to_time = settings.value("to_time").toTime(); + pe.days << EVERY_DAY; + // Cookies + long from_cookie = settings.value("silencing_cookie", 0).toLongLong(); + if(from_cookie > 0) + pe.alarmd_cookies << from_cookie; + long to_cookie = settings.value("unsilencing_cookie", 0).toLongLong(); + if(to_cookie > 0) + pe.alarmd_cookies << to_cookie; + if(to_cookie == 0 || from_cookie == 0) + pe.activated = 0; + events.insert(pe.getID(), pe.save()); + // Remove old format values + settings.clear(); + // Save in new format + settings.setValue("events", events); + } + // Load >= v0.6 settings + bool settings_change = false; + foreach(QVariant e, events.values()) { + ProfileEvent *pe = ProfileEvent::load(e); + // Check if still active + if(pe->activated && !AlarmdBackend::checkIfStillActive(pe)) { + qDebug("An existing profile switching event is no longer active, updating its status"); + pe->activated = false; + events[pe->getID()] = pe->save(); + settings_change = true; + } + // Add new model row + const int nb_rows = model->rowCount(); + model->setRowCount(nb_rows+1); + updateRow(nb_rows, pe); + // Clean up + delete pe; + } + if(settings_change) + settings.setValue("events", events); +} + +void SwitchingEventList::addNewEvent(QVariant var_event) { + qDebug("Adding a new event to the list"); + ProfileEvent *pe = ProfileEvent::load(var_event); + // Add new model row + const int nb_rows = model->rowCount(); + model->setRowCount(nb_rows+1); + updateRow(nb_rows, pe); + delete pe; +} + +void SwitchingEventList::editEvent(QByteArray id, bool new_status) { + const int row = getRowFromID(id); + qDebug("Editing event at row %d", row); + Q_ASSERT(row >= 0); + model->setData(model->index(row, EV_STATUS), new_status); +} + +void SwitchingEventList::deleteEvent(QByteArray id) { + const int row = getRowFromID(id); + qDebug("Deleting an event (row: %d)", row); + Q_ASSERT(row >= 0); + model->removeRow(row); +} + +int SwitchingEventList::getRowFromID(QByteArray id) { + for(int i=0; irowCount(); ++i) { + if(model->data(model->index(i, EV_ID)).toByteArray() == id) + return i; + } + return -1; +} diff --git a/switchingeventlist.h b/switchingeventlist.h new file mode 100644 index 0000000..64cbe21 --- /dev/null +++ b/switchingeventlist.h @@ -0,0 +1,51 @@ +/* + * This file is part of TimedSilencer. + * + * TimedSilencer is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TimedSilencer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimedSilencer. If not, see . + */ + +#ifndef SWITCHINGEVENTLIST_H +#define SWITCHINGEVENTLIST_H + +#include +struct QStandardItemModel; +struct ProfileEvent; + +enum EventCols {EV_STATUS, EV_FROM, EV_TO, EV_REPEAT, EV_ID}; + +class SwitchingEventList : public QTableView +{ + Q_OBJECT +public: + explicit SwitchingEventList(QWidget *parent = 0); + ~SwitchingEventList(); + int getRowFromID(QByteArray id); + +signals: + +public slots: + void addNewEvent(QVariant event); + void editEvent(QByteArray id, bool new_status); + void deleteEvent(QByteArray id); + +protected slots: + void loadSavedEvents(); + void updateRow(int row, ProfileEvent *pe); + void editEvent(QModelIndex index); + +private: + QStandardItemModel *model; +}; + +#endif // SWITCHINGEVENTLIST_H -- 1.7.9.5