1 /*
2 TaskEditor.cpp
3
4 This file is part of Charm, a task-based time tracking application.
5
6 Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
7
8 Author: Mirko Boehm <mirko.boehm@kdab.com>
9 Author: Frank Osterfeld <frank.osterfeld@kdab.com>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "TaskEditor.h"
26 #include "SelectTaskDialog.h"
27 #include "ViewHelpers.h"
28
29 #include "Core/CharmConstants.h"
30 #include "Core/CharmDataModel.h"
31 #include "Core/TaskTreeItem.h"
32
33 #include <QCalendarWidget>
34 #include <QCheckBox>
35 #include <QPushButton>
36 #include <QMessageBox>
37
38 #include "ui_TaskEditor.h"
39
TaskEditor(QWidget * parent)40 TaskEditor::TaskEditor(QWidget *parent)
41 : QDialog(parent)
42 , m_ui(new Ui::TaskEditor)
43 {
44 m_ui->setupUi(this);
45 m_ui->dateEditFrom->calendarWidget()->setFirstDayOfWeek(Qt::Monday);
46 m_ui->dateEditFrom->calendarWidget()->setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers);
47 m_ui->dateEditTo->calendarWidget()->setFirstDayOfWeek(Qt::Monday);
48 m_ui->dateEditTo->calendarWidget()->setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers);
49 connect(m_ui->pushButtonParent, &QPushButton::clicked, this, &TaskEditor::slotSelectParent);
50 connect(m_ui->dateEditFrom, &QDateEdit::dateChanged, this, &TaskEditor::slotDateChanged);
51 connect(m_ui->dateEditTo, &QDateEdit::dateChanged, this, &TaskEditor::slotDateChanged);
52 connect(m_ui->checkBoxFrom, &QCheckBox::clicked, this, &TaskEditor::slotCheckBoxChecked);
53 connect(m_ui->checkBoxUntil, &QCheckBox::clicked, this, &TaskEditor::slotCheckBoxChecked);
54 }
55
~TaskEditor()56 TaskEditor::~TaskEditor()
57 {
58 }
59
setTask(const Task & task)60 void TaskEditor::setTask(const Task &task)
61 {
62 Q_ASSERT(m_ui);
63 m_task = task;
64 const TaskTreeItem &taskTreeItem
65 = MODEL.charmDataModel()->taskTreeItem(task.id());
66 m_ui->labelTaskName->setText(MODEL.charmDataModel()->fullTaskName(taskTreeItem.task()));
67 m_ui->lineEditName->setText(task.name());
68 m_ui->checkBoxTrackable->setChecked(task.trackable());
69 if (task.parent() != 0) {
70 const TaskTreeItem &parentItem
71 = MODEL.charmDataModel()->taskTreeItem(task.parent());
72 const QString name = parentItem.task().name();
73 m_ui->pushButtonParent->setText(name);
74 } else {
75 m_ui->pushButtonParent->setText(tr("Choose Parent Task"));
76 }
77 if (task.parent() == 0) {
78 m_ui->checkBoxTopLevel->setChecked(true);
79 } else {
80 m_ui->checkBoxTopLevel->setChecked(false);
81 }
82 QDate start = task.validFrom().date();
83 if (start.isValid()) {
84 m_ui->dateEditFrom->setDate(start);
85 m_ui->checkBoxFrom->setChecked(false);
86 } else {
87 m_ui->checkBoxFrom->setChecked(true);
88 m_ui->dateEditFrom->setDate(QDate::currentDate());
89 }
90 QDate end = task.validUntil().date();
91 if (end.isValid()) {
92 m_ui->dateEditTo->setDate(end);
93 m_ui->checkBoxUntil->setChecked(false);
94 } else {
95 m_ui->checkBoxUntil->setChecked(true);
96 m_ui->dateEditTo->setDate(QDate::currentDate());
97 }
98 m_ui->lineEditComment->setText(task.comment());
99 checkInvariants();
100 }
101
getTask() const102 Task TaskEditor::getTask() const
103 {
104 Task newTask = m_task;
105 newTask.setName(m_ui->lineEditName->text());
106 newTask.setTrackable(m_ui->checkBoxTrackable->isChecked());
107 if (m_ui->checkBoxTopLevel->isChecked())
108 newTask.setParent(0);
109 if (m_ui->checkBoxFrom->isChecked()) {
110 newTask.setValidFrom(QDateTime());
111 } else {
112 newTask.setValidFrom(m_ui->dateEditFrom->dateTime());
113 }
114 if (m_ui->checkBoxUntil->isChecked()) {
115 newTask.setValidUntil(QDateTime());
116 } else {
117 newTask.setValidUntil(m_ui->dateEditTo->dateTime());
118 }
119 newTask.setComment(m_ui->lineEditComment->text());
120 return newTask;
121 }
122
parentTreeIsTree(TaskId newParent,TaskId task)123 bool parentTreeIsTree(TaskId newParent, TaskId task)
124 {
125 QList<TaskId> parents;
126 TaskId parent = newParent;
127 while (parent != 0) {
128 parents << parent;
129 const TaskTreeItem &parentItem = MODEL.charmDataModel()->taskTreeItem(parent);
130 parent = parentItem.task().parent();
131 }
132 return !parents.contains(task);
133 }
134
slotSelectParent()135 void TaskEditor::slotSelectParent()
136 {
137 SelectTaskDialog dialog(this);
138 dialog.setNonTrackableSelectable();
139 Q_FOREVER {
140 if (dialog.exec()) {
141 TaskId newParentId = dialog.selectedTask();
142 const TaskTreeItem &parentItem
143 = MODEL.charmDataModel()->taskTreeItem(newParentId);
144 QString name = m_task.name();
145 QString parent = parentItem.task().name();
146 if (parentTreeIsTree(newParentId, m_task.id())) {
147 m_task.setParent(dialog.selectedTask());
148 if (newParentId != 0) {
149 m_ui->pushButtonParent->setText(parent);
150 } else {
151 m_ui->pushButtonParent->setText(tr("Choose Parent Task"));
152 }
153
154 break;
155 }
156 QMessageBox::information(this, tr("Please choose another task"),
157 tr(
158 "The task \"%1\" cannot be selected as the parent task for \"%2\","
159 " because they are the same, or \"%3\" is a direct or indirect subtask of \"%4\".")
160 .arg(parent, name, parent, name));
161 } else {
162 break;
163 }
164 }
165 }
166
slotDateChanged(const QDate &)167 void TaskEditor::slotDateChanged(const QDate &)
168 {
169 checkInvariants();
170 }
171
slotCheckBoxChecked(bool)172 void TaskEditor::slotCheckBoxChecked(bool)
173 {
174 checkInvariants();
175 }
176
checkInvariants()177 void TaskEditor::checkInvariants()
178 {
179 bool acceptable;
180 // the start and end dates are acceptable if
181 // * both start and end date are deactivated,
182 // * if only one date is set, or
183 // * if none are set, and the start date is before the end date
184 if (m_ui->checkBoxFrom->isChecked() && m_ui->checkBoxUntil->isChecked()) {
185 acceptable = true;
186 } else if (m_ui->checkBoxFrom->isChecked() || m_ui->checkBoxUntil->isChecked()) {
187 acceptable = true;
188 } else if (m_ui->dateEditFrom->dateTime() < m_ui->dateEditTo->dateTime()) {
189 acceptable = true;
190 } else {
191 acceptable = false;
192 }
193
194 m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable);
195 }
196