diff --git a/TaskBoard.pro b/TaskBoard.pro
index 0958cf9..af339db 100644
--- a/TaskBoard.pro
+++ b/TaskBoard.pro
@@ -68,6 +68,7 @@ linux-* {
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
+ src/frames/filterdialog.cpp \
src/frames/aboutdialog.cpp \
src/models/board.cpp \
src/main.cpp \
@@ -82,6 +83,7 @@ SOURCES += \
src/tools.cpp
HEADERS += \
+ src/frames/filterdialog.h \
src/frames/aboutdialog.h \
src/models/board.h \
src/frames/mainwindow.h \
@@ -95,6 +97,7 @@ HEADERS += \
src/tools.h
FORMS += \
+ src/frames/filterdialog.ui \
src/frames/aboutdialog.ui \
src/frames/mainwindow.ui \
src/frames/namedialog.ui \
diff --git a/resources.qrc b/resources.qrc
index d479d41..e9b45f4 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -1,5 +1,8 @@
resources/logo.png
+ resources/board_add.png
+ resources/task_add.png
+ resources/add_filter.png
diff --git a/resources/add_filter.png b/resources/add_filter.png
new file mode 100644
index 0000000..67323fd
Binary files /dev/null and b/resources/add_filter.png differ
diff --git a/resources/board_add.png b/resources/board_add.png
new file mode 100644
index 0000000..1d5e3bd
Binary files /dev/null and b/resources/board_add.png differ
diff --git a/resources/task_add.png b/resources/task_add.png
new file mode 100644
index 0000000..3ba8b0f
Binary files /dev/null and b/resources/task_add.png differ
diff --git a/src/frames/filterdialog.cpp b/src/frames/filterdialog.cpp
new file mode 100644
index 0000000..97aa56e
--- /dev/null
+++ b/src/frames/filterdialog.cpp
@@ -0,0 +1,80 @@
+#include "filterdialog.h"
+#include "ui_filterdialog.h"
+
+FilterDialog::FilterDialog(QString dialogTitle, QVector boards, QVector status, QVector priorities, QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::FilterDialog)
+{
+ ui->setupUi(this);
+ this->setWindowTitle(dialogTitle);
+
+ for (Board *b : boards)
+ {
+ QListWidgetItem *item = new QListWidgetItem();
+ item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
+ item->setCheckState(Qt::Unchecked);
+ item->setText(b->getName());
+ item->setData(1, b->getUuid());
+ ui->boardListWidget->addItem(item);
+ }
+
+ for (Status s : status)
+ {
+ QListWidgetItem *item = new QListWidgetItem();
+ item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
+ item->setCheckState(Qt::Unchecked);
+ item->setText(s.getName());
+ item->setData(1, s.getUUID());
+ ui->statusListWidget->addItem(item);
+ }
+
+ for (Priority p : priorities)
+ {
+ QListWidgetItem *item = new QListWidgetItem();
+ item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
+ item->setCheckState(Qt::Unchecked);
+ item->setText(p.getName());
+ item->setData(1, p.getUUID());
+ ui->priorityListWidget->addItem(item);
+ }
+}
+
+FilterDialog::~FilterDialog()
+{
+ delete ui;
+}
+
+const Filter FilterDialog::getFilter()
+{
+ QString name = ui->nameEdit->text();
+ uint8_t dateComparation = 0;
+ if (ui->dateComparationCombobox->currentIndex() > -1)
+ {
+ dateComparation = ui->dateComparationCombobox->currentIndex();
+ }
+ QVector boards;
+ for (int i = 0; i < ui->boardListWidget->count(); ++i) {
+ QListWidgetItem *item = ui->boardListWidget->item(i);
+ if (item->checkState() == Qt::Checked)
+ {
+ boards.append(item->data(1).toString());
+ }
+ }
+ QVector status;
+ for (int i = 0; i < ui->statusListWidget->count(); ++i) {
+ QListWidgetItem *item = ui->statusListWidget->item(i);
+ if (item->checkState() == Qt::Checked)
+ {
+ status.append(item->data(1).toString());
+ }
+ }
+ QVector priorities;
+ for (int i = 0; i < ui->priorityListWidget->count(); ++i) {
+ QListWidgetItem *item = ui->priorityListWidget->item(i);
+ if (item->checkState() == Qt::Checked)
+ {
+ priorities.append(item->data(1).toString());
+ }
+ }
+ return Filter(name, dateComparation, boards, status, priorities);
+}
diff --git a/src/frames/filterdialog.h b/src/frames/filterdialog.h
new file mode 100644
index 0000000..1aeaf59
--- /dev/null
+++ b/src/frames/filterdialog.h
@@ -0,0 +1,28 @@
+#ifndef FILTERDIALOG_H
+#define FILTERDIALOG_H
+
+#include
+
+#include "../models/board.h"
+#include "../models/priority.h"
+#include "../models/status.h"
+#include "../models/filter.h"
+
+namespace Ui {
+class FilterDialog;
+}
+
+class FilterDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit FilterDialog(QString dialogTitle, QVector boards, QVector status, QVector priorities, QWidget *parent = nullptr);
+ ~FilterDialog();
+ const Filter getFilter();
+
+private:
+ Ui::FilterDialog *ui;
+};
+
+#endif // FILTERDIALOG_H
diff --git a/src/frames/filterdialog.ui b/src/frames/filterdialog.ui
new file mode 100644
index 0000000..a99baf0
--- /dev/null
+++ b/src/frames/filterdialog.ui
@@ -0,0 +1,169 @@
+
+
+ FilterDialog
+
+
+ Qt::WindowModal
+
+
+
+ 0
+ 0
+ 449
+ 509
+
+
+
+ Dialog
+
+
+ true
+
+
+ -
+
+
-
+
+
+ Filter name
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ Date comparation
+
+
+
+ -
+
+
-
+
+ Ignore date
+
+
+ -
+
+ On time
+
+
+ -
+
+ End today
+
+
+ -
+
+ Ended
+
+
+
+
+
+
+ -
+
+
+ Boards (None = all)
+
+
+
+ -
+
+
+ Qt::NoContextMenu
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+ false
+
+
+
+ -
+
+
+ Status (None = all)
+
+
+
+ -
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+
+ -
+
+
+ Priority (None = all)
+
+
+
+ -
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Save
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ FilterDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ FilterDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/frames/mainwindow.cpp b/src/frames/mainwindow.cpp
index 77efbb5..ef0eba2 100644
--- a/src/frames/mainwindow.cpp
+++ b/src/frames/mainwindow.cpp
@@ -15,6 +15,7 @@
#include "aboutdialog.h"
#include "namedialog.h"
#include "taskdialog.h"
+#include "filterdialog.h"
#include "../tools.h"
MainWindow::MainWindow(QWidget *parent)
@@ -32,6 +33,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::openAbout);
connect(ui->actionNew, &QAction::triggered, this, &MainWindow::onNewBoardClick);
connect(ui->actionNew_task, &QAction::triggered, this, &MainWindow::onNewTaskClick);
+ connect(ui->actionNew_filter, &QAction::triggered, this, &MainWindow::onNewFilterClick);
connect(ui->boardList, &QListWidget::currentRowChanged, this, &MainWindow::onBoardSelected);
connect(ui->boardList, &QListWidget::customContextMenuRequested, this, &MainWindow::prepareBoardMenu);
connect(ui->taskList, &QTreeWidget::itemDoubleClicked, this, &MainWindow::onEditTask);
@@ -70,51 +72,57 @@ void MainWindow::openAbout()
void MainWindow::prepareBoardMenu(const QPoint &pos)
{
+ QMenu menu(this);
if (ui->boardList->selectedItems().length() == 1) {
- QMenu menu(this);
-
- QAction *renameAction = new QAction(tr("Rename this board"), this);
+ QAction *renameAction = new QAction(tr("Edit board"), this);
connect(renameAction, &QAction::triggered, this, &MainWindow::onEditNameBoardMenu);
menu.addAction(renameAction);
- menu.addSeparator();
-
- QAction *deleteAction = new QAction(tr("Delete this board"), this);
+ QAction *deleteAction = new QAction(tr("Delete the board and all the tasks"), this);
connect(deleteAction, &QAction::triggered, this, &MainWindow::onRemoveBoardMenu);
menu.addAction(deleteAction);
- menu.exec(ui->boardList->mapToGlobal(pos));
+ menu.addSeparator();
}
+ QAction *addAction = new QAction(tr("New board"), this);
+ connect(addAction, &QAction::triggered, this, &MainWindow::onNewBoardClick);
+ menu.addAction(addAction);
+
+ menu.exec(ui->boardList->mapToGlobal(pos));
}
void MainWindow::prepareTaskMenu(const QPoint &pos)
{
+ QMenu menu(this);
if (ui->taskList->selectedItems().length() == 1) {
- QMenu menu(this);
-
QAction *renameAction = new QAction(tr("Edit the task"), this);
connect(renameAction, &QAction::triggered, this, &MainWindow::onEditNameTaskMenu);
menu.addAction(renameAction);
- menu.addSeparator();
-
QAction *deleteAction = new QAction(tr("Delete from the board"), this);
connect(deleteAction, &QAction::triggered, this, &MainWindow::onRemoveTaskMenu);
menu.addAction(deleteAction);
- menu.exec(ui->taskList->mapToGlobal(pos));
+ menu.addSeparator();
}
+ QAction *addAction = new QAction(tr("New task"), this);
+ connect(addAction, &QAction::triggered, this, &MainWindow::onNewTaskClick);
+ menu.addAction(addAction);
+
+ menu.exec(ui->taskList->mapToGlobal(pos));
}
void MainWindow::onNewBoardClick()
{
- NameDialog dialog("Create a board", "New empty board", this);
+ NameDialog dialog("Create a board", "New empty board", "", this);
if (dialog.exec() == QDialog::DialogCode::Accepted)
{
QString name = dialog.getChoosenName();
- Board *b = new Board(name);
+ QString desc = dialog.getDescription();
+ Board *b = new Board(name, desc);
boards.append(b);
QListWidgetItem *item = new QListWidgetItem(name);
+ item->setStatusTip(desc);
ui->boardList->addItem(item);
save();
}
@@ -138,6 +146,17 @@ void MainWindow::onNewTaskClick()
}
}
+void MainWindow::onNewFilterClick()
+{
+ FilterDialog dialog("New filter", boards, status, priorities, this);
+ if (dialog.exec() == QDialog::DialogCode::Accepted)
+ {
+ Filter f = dialog.getFilter();
+ QListWidgetItem *item = new QListWidgetItem(f.getName());
+ ui->filterListWidget->addItem(item);
+ }
+}
+
void MainWindow::onBoardSelected(int i)
{
selectedBoardIndex = i;
@@ -145,11 +164,13 @@ void MainWindow::onBoardSelected(int i)
{
Board *b = boards[selectedBoardIndex];
ui->label->setText(b->getName());
+ ui->boardDescription->setText(b->getDescription());
ui->actionNew_task->setDisabled(false);
}
else
{
- ui->label->setText("<- Select a board");
+ ui->label->setText("No board selected");
+ ui->boardDescription->clear();
ui->actionNew_task->setDisabled(true);
}
redrawTaskTree();
@@ -213,13 +234,18 @@ void MainWindow::onEditNameBoardMenu()
if (selectedBoardIndex > -1)
{
Board *b = boards.at(selectedBoardIndex);
- NameDialog dialog("Edit board name", b->getName(), this);
+ NameDialog dialog("Edit board name", b->getName(), b->getDescription(), this);
if (dialog.exec() == QDialog::DialogCode::Accepted)
{
- QString newName= dialog.getChoosenName();
+ QString newName = dialog.getChoosenName();
+ QString newDesc = dialog.getDescription();
b->setName(newName);
- ui->boardList->item(selectedBoardIndex)->setText(newName);
+ b->setDescription(newDesc);
+ QListWidgetItem *item = ui->boardList->item(selectedBoardIndex);
+ item->setText(newName);
+ item->setToolTip(newDesc);
ui->label->setText(newName);
+ ui->boardDescription->setText(newDesc);
save();
}
}
@@ -281,6 +307,12 @@ QVector MainWindow::defaultStatus()
return res;
}
+QVector MainWindow::defaultFilters()
+{
+ QVector res;
+ return res;
+}
+
const QString MainWindow::getPriorityLabel(QString uuid)
{
QString res = "";
@@ -416,6 +448,7 @@ void MainWindow::redrawBoardList()
foreach (Board *b, boards)
{
QListWidgetItem *item = new QListWidgetItem(b->getName());
+ item->setToolTip(b->getDescription());
l->addItem(item);
}
}
diff --git a/src/frames/mainwindow.h b/src/frames/mainwindow.h
index 807dedd..c48e89d 100644
--- a/src/frames/mainwindow.h
+++ b/src/frames/mainwindow.h
@@ -9,6 +9,7 @@
#include "../models/priority.h"
#include "../models/status.h"
#include "../models/board.h"
+#include "../models/filter.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@@ -27,6 +28,7 @@ private slots:
void openAbout();
void onNewBoardClick();
void onNewTaskClick();
+ void onNewFilterClick();
void onBoardSelected(int i);
void onEditTask(QTreeWidgetItem*);
void onRemoveBoardMenu();
@@ -45,9 +47,11 @@ private:
QVector priorities;
QVector status;
QVector boards;
+ QVector filters;
QVector defaultPriorities();
QVector defaultStatus();
+ QVector defaultFilters();
const QString getPriorityLabel(QString uuid);
const QString getStatusLabel(QString uuid);
diff --git a/src/frames/mainwindow.ui b/src/frames/mainwindow.ui
index 677e527..4d7effd 100644
--- a/src/frames/mainwindow.ui
+++ b/src/frames/mainwindow.ui
@@ -27,35 +27,82 @@
-
-
-
-
-
- 250
- 0
-
+
+
+ QLayout::SetMinimumSize
-
-
- 250
- 16777215
-
-
-
- true
-
-
+
-
+
+
+ Filters
+
+
+
+ -
+
+
+
+ 250
+ 0
+
+
+
+
+ 250
+ 250
+
+
+
+
+ -
+
+
+ Boards
+
+
+
+ -
+
+
+
+ 250
+ 0
+
+
+
+
+ 250
+ 16777215
+
+
+
+ true
+
+
+
+
-
+
+ QLayout::SetMaximumSize
+
-
- 26
+ 19
- <- Select a board
+ No board selected
+
+
+
+ -
+
+
+ Create or select a board to start
@@ -101,7 +148,7 @@
0
0
1159
- 24
+ 23
+
+
+ true
+
+
+ toolBar
+
+
+ false
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ false
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
Preferences
+
+
+ :/images/resources/board_add.png:/images/resources/board_add.png
+
New Board
+
+ Ctrl+N, Ctrl+B
+
@@ -147,11 +228,32 @@
false
+
+
+ :/images/resources/task_add.png:/images/resources/task_add.png
+
New task
+
+ Ctrl+N, Ctrl+T
+
+
+
+
+
+ :/images/resources/add_filter.png:/images/resources/add_filter.png
+
+
+ New filter
+
+
+ Ctrl+N, Ctrl+F
+
-
+
+
+
diff --git a/src/frames/namedialog.cpp b/src/frames/namedialog.cpp
index 624f48e..909fd31 100644
--- a/src/frames/namedialog.cpp
+++ b/src/frames/namedialog.cpp
@@ -1,7 +1,7 @@
#include "namedialog.h"
#include "ui_namedialog.h"
-NameDialog::NameDialog(QString label, QString defaultName, QWidget *parent) :
+NameDialog::NameDialog(QString label, QString defaultName, QString description, QWidget *parent) :
QDialog(parent),
ui(new Ui::NameDialog)
{
@@ -9,6 +9,7 @@ NameDialog::NameDialog(QString label, QString defaultName, QWidget *parent) :
this->setWindowTitle(label);
this->defaultName = defaultName;
ui->lineEdit->setText(defaultName);
+ ui->descriptionTextEdit->setPlainText(description);
}
NameDialog::~NameDialog()
@@ -24,3 +25,10 @@ const QString NameDialog::getChoosenName()
}
return defaultName;
}
+
+const QString NameDialog::getDescription()
+{
+ return ui->descriptionTextEdit->toPlainText();
+}
+
+
diff --git a/src/frames/namedialog.h b/src/frames/namedialog.h
index 0982c39..8f6cf33 100644
--- a/src/frames/namedialog.h
+++ b/src/frames/namedialog.h
@@ -12,9 +12,10 @@ class NameDialog : public QDialog
Q_OBJECT
public:
- explicit NameDialog(QString label, QString defaultName, QWidget *parent = nullptr);
+ explicit NameDialog(QString label, QString defaultName, QString description, QWidget *parent = nullptr);
~NameDialog();
const QString getChoosenName();
+ const QString getDescription();
private:
Ui::NameDialog *ui;
diff --git a/src/frames/namedialog.ui b/src/frames/namedialog.ui
index 41a3dff..1e4eb9c 100644
--- a/src/frames/namedialog.ui
+++ b/src/frames/namedialog.ui
@@ -10,19 +10,19 @@
0
0
400
- 133
+ 227
400
- 133
+ 227
400
- 133
+ 227
@@ -34,8 +34,8 @@
- 40
- 90
+ 50
+ 190
341
32
@@ -51,7 +51,7 @@
10
- 50
+ 33
381
21
@@ -61,7 +61,7 @@
10
- 30
+ 13
58
16
@@ -70,6 +70,29 @@
Name
+
+
+
+ 10
+ 70
+ 181
+ 18
+
+
+
+ Description
+
+
+
+
+
+ 10
+ 90
+ 381
+ 91
+
+
+
diff --git a/src/models/board.cpp b/src/models/board.cpp
index 6db71a0..79bedf2 100644
--- a/src/models/board.cpp
+++ b/src/models/board.cpp
@@ -3,16 +3,18 @@
#define NAME_KEY "name"
#define TASKS_KEY "tasks"
#define UUID_KEY "uuid"
+#define DESCRIPTION_KEY "description"
#include
#include
#include
-Board::Board(QString name)
+Board::Board(QString name, QString description)
{
QUuid uuid = QUuid::createUuid();
this->uuid = uuid.toString(QUuid::WithoutBraces);
this->name = name;
+ this->description = description;
}
Board::Board(QJsonObject obj)
@@ -20,8 +22,9 @@ Board::Board(QJsonObject obj)
QUuid uuid = QUuid::createUuid();
this->uuid = obj[UUID_KEY].toString(uuid.toString(QUuid::WithoutBraces));
this->name = obj[NAME_KEY].toString("!Missing name!");
+ this->description = obj[DESCRIPTION_KEY].toString("");
QJsonArray jsonTasks = obj[TASKS_KEY].toArray();
- for (QJsonValue value : jsonTasks) {
+ foreach (QJsonValue value, jsonTasks) {
Task *t = new Task(value.toObject());
this->tasks.append(t);
}
@@ -46,11 +49,21 @@ const QString Board::getName()
return name;
}
+const QString Board::getDescription()
+{
+ return description;
+}
+
void Board::setName(const QString name)
{
this->name = name;
}
+void Board::setDescription(const QString description)
+{
+ this->description = description;
+}
+
void Board::add(Task t)
{
tasks.append(new Task(t));
@@ -87,6 +100,7 @@ const QJsonObject Board::toJson()
QJsonObject obj;
obj[NAME_KEY] = this->name;
obj[TASKS_KEY] = array;
+ obj[DESCRIPTION_KEY] = description;
return obj;
}
diff --git a/src/models/board.h b/src/models/board.h
index 4089e81..bf1dffb 100644
--- a/src/models/board.h
+++ b/src/models/board.h
@@ -10,13 +10,15 @@
class Board
{
public:
- Board(QString name);
+ Board(QString name, QString description);
Board(QJsonObject);
~Board();
const QString getUuid();
const QString getName();
+ const QString getDescription();
void setName(const QString name);
+ void setDescription(const QString description);
void add(Task);
void remove(uint16_t index);
Task *taskAt(uint16_t);
@@ -28,6 +30,7 @@ private:
QVector tasks;
QString uuid;
QString name;
+ QString description;
};
diff --git a/src/models/filter.cpp b/src/models/filter.cpp
index 6542c1c..6f58df9 100644
--- a/src/models/filter.cpp
+++ b/src/models/filter.cpp
@@ -1,4 +1,5 @@
#include "filter.h"
+#include "qjsonarray.h"
#define NAME_KEY "name"
#define DATE_KEY "date"
@@ -6,7 +7,7 @@
#define STATUS_KEY "status"
#define PRIORITY_KEY "priority"
-filter::filter(QString name, uint8 expectedForComparator, QVector boards, QVector status, QVector priorities)
+Filter::Filter(QString name, uint8_t expectedForComparator, QVector boards, QVector status, QVector priorities)
{
this->name = name;
this->expectedForComparator = expectedForComparator;
@@ -15,7 +16,7 @@ filter::filter(QString name, uint8 expectedForComparator, QVector board
this->priorities = priorities;
}
-filter::filter(QJsonObject obj)
+Filter::Filter(QJsonObject obj)
{
this->name = obj[NAME_KEY].toString("!Missing name!");
this->expectedForComparator = obj[DATE_KEY].toInt();
@@ -45,7 +46,7 @@ filter::filter(QJsonObject obj)
}
}
-QVector filter::get(QVector allBoards)
+QVector Filter::get(QVector allBoards)
{
QDate now = QDate::currentDate();
QVector selectedBoards;
@@ -85,7 +86,7 @@ QVector filter::get(QVector allBoards)
return result;
}
-bool filter::filterStatus(Task *t)
+bool Filter::filterStatus(Task *t)
{
if (status.count() == 0)
{
@@ -102,7 +103,7 @@ bool filter::filterStatus(Task *t)
return result;
}
-bool filter::filterPriority(Task *t)
+bool Filter::filterPriority(Task *t)
{
if (priorities.count() == 0)
{
@@ -119,7 +120,7 @@ bool filter::filterPriority(Task *t)
return result;
}
-bool filter::filterDate(Task *t, QDate now)
+bool Filter::filterDate(Task *t, QDate now)
{
switch (expectedForComparator) {
case 0:
@@ -134,7 +135,12 @@ bool filter::filterDate(Task *t, QDate now)
return false;
}
-const QJsonObject filter::toJson()
+const QString Filter::getName()
+{
+ return name;
+}
+
+const QJsonObject Filter::toJson()
{
QJsonObject obj;
obj[name] = name;
diff --git a/src/models/filter.h b/src/models/filter.h
index df3929c..c0f0513 100644
--- a/src/models/filter.h
+++ b/src/models/filter.h
@@ -8,7 +8,7 @@
#include "task.h"
#include "board.h"
-class filter
+class Filter
{
private:
QString name;
@@ -19,14 +19,17 @@ private:
QVector status;
QVector priorities;
public:
- filter(QString name, uint8 expectedForComparator,QVector boards,QVector status,QVector priorities);
- filter(QJsonObject obj);
+ Filter(QString name, uint8_t expectedForComparator,QVector boards,QVector status,QVector priorities);
+ Filter(QJsonObject obj);
QVector get(QVector);
bool filterStatus(Task *t);
bool filterPriority(Task *t);
bool filterDate(Task *t, QDate now);
+
+ const QString getName();
+
const QJsonObject toJson();
};