diff --git a/src/akonadi/akonadiserializer.cpp b/src/akonadi/akonadiserializer.cpp --- a/src/akonadi/akonadiserializer.cpp +++ b/src/akonadi/akonadiserializer.cpp @@ -419,6 +419,57 @@ return Domain::Recurrence::Ptr(new Domain::Recurrence(recurrence)); } +KCalCore::Alarm::Type toKCalAlarmType(Domain::Alarm::Type type) +{ + switch(type) { + case Domain::Alarm::Audio: + return KCalCore::Alarm::Audio; + case Domain::Alarm::Display: + return KCalCore::Alarm::Display; + default: + qFatal("unhandled Alarm tpye"); + } + return KCalCore::Alarm::Invalid; +} + +Domain::Alarm::Type fromKCalAlarmType(KCalCore::Alarm::Type type) +{ + switch(type) { + case KCalCore::Alarm::Audio: + return Domain::Alarm::Audio; + case KCalCore::Alarm::Display: + return Domain::Alarm::Display; + default: + qFatal("unhandled Alarm tpye"); + } + return Domain::Alarm::Display; +} + +Domain::Alarm::List fromKCalAlarm(KCalCore::Alarm::List alist) +{ + Domain::Alarm::List alarms; + + foreach(auto a, alist) { + Domain::Alarm::Ptr alarm(new Domain::Alarm()); + alarm->setType(fromKCalAlarmType(a->type())); + if (a->hasTime()) { + alarm->setPosition(Domain::Alarm::Exact); + alarm->setDateTime(a->time().dateTime()); + } else { + if (a->hasStartOffset()) { + alarm->setPosition(Domain::Alarm::Start); + alarm->setOffset(a->startOffset().asSeconds()); + } else { + alarm->setPosition(Domain::Alarm::End); + alarm->setOffset(a->endOffset().asSeconds()); + } + } + alarms.append(alarm); + } + + return alarms; +} + void Serializer::updateTaskFromItem(Domain::Task::Ptr task, Item item) { if (!isTaskItem(item)) @@ -461,6 +512,11 @@ task->setDelegate(Domain::Task::Delegate((*delegate)->name(), (*delegate)->email())); } } + if (!todo->alarms().isEmpty()) { + task->setAlarms(fromKCalAlarm(todo->alarms())); + } else { + task->setAlarms(Domain::Alarm::List()); + } if (todo->recurs()) { Domain::Recurrence::Ptr recurrence(fromKCalRecurrence(todo->recurrence())); task->setRecurrence(recurrence); @@ -558,6 +614,7 @@ todo->setDtDue(KDateTime(task->dueDate())); todo->setPercentComplete(task->progress()); todo->setStatus(toKCalStatus(task->status())); + if (task->status() != Domain::Task::Complete || task->status() != Domain::Task::FullComplete) { //Because the serializer doesn't serialize the status as it should but instead serializes the isComplete status todo->setCompleted(false); @@ -567,6 +624,27 @@ updateKCalRecurrence(task->recurrence(), todo->recurrence()); } + if(!task->alarms().isEmpty()) { + foreach(auto a, task->alarms()) { + KCalCore::Alarm::Ptr alarm(new KCalCore::Alarm(todo.data())); + KCalCore::Duration duration(a->offset(), KCalCore::Duration::Seconds); + alarm->setEnabled(true); + alarm->setType(toKCalAlarmType(a->type())); + switch (a->position()) { + case Domain::Alarm::Exact: + alarm->setTime(KDateTime(a->datetime())); + break; + case Domain::Alarm::Start: + alarm->setStartOffset(duration); + break; + case Domain::Alarm::End: + alarm->setEndOffset(duration); + break; + } + todo->addAlarm(alarm); + } + } + if (task->property("todoUid").isValid()) { todo->setUid(task->property("todoUid").toString()); } diff --git a/src/domain/task.h b/src/domain/task.h --- a/src/domain/task.h +++ b/src/domain/task.h @@ -30,6 +30,51 @@ namespace Domain { +class Alarm : public QObject +{ + Q_OBJECT +public: + typedef QSharedPointer Ptr; + typedef QList List; + + enum Type { + None, /**< no alarm set */ + Display, /**< Display a dialog box */ + Audio /**< Play an audio file */ + }; + + enum Position { + Exact, /**< exact datetime */ + Start, /**< relative to start date */ + End /**< relative to end date */ + }; + + explicit Alarm(QObject *parent = 0); + explicit Alarm(const Domain::Alarm &other); + virtual ~Alarm(); + + Alarm &operator=(const Alarm &other); + bool operator==(const Alarm &other) const; + + void setPosition(Position postition); + Position position() const; + + void setType(Type type); + Type type() const; + + void setDateTime(const QDateTime &datetime); + QDateTime datetime() const; + + void setOffset(int offset); + int offset() const; + +private: + Position m_position; + Type m_type; + QDateTime m_datetime; /**< exacpt datetime to start alarm */ + int m_offset; /**< offset in seconds */ +}; + class Recurrence : public QObject { Q_OBJECT @@ -126,6 +171,7 @@ void setExceptionDates(const QList &exceptions); QList exceptionDates() const; + private: Frequency m_frequency; Weekday m_weekStart; @@ -153,6 +199,7 @@ Q_PROPERTY(QDateTime dueDate READ dueDate WRITE setDueDate NOTIFY dueDateChanged) Q_PROPERTY(Domain::Task::Delegate delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_PROPERTY(Domain::Recurrence::Ptr recurrence READ recurrence WRITE setRecurrence NOTIFY recurrenceChanged) + Q_PROPERTY(Domain::Alarm::List alarms READ alarms WRITE setAlarms NOTIFY alarmsChanged) public: typedef QSharedPointer Ptr; typedef QList List; @@ -203,6 +250,7 @@ int progress() const; Status status() const; Recurrence::Ptr recurrence() const; + Alarm::List alarms() const; public slots: void setDone(bool done); @@ -212,7 +260,7 @@ void setProgress(int progress); void setStatus(int status); void setRecurrence(const Domain::Recurrence::Ptr &recurrence); - + void setAlarms(const Alarm::List &alarms); signals: void startDateChanged(const QDateTime &startDate); void dueDateChanged(const QDateTime &dueDate); @@ -220,6 +268,7 @@ void progressChanged(int progress); void statusChanged(int status); void recurrenceChanged(const Domain::Recurrence::Ptr &recurrence); + void alarmsChanged(const Alarm::List &alarms); private: QDateTime m_startDate; @@ -228,6 +277,7 @@ Recurrence::Ptr m_recurrence; int m_progress; Status m_status; + Alarm::List m_alarms; }; } @@ -238,4 +288,7 @@ Q_DECLARE_METATYPE(Domain::Recurrence::Ptr) Q_DECLARE_METATYPE(Domain::Recurrence::List) + +Q_DECLARE_METATYPE(Domain::Alarm::Ptr) +Q_DECLARE_METATYPE(Domain::Alarm::List) #endif // DOMAIN_TASK_H diff --git a/src/domain/task.cpp b/src/domain/task.cpp --- a/src/domain/task.cpp +++ b/src/domain/task.cpp @@ -43,6 +43,7 @@ , m_recurrence(other.m_recurrence) , m_progress(other.m_progress) , m_status(other.m_status) + , m_alarms(other.m_alarms) { } @@ -60,6 +61,7 @@ std::swap(m_recurrence, copy.m_recurrence); std::swap(m_progress, copy.m_progress); std::swap(m_status, copy.m_status); + std::swap(m_alarms, copy.m_alarms); setText(other.text()); setTitle(other.title()); return *this; @@ -169,6 +171,20 @@ emit recurrenceChanged(recurrence); } +Alarm::List Task::alarms() const +{ + return m_alarms; +} + +void Task::setAlarms(const Alarm::List &alarms) +{ + if (m_alarms == alarms) { + return; + } + + m_alarms = alarms; + emit alarmsChanged(alarms); +} Task::Delegate::Delegate() { @@ -483,3 +499,100 @@ { return m_exceptionDates; } + + +Alarm::Alarm(QObject *parent) + : QObject(parent) + , m_position(End) + , m_type(Display) +{ + +} + + +Alarm::Alarm(const Alarm &other) + : QObject(other.parent()) + , m_position(other.m_position) + , m_type(other.m_type) + , m_datetime(other.m_datetime) + , m_offset(other.m_offset) +{ + +} + +Alarm::~Alarm() +{ + +} + +Alarm &Alarm::operator=(const Alarm &other) +{ + Alarm copy(other); + std::swap(m_position, copy.m_position); + std::swap(m_type, copy.m_type); + std::swap(m_datetime, copy.m_datetime); + std::swap(m_offset, copy.m_offset); + return *this; +} + + +bool Alarm::operator==(const Alarm &other) const +{ + bool ret = m_type == other.m_type && + m_position == other.m_position; + if (!ret) { + return false; + } + + switch(m_position) { + case Exact: + return m_datetime == other.m_datetime; + break; + case Start: + case End: + return m_offset == other.m_offset; + break; + default: + return false; + } +} + +QDateTime Alarm::datetime() const +{ + return m_datetime; +} + +void Alarm::setDateTime(const QDateTime &datetime) +{ + m_datetime = datetime; +} + +int Alarm::offset() const +{ + return m_offset; +} + +void Alarm::setOffset(int offset) +{ + m_offset = offset; +} + +Alarm::Position Alarm::position() const +{ + return m_position; +} + +void Alarm::setPosition(Alarm::Position postition) +{ + m_position = postition; +} + +Alarm::Type Alarm::type() const +{ + return m_type; +} + +void Alarm::setType(Alarm::Type type) +{ + m_type = type; +} diff --git a/src/presentation/artifacteditormodel.h b/src/presentation/artifacteditormodel.h --- a/src/presentation/artifacteditormodel.h +++ b/src/presentation/artifacteditormodel.h @@ -57,6 +57,7 @@ Q_PROPERTY(QList relations READ relations NOTIFY relationsChanged) Q_PROPERTY(Domain::Artifact::Attachment::List attachments READ attachments NOTIFY attachmentsChanged) Q_PROPERTY(Domain::Recurrence::Ptr recurrence READ recurrence WRITE setRecurrence NOTIFY recurrenceChanged) + Q_PROPERTY(Domain::Alarm::Ptr alarm READ alarm READ alarm WRITE setAlarm NOTIFY alarmChanged) public: explicit ArtifactEditorModel(Domain::TaskRepository *taskRepository, Domain::NoteRepository *noteRepository, @@ -80,6 +81,7 @@ QList relations() const; Domain::Artifact::Attachment::List attachments() const; Domain::Recurrence::Ptr recurrence() const; + Domain::Alarm::Ptr alarm() const; static int autoSaveDelay(); @@ -108,6 +110,11 @@ void setByMonth(const QList< int > &monthList); void setByMonthDays(const QList< int > &dayList); + void setAlarm(const Domain::Alarm::Ptr &alarm); + void setAlarmType(int type); + void setAlarmPosition(int position); + void setAlarmOffset(int offset); + signals: void artifactChanged(const Domain::Artifact::Ptr &artifact); void hasTaskPropertiesChanged(bool hasTaskProperties); @@ -121,6 +128,7 @@ void relationsChanged(const QList &relations); void attachmentsChanged(const Domain::Artifact::Attachment::List &attachments); void recurrenceChanged(const Domain::Recurrence::Ptr &recurrence); + void alarmChanged(const Domain::Alarm::Ptr &alarm); private slots: void onTextChanged(const QString &text); @@ -132,6 +140,8 @@ void onStatusChanged(int status); void onRecurrenceChanged(const Domain::Recurrence::Ptr &recurrence); void onAttachmentsChanged(const Domain::Artifact::Attachment::List &attachments); + void onAlarmChanged(const Domain::Alarm::Ptr &alarm); + void onAlarmsChanged(Domain::Alarm::List); void save(); @@ -158,6 +168,7 @@ QList m_relations; Domain::Recurrence::Ptr m_recurrence; Domain::Artifact::Attachment::List m_attachments; + Domain::Alarm::Ptr m_alarm; QTimer *m_saveTimer; bool m_saveNeeded; diff --git a/src/presentation/artifacteditormodel.cpp b/src/presentation/artifacteditormodel.cpp --- a/src/presentation/artifacteditormodel.cpp +++ b/src/presentation/artifacteditormodel.cpp @@ -104,6 +104,11 @@ m_status = task->status(); m_recurrence = task->recurrence(); m_attachments = task->attachments(); + if (!task->alarms().isEmpty()) { + m_alarm = task->alarms().at(0); + } else { + m_alarm = Domain::Alarm::Ptr(0); + } connect(m_artifact.data(), SIGNAL(startDateChanged(QDateTime)), this, SLOT(onStartDateChanged(QDateTime))); @@ -119,6 +124,8 @@ this, SLOT(onRecurrenceChanged(Domain::Recurrence::Ptr))); connect(m_artifact.data(), SIGNAL(attachmentsChanged(Domain::Artifact::Attachment::List)), this, SLOT(onAttachmentsChanged(Domain::Artifact::Attachment::List))); + connect(m_artifact.data(), SIGNAL(alarmsChanged(Domain::Alarm::List)), + this, SLOT(onAlarmsChanged(Domain::Alarm::List))); } auto relationQuery = m_relationQueries->findRelations(m_artifact); @@ -140,6 +147,7 @@ emit relationsChanged(m_relations); emit recurrenceChanged(m_recurrence); emit attachmentsChanged(m_attachments); + emit alarmChanged(m_alarm); } void ArtifactEditorModel::addRelation(const Domain::Relation::Ptr &relation) @@ -495,6 +503,64 @@ return m_relations; } +Domain::Alarm::Ptr ArtifactEditorModel::alarm() const +{ + return m_alarm; +} + +void ArtifactEditorModel::setAlarm(const Domain::Alarm::Ptr &alarm) +{ + if (alarm == m_alarm) { + return; + } + + onAlarmChanged(alarm); + setSaveNeeded(true); +} + +void ArtifactEditorModel::setAlarmOffset(int offset) +{ + if (m_alarm->offset() == offset) { + return; + } + + m_alarm->setOffset(offset); + onAlarmChanged(m_alarm); + setSaveNeeded(true); +} + +void ArtifactEditorModel::setAlarmPosition(int p) +{ + auto position = static_cast(p); + if (m_alarm->position() == position) { + return; + } + + m_alarm->setPosition(position); + onAlarmChanged(m_alarm); + setSaveNeeded(true); +} + +void ArtifactEditorModel::setAlarmType(int t) +{ + auto type = static_cast(t); + if ((m_alarm && m_alarm->type() == type) + || (!m_alarm && type == Domain::Alarm::None)) { + return; + } + + if (!m_alarm && type != Domain::Alarm::None) { + m_alarm = Domain::Alarm::Ptr(new Domain::Alarm()); + } else if (m_alarm && type == Domain::Alarm::None) { + m_alarm = Domain::Alarm::Ptr(0); + } + if (m_alarm) { + m_alarm->setType(type); + } + onAlarmChanged(m_alarm); + setSaveNeeded(true); +} + void ArtifactEditorModel::onTextChanged(const QString &text) { m_text = text; @@ -549,6 +615,23 @@ emit attachmentsChanged(attachments); } +void ArtifactEditorModel::onAlarmChanged(const Domain::Alarm::Ptr &alarm) +{ + m_alarm = alarm; + emit alarmChanged(alarm); +} + +void ArtifactEditorModel::onAlarmsChanged(const Domain::Alarm::List &alarms) +{ + if (!alarms.isEmpty()) { + m_alarm = alarms.first(); + } else { + m_alarm = Domain::Alarm::Ptr(0); + } + emit alarmChanged(m_alarm); +} + + void ArtifactEditorModel::save() { if (!isSaveNeeded()) @@ -567,6 +650,17 @@ task->setProgress(m_progress); task->setStatus(m_status); task->setRecurrence(m_recurrence); + Domain::Alarm::List alarms = task->alarms(); + if (m_alarm) { + if (alarms.isEmpty()) { + alarms.append(m_alarm); + } else { + alarms[0] = m_alarm; + } + } else { + alarms = Domain::Alarm::List(); + } + task->setAlarms(alarms); m_taskRepository->update(task); } else { auto note = m_artifact.objectCast(); diff --git a/src/widgets/editorview.h b/src/widgets/editorview.h --- a/src/widgets/editorview.h +++ b/src/widgets/editorview.h @@ -70,6 +70,10 @@ void progressChanged(int progress); void statusChanged(int status); + void alarmTypeChanged(int type); + void alarmPositionChanged(int position); + void alarmOffsetChanged(int offset); + private slots: void onArtifactChanged(); void onHasTaskPropertiesChanged(); @@ -99,9 +103,17 @@ void onStartTimeEntered(const QTime &start); void onDueTimeEntered(const QTime &due); + void onAlarmChanged(); + void onAlarmTypeChanged(int type); + void onAlarmPositionChanged(int); + void onAlarmOffsetChanged(int); + void onAlarmEnableChanged(int); + void toggleFullscreenEditor(); private: + void fillAlarmCombo(); + QObject *m_model; QLabel *m_delegateLabel; @@ -122,6 +134,9 @@ QVBoxLayout *m_attachmentsLayout; QAbstractButton *m_addAttachmentButton; RecurrenceWidget *m_recurrenceWidget; + QComboBox *m_alarmTypeWidget; + QComboBox *m_alarmPositionWidget; + QSpinBox *m_alarmOffsetEdit; }; } diff --git a/src/widgets/editorview.cpp b/src/widgets/editorview.cpp --- a/src/widgets/editorview.cpp +++ b/src/widgets/editorview.cpp @@ -57,6 +57,17 @@ using namespace Widgets; +enum AlarmType { + AlarmNone, + AlarmDisplay, + AlarmAudio +}; + +enum AlarmPosition { + AlarmStart, + AlarmEnd +}; + EditorView::EditorView(QWidget *parent) : QWidget(parent), m_model(0), @@ -74,7 +85,10 @@ m_progressEdit(new QSpinBox(m_taskGroup)), m_relationsLayout(new QVBoxLayout), m_attachmentsLayout(new QVBoxLayout), - m_addAttachmentButton(new QPushButton(tr("Add attachment"), m_taskGroup)) + m_addAttachmentButton(new QPushButton(tr("Add attachment"), m_taskGroup)), + m_alarmTypeWidget(new QComboBox(m_taskGroup)), + m_alarmPositionWidget(new QComboBox(m_taskGroup)), + m_alarmOffsetEdit(new QSpinBox(m_taskGroup)) { // To avoid having unit tests talking to akonadi // while we don't need the completion for them @@ -94,12 +108,18 @@ m_startTodayButton->setObjectName("startTodayButton"); m_statusComboBox->setObjectName("statusComboBox"); m_progressEdit->setObjectName("progressEdit"); + m_alarmTypeWidget->setObjectName("alarmTypeWidget"); + m_alarmPositionWidget->setObjectName("alarmPositionWidget"); + m_alarmOffsetEdit->setObjectName("alarmOffsetEdit"); m_startDateEdit->setMinimumContentsLength(10); m_dueDateEdit->setMinimumContentsLength(10); m_progressEdit->setRange(0, 100); + m_alarmOffsetEdit->setRange(0,10000); + m_alarmOffsetEdit->setSuffix(" seconds"); + m_statusComboBox->addItem(tr("None"), Domain::Task::None); m_statusComboBox->addItem(tr("Needs action"), Domain::Task::NeedsAction); m_statusComboBox->addItem(tr("In process"), Domain::Task::InProcess); @@ -138,6 +158,12 @@ bottomHBox->addWidget(m_startTodayButton); bottomHBox->addStretch(); vbox->addLayout(bottomHBox); + auto alarmHBox= new QHBoxLayout; + alarmHBox->addWidget(new QLabel(tr("Alarm"), m_taskGroup)); + alarmHBox->addWidget(m_alarmTypeWidget, 1); + alarmHBox->addWidget(m_alarmOffsetEdit, 1); + alarmHBox->addWidget(m_alarmPositionWidget, 1); + vbox->addLayout(alarmHBox); auto progressHBox = new QHBoxLayout; progressHBox->addWidget(new QLabel(tr("Progress"), m_taskGroup)); progressHBox->addWidget(m_progressEdit, 1); @@ -191,8 +217,44 @@ connect(m_delegateEdit, SIGNAL(returnPressed()), this, SLOT(onDelegateEntered())); connect(m_progressEdit, SIGNAL(valueChanged(int)), this, SLOT(onProgressChanged(int))); connect(m_statusComboBox, SIGNAL(activated(int)), this, SLOT(onStatusChanged(int))); + connect(m_alarmTypeWidget, SIGNAL(currentIndexChanged(int)), this, SLOT(onAlarmEnableChanged(int))); + connect(m_alarmTypeWidget, SIGNAL(currentIndexChanged(int)), this, SLOT(onAlarmTypeChanged(int))); + connect(m_alarmPositionWidget, SIGNAL(currentIndexChanged(int)), this, SLOT(onAlarmPositionChanged(int))); + connect(m_alarmOffsetEdit, SIGNAL(valueChanged(int)), this, SLOT(onAlarmOffsetChanged(int))); setEnabled(false); + + fillAlarmCombo(); +} + +void EditorView::fillAlarmCombo() +{ + m_alarmTypeWidget->clear(); + m_alarmPositionWidget->clear(); + + for (int i=AlarmNone; i <= AlarmAudio; ++i) { + switch(i) { + case AlarmNone: + m_alarmTypeWidget->addItem(tr("None"), Domain::Alarm::None); + break; + case AlarmDisplay: + m_alarmTypeWidget->addItem(tr("Message"), Domain::Alarm::Display); + break; + case AlarmAudio: + m_alarmTypeWidget->addItem(tr("Audio"), Domain::Alarm::Audio); + } + } + + for(int i=AlarmStart; i <= AlarmEnd; ++i) { + switch(i) { + case AlarmStart: + m_alarmPositionWidget->addItem(tr("before start"), Domain::Alarm::Start); + break; + case AlarmEnd: + m_alarmPositionWidget->addItem(tr("before end"), Domain::Alarm::End); + } + } + onAlarmTypeChanged(AlarmNone); } void EditorView::toggleFullscreenEditor() @@ -235,6 +297,7 @@ onRelationsChanged(); onAttachmentsChanged(); onStatusChanged(); + onAlarmChanged(); connect(m_model, SIGNAL(artifactChanged(Domain::Artifact::Ptr)), this, SLOT(onArtifactChanged())); @@ -251,6 +314,7 @@ connect(m_model, SIGNAL(recurrenceChanged(Domain::Recurrence::Ptr)), this, SLOT(onRecurrenceChanged())); connect(m_model, SIGNAL(relationsChanged(QList)), this, SLOT(onRelationsChanged())); connect(m_model, SIGNAL(attachmentsChanged(Domain::Artifact::Attachment::List)), this, SLOT(onAttachmentsChanged())); + connect(m_model, SIGNAL(alarmChanged(Domain::Alarm::Ptr)), this, SLOT(onAlarmChanged())); connect(this, SIGNAL(titleChanged(QString)), m_model, SLOT(setTitle(QString))); connect(this, SIGNAL(textChanged(QString)), m_model, SLOT(setText(QString))); @@ -259,6 +323,9 @@ connect(this, SIGNAL(delegateChanged(QString, QString)), m_model, SLOT(setDelegate(QString, QString))); connect(this, SIGNAL(progressChanged(int)), m_model, SLOT(setProgress(int))); connect(this, SIGNAL(statusChanged(int)), m_model, SLOT(setStatus(int))); + connect(this, SIGNAL(alarmTypeChanged(int)),m_model, SLOT(setAlarmType(int))); + connect(this, SIGNAL(alarmPositionChanged(int)),m_model, SLOT(setAlarmPosition(int))); + connect(this, SIGNAL(alarmOffsetChanged(int)),m_model, SLOT(setAlarmOffset(int))); connect(m_recurrenceWidget, SIGNAL(frequencyChanged(Domain::Recurrence::Frequency,int)), m_model, SLOT(setFrequency(Domain::Recurrence::Frequency, int))); @@ -452,6 +519,59 @@ } } +void EditorView::onAlarmChanged() +{ + const auto alarm = m_model->property("alarm").value(); + if (!alarm) { + m_alarmTypeWidget->setCurrentIndex(AlarmNone); + onAlarmEnableChanged(AlarmNone); + return; + } + switch(alarm->type()) { + case Domain::Alarm::Display: + m_alarmTypeWidget->setCurrentIndex(AlarmDisplay); + onAlarmEnableChanged(AlarmDisplay); + break; + case Domain::Alarm::Audio: + m_alarmTypeWidget->setCurrentIndex(AlarmAudio); + onAlarmEnableChanged(AlarmAudio); + break; + } + + switch(alarm->position()) { + case Domain::Alarm::Start: + m_alarmPositionWidget->setCurrentIndex(AlarmStart); + break; + case Domain::Alarm::End: + m_alarmPositionWidget->setCurrentIndex(AlarmEnd); + break; + } + + m_alarmOffsetEdit->setValue(-alarm->offset()); +} + +void EditorView::onAlarmEnableChanged(int t) +{ + AlarmType type = static_cast(t); + bool enabled = (type != AlarmNone); + m_alarmOffsetEdit->setEnabled(enabled); + m_alarmPositionWidget->setEnabled(enabled); +} + +void EditorView::onAlarmTypeChanged(int index) +{ + emit alarmTypeChanged(m_alarmTypeWidget->itemData(index).toInt()); +} + +void EditorView::onAlarmPositionChanged(int index) +{ + emit alarmPositionChanged(m_alarmPositionWidget->itemData(index).toInt()); +} + +void EditorView::onAlarmOffsetChanged(int offset) +{ + emit alarmOffsetChanged(-offset); +} void EditorView::onRemoveRelationClicked() {