commit 523a4085cc6252e5680bb87e3d6d6d3228689161 Author: Aurélie DELHAIE Date: Sat Mar 14 05:27:54 2026 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca8b61e --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash +**/.qmlls.ini + +# qtcreator generated files +*.pro.user* +*.qbs.user* +CMakeLists.txt.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + +# Directories with generated files +.moc/ +.obj/ +.pch/ +.rcc/ +.uic/ +/build*/ +/.qtcreator/ diff --git a/ToDo.pro b/ToDo.pro new file mode 100644 index 0000000..a5fb6bc --- /dev/null +++ b/ToDo.pro @@ -0,0 +1,97 @@ +QT += widgets + +CONFIG += c++17 + +QMAKE_CXXFLAGS += -Wall -Wextra -Wpedantic +QMAKE_CXXFLAGS += -Werror + +win32:VERSION = 3.0.0.0 # major.minor.patch.build +else:VERSION = 3.0.0 # major.minor.patch + +DEFINES += APP_VERSION=\"\\\"$${VERSION}\\\"\" +DEFINES += APP_NAME=\"\\\"ToDo\\\"\" + +# remove possible other optimization flags +win32 { + message("Build for Windows") + QMAKE_CXXFLAGS_RELEASE -= -O + QMAKE_CXXFLAGS_RELEASE -= -O1 + QMAKE_CXXFLAGS_RELEASE *= -O2 + DEFINES += APP_OS=\"\\\"Windows\\\"\" + DEFINES += APP_OS_VERSION=\"\\\"$$system(ver)\\\"\" + equals(QMAKE_TARGET.arch, arm64) { + message("CPU Architecture : aarch64") + DEFINES += APP_ARCH=\"\\\"arm64\\\"\" + } + equals(QMAKE_TARGET.arch, x86_64) { + message("CPU Architecture : x64") + QMAKE_CXXFLAGS_RELEASE += -favor:INTEL64 + DEFINES += APP_ARCH=\"\\\"x64\\\"\" + } + RC_ICONS = icon.ico + QMAKE_TARGET_COMPANY = "Aurelie Delhaie" + QMAKE_TARGET_PRODUCT = "ToDo" + QMAKE_TARGET_DESCRIPTION = "ToDo" +} + +macx { + message("Build for macOS") + #ICON = icon.icns + #QMAKE_INFO_PLIST = Info.plist + QMAKE_CXXFLAGS_RELEASE -= -O + QMAKE_CXXFLAGS_RELEASE -= -O1 + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE *= -O3 + QMAKE_APPLE_DEVICE_ARCHS = arm64 + DEFINES += APP_OS=\"\\\"macOS\\\"\" + DEFINES += APP_OS_VERSION=\"\\\"$$system(uname -r)\\\"\" + DEFINES += APP_ARCH=\"\\\"universal\\\"\" +} + +linux-* { + message("Build for Linux") + DEFINES += APP_OS=\"\\\"$$system(cat /etc/issue | cut -d\' \' -f1)\\\"\" + DEFINES += APP_OS_VERSION=\"\\\"$$system(uname -r)\\\"\" + DEFINES += APP_ARCH=\"\\\"$$system(uname -m)\\\"\" + ARCH = $$system(uname -m) + equals(ARCH, aarch64) { + message("CPU Architecture : aarch64") + QMAKE_CXXFLAGS_RELEASE += -mtune=cortex-a72 + } + equals(ARCH, amd64) { + message("CPU Architecture : amd64") + QMAKE_CXXFLAGS_RELEASE += -march=skylake + } + QMAKE_CXXFLAGS_RELEASE *= -O3 +} + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + dialog.cpp \ + list.cpp \ + listservice.cpp \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + dialog.h \ + list.h \ + listservice.h \ + mainwindow.h + +FORMS += \ + dialog.ui \ + mainwindow.ui + +TRANSLATIONS += \ + ToDo_en_150.ts +CONFIG += lrelease +CONFIG += embed_translations + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/ToDo_en_150.ts b/ToDo_en_150.ts new file mode 100644 index 0000000..0bdd0ba --- /dev/null +++ b/ToDo_en_150.ts @@ -0,0 +1,3 @@ + + + diff --git a/dialog.cpp b/dialog.cpp new file mode 100644 index 0000000..9691ab1 --- /dev/null +++ b/dialog.cpp @@ -0,0 +1,36 @@ +#include "dialog.h" +#include "ui_dialog.h" + +Dialog::Dialog(QWidget *parent, QString title, QString headline, QString message) : QDialog(parent), ui(new Ui::Dialog) +{ + ui->setupUi(this); + this->setWindowTitle(title); + ui->headline->setText(headline); + ui->message->setText(message); +} + +Dialog::~Dialog() +{ + delete ui; +} + +QString Dialog::getInput() +{ + if (this->result() != Accepted) { + return ""; + } + return this->ui->lineEdit->text(); +} + + +void Dialog::on_buttonBox_accepted() +{ + accept(); +} + + +void Dialog::on_buttonBox_rejected() +{ + reject(); +} + diff --git a/dialog.h b/dialog.h new file mode 100644 index 0000000..9a7b9ab --- /dev/null +++ b/dialog.h @@ -0,0 +1,29 @@ +#ifndef DIALOG_H +#define DIALOG_H + +#include + +namespace Ui { +class Dialog; +} + +class Dialog : public QDialog +{ + Q_OBJECT + +public: + Dialog(QWidget *parent, QString title, QString headline, QString message); + ~Dialog(); + + QString getInput(); + +private slots: + void on_buttonBox_accepted(); + + void on_buttonBox_rejected(); + +private: + Ui::Dialog *ui; +}; + +#endif // DIALOG_H diff --git a/dialog.ui b/dialog.ui new file mode 100644 index 0000000..549d341 --- /dev/null +++ b/dialog.ui @@ -0,0 +1,186 @@ + + + Dialog + + + Qt::WindowModality::ApplicationModal + + + + 0 + 0 + 454 + 176 + + + + + 454 + 176 + + + + + 454 + 176 + + + + Dialog + + + background-color: rgb(249, 255, 251); + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + QLayout::SizeConstraint::SetDefaultConstraint + + + + + + 16777215 + 50 + + + + + 22 + Light + + + + background-color: rgb(138, 176, 106); +padding: 6px; +padding-left: 20 px; +padding-right: 20px; + + + + + + + + + + + 16777215 + 40 + + + + color: rgb(13, 13, 13); +padding: 6px; +padding-left: 20px; +padding-right: 20px; + + + + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + + + + + + margin: 6px; +margin-left: 20px; +margin-right: 20px; +background-color: rgb(243, 243, 243); +padding: 4px; +color: rgb(13, 13, 13); +border: 2px solid rgb(230, 230, 230); + + + + + + + 0 + + + + + Qt::Orientation::Horizontal + + + QSizePolicy::Policy::Fixed + + + + 20 + 30 + + + + + + + + QPushButton { + border: none; + color: rgb(12, 12, 12); + background-color: rgb(217, 217, 217); + padding: 6px; +} + +QPushButton::pressed { + background-color: ; + background-color: rgb(192, 192, 192); +} + + + QDialogButtonBox::StandardButton::Discard|QDialogButtonBox::StandardButton::Save + + + + + + + Qt::Orientation::Horizontal + + + QSizePolicy::Policy::Fixed + + + + 20 + 30 + + + + + + + + + + + + + diff --git a/list.cpp b/list.cpp new file mode 100644 index 0000000..2af90a6 --- /dev/null +++ b/list.cpp @@ -0,0 +1,34 @@ +#include "list.h" + +List::List(QUuid uuid, QString name) +{ + this->uuid = uuid; + this->name = name; +} + +List::List(QString name) +{ + this->uuid = QUuid::createUuid(); + this->name = name; +} + +QUuid List::getUUID() +{ + return this->uuid; +} + +QString List::getName() +{ + return this->name; +} + +void List::setName(QString value) +{ + this->name = value; +} + +List List::duplicate() +{ + List l = List(this->getName() + " (copy)"); + return l; +} diff --git a/list.h b/list.h new file mode 100644 index 0000000..b3e9e3a --- /dev/null +++ b/list.h @@ -0,0 +1,26 @@ +#ifndef LIST_H +#define LIST_H + +#include +#include + +class List +{ +private: + QUuid uuid; + QString name; + +public: + List() {} + List(QUuid uuid, QString name); + List(QString name); + + QUuid getUUID(); + QString getName(); + + void setName(QString value); + List duplicate(); + +}; + +#endif // LIST_H diff --git a/listservice.cpp b/listservice.cpp new file mode 100644 index 0000000..23b0a3b --- /dev/null +++ b/listservice.cpp @@ -0,0 +1,50 @@ +#include "listservice.h" + +ListService* ListService::_instance = nullptr; + +ListService::ListService() {} + +ListService *ListService::getInstance() +{ + if (_instance == nullptr) { + _instance = new ListService(); + } + + return _instance; +} + +List ListService::create(QString name) +{ + // create the object, the uuid is already assigned by itself + List l = List(name); + + // store + // TODO: implement the real datastore (SQLite or something like that) + this->store[l.getUUID().toUInt128()] = l; + + // return the actual value + onListCreated(l); + return l; +} + +List ListService::update(QUuid uuid, QString newName) +{ + if (!this->store.contains(uuid.toUInt128())) { + throw new std::exception(); + } + + List l = this->store.value(uuid.toUInt128(), List("!!!")); + l.setName(newName); + this->store[uuid.toUInt128()] = l; + + onListUpdated(l); + return l; +} + +void ListService::remove(QUuid uuid) +{ + this->store.remove(uuid.toUInt128()); + onListDeleted(uuid); +} + + diff --git a/listservice.h b/listservice.h new file mode 100644 index 0000000..7a7ea35 --- /dev/null +++ b/listservice.h @@ -0,0 +1,37 @@ +#ifndef LISTSERVICE_H +#define LISTSERVICE_H + +#include +#include + +#include "list.h" + +/* + * + * ListService is a singleton that query the "lists" over the datasource layer + * + */ +class ListService : public QObject +{ + Q_OBJECT +private: + ListService(); + static ListService* _instance; + + QMap store; + +public: + static ListService* getInstance(); + + List create(QString name); + List update(QUuid uuid, QString newName); + void remove(QUuid uuid); + +signals: + void onListCreated(List value); + void onListUpdated(List value); + void onListDeleted(QUuid uuid); + +}; + +#endif // LISTSERVICE_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..43b7ce9 --- /dev/null +++ b/main.cpp @@ -0,0 +1,23 @@ +#include "mainwindow.h" + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QTranslator translator; + const QStringList uiLanguages = QLocale::system().uiLanguages(); + for (const QString &locale : uiLanguages) { + const QString baseName = "ToDo_" + QLocale(locale).name(); + if (translator.load(":/i18n/" + baseName)) { + a.installTranslator(&translator); + break; + } + } + MainWindow w; + w.show(); + return QCoreApplication::exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..3b56b2e --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,54 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +#include "dialog.h" +#include "listservice.h" + +#include +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + /* + * Events + */ + + // ui + connect(ui->addListButton, &QPushButton::clicked, this, &MainWindow::openCreateListDialog); + + // services + connect(ListService::getInstance(), &ListService::onListCreated, this, &MainWindow::onListCreated); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::openCreateListDialog(bool _) +{ + // create the input dialog + Dialog d = Dialog(this, "Create a list", "New List", "Give a name to this list"); + auto res = d.exec(); + + // execute, ignore if not saved + if (res != QDialog::Accepted) { + return; + } + + QString newListName = d.getInput(); + ListService::getInstance()->create(newListName); +} + +void MainWindow::onListCreated(List value) +{ + QListWidgetItem* item = new QListWidgetItem(); + item->setText(value.getName()); + item->setData(Qt::UserRole, QVariant(value.getUUID())); + + this->ui->lists->addItem(item); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..b12489a --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,29 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include "list.h" + +QT_BEGIN_NAMESPACE +namespace Ui { +class MainWindow; +} +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow() override; + +private slots: + void openCreateListDialog(bool); + void onListCreated(List value); + +private: + Ui::MainWindow *ui; + +}; +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..363818d --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,303 @@ + + + MainWindow + + + + 0 + 0 + 1032 + 629 + + + + + 1032 + 629 + + + + MainWindow + + + background-color: rgb(249, 255, 251); + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + 0 + + + QLayout::SizeConstraint::SetDefaultConstraint + + + + + + 250 + 50 + + + + + 250 + 50 + + + + + 28 + DemiBold + + + + background-color: rgb(119, 167, 92); +border: none; +padding-left: 2px; +border-bottom: 2px solid rgb(242, 242, 242) + + + 0 + + + ToDo + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter + + + + + + + + 250 + 0 + + + + + 250 + 16777215 + + + + + 15 + Light + + + + QListView { + show-decoration-selected: 1; /* make the selection span the entire width of the view */ + background-color: rgb(119, 167, 92); + border: none; + padding: 2px; + padding-top: 14px; +} + +QListView::item { + padding: 8px; + border: none; +} + +QListView::item:selected { + background-color: rgb(170, 216, 130); +} + +QListView::item:selected:!active { + background: none; +} + +QListView::item:selected:active { + background-color: rgb(170, 216, 130); +} + +QListView::item:hover { + background-color: rgb(152, 193, 116); +} + + + QFrame::Shadow::Plain + + + 0 + + + 2 + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + false + + + Qt::DropAction::IgnoreAction + + + Qt::DropAction::IgnoreAction + + + + + + + + 250 + 0 + + + + + 250 + 16777215 + + + + background-color: rgb(138, 176, 106); + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + border: none; +padding: 6px; + + + + + + + + + true + + + + + + + + + + + + false + + + QListView { + show-decoration-selected: 1; /* make the selection span the entire width of the view */ + background-color: rgb(242, 242, 242); + border: none; + padding: 2px; + color: rgb(13, 13, 13); +} + +QListView::item { + margin: 2px; + padding: 8px; + border: none; +} + +QListView::item:alternate { + background: #EEEEEE; +} + +QListView::item:selected { + background-color: rgb(154, 154, 154); +} + +QListView::item:selected:!active { + background: none; +} + +QListView::item:selected:active { + background-color: rgb(154, 154, 154); +} + +QListView::item:hover { + background-color: rgb(204, 204, 204); +} + + + QFrame::Shadow::Plain + + + 0 + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + false + + + Qt::DropAction::IgnoreAction + + + QAbstractItemView::SelectionMode::NoSelection + + + Qt::DropAction::IgnoreAction + + + + + + + + + + +