Add folder support

This commit is contained in:
Aurélie Delhaie
2022-10-22 19:33:54 +02:00
parent 8ceae034e1
commit 7b17dfb044
35 changed files with 1299 additions and 1313 deletions

View File

@@ -23,7 +23,7 @@
</size>
</property>
<property name="windowTitle">
<string>About TaskNote</string>
<string>About WorkPad</string>
</property>
<property name="modal">
<bool>true</bool>
@@ -64,7 +64,7 @@
</font>
</property>
<property name="text">
<string>TaskNote</string>
<string>WorkPad</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>

View File

@@ -0,0 +1,19 @@
#include "createdialog.h"
#include "ui_createdialog.h"
CreateDialog::CreateDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CreateDialog)
{
ui->setupUi(this);
}
CreateDialog::~CreateDialog()
{
delete ui;
}
QString CreateDialog::getTitle()
{
return ui->lineEdit->text();
}

23
src/frames/createdialog.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef CREATEDIALOG_H
#define CREATEDIALOG_H
#include <QDialog>
namespace Ui {
class CreateDialog;
}
class CreateDialog : public QDialog
{
Q_OBJECT
public:
explicit CreateDialog(QWidget *parent = nullptr);
~CreateDialog();
QString getTitle();
private:
Ui::CreateDialog *ui;
};
#endif // CREATEDIALOG_H

111
src/frames/createdialog.ui Normal file
View File

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CreateDialog</class>
<widget class="QDialog" name="CreateDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>139</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>139</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>139</height>
</size>
</property>
<property name="windowTitle">
<string>Create</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>100</y>
<width>381</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>141</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>24</pointsize>
</font>
</property>
<property name="text">
<string>Create</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>381</width>
<height>25</height>
</rect>
</property>
<property name="placeholderText">
<string>Title</string>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CreateDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CreateDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,21 +1,29 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "aboutdialog.h"
#include "createdialog.h"
#include "movedialog.h"
#include "renamedialog.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer(this);
connect(ui->actionAdd_folder, &QAction::triggered, this, &MainWindow::createFolder);
connect(ui->actionAdd, &QAction::triggered, this, &MainWindow::createNote);
connect(ui->actionRemove, &QAction::triggered, this, &MainWindow::removeSelected);
connect(ui->actionSave, &QAction::triggered, this, &MainWindow::save);
connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::showAboutBox);
connect(ui->noteList, &QListWidget::currentRowChanged, this, &MainWindow::selectionChanged);
connect(ui->titleEdit, &QLineEdit::textChanged, this, &MainWindow::titleChanged);
connect(ui->contentEdit, &QPlainTextEdit::textChanged, this, &MainWindow::contentChanged);
connect(ui->contentEdit, &QPlainTextEdit::textChanged, this, &MainWindow::markdownContentChanged);
connect(ui->plainTextEdit, &QPlainTextEdit::textChanged, this, &MainWindow::plainContentChanged);
connect(ui->treeWidget, &QTreeWidget::itemSelectionChanged, this, &MainWindow::selectionChanged);
connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, &MainWindow::prepareMenu);
const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
ui->contentEdit->setFont(fixedFont);
ui->plainTextEdit->setFont(fixedFont);
ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
this->savemng = new SaveManager();
updateListView();
connect(timer, &QTimer::timeout, this, &MainWindow::save);
@@ -30,77 +38,90 @@ MainWindow::~MainWindow()
void MainWindow::createNote()
{
Note *n = new Note();
n->setTitle("untitled note");
savemng->addNote(n);
updateListView();
}
void MainWindow::selectionChanged(int i)
{
this->currentIndex = i;
if (i == -1)
if (ui->treeWidget->selectedItems().length() == 1)
{
clearAndDisableFields();
return;
}
Note *n = this->savemng->getNoteByIndex(i);
if (n == nullptr)
{
QMessageBox::critical(this, tr("TaskNote"), "Failed to get this note, the memory pointer is empty", QMessageBox::Ok, QMessageBox::Ok);
clearAndDisableFields();
return;
}
ui->contentEdit->blockSignals(true);
ui->titleEdit->blockSignals(true);
ui->titleEdit->setDisabled(false);
ui->contentEdit->setDisabled(false);
ui->actionRemove->setDisabled(false);
ui->titleEdit->setText(n->getTitle());
ui->contentEdit->setPlainText(n->getContent());
ui->markdownViewer->setMarkdown(ui->contentEdit->toPlainText());
ui->contentEdit->blockSignals(false);
ui->titleEdit->blockSignals(false);
}
void MainWindow::removeSelected()
{
if (this->currentIndex > -1)
{
this->savemng->removeNoteByIndex(this->currentIndex);
clearAndDisableFields();
CreateDialog dialog(this);
if (dialog.exec() != QDialog::Accepted) {
return;
}
QString title = dialog.getTitle();
QString uuidFolder = "";
auto item = ui->treeWidget->selectedItems()[0];
if (item->text(COLUMN_TYPE) == TYPE_NOTE)
{
uuidFolder = item->parent()->text(COLUMN_UUID);
}
else
{
uuidFolder = item->text(COLUMN_UUID);
}
Note *n = savemng->newNote(uuidFolder, title);
updateListView();
selectTreeItem(n->getUUID());
}
}
void MainWindow::createFolder()
{
CreateDialog dialog;
if (dialog.exec() != QDialog::Accepted) {
return;
}
QString title = dialog.getTitle();
Folder *f = savemng->newFolder(title);
updateListView();
selectTreeItem(f->getUUID());
}
void MainWindow::selectionChanged()
{
if (ui->treeWidget->selectedItems().length() == 1)
{
auto item = ui->treeWidget->selectedItems()[0];
ui->actionAdd->setDisabled(false);
if (item->text(COLUMN_TYPE) == TYPE_NOTE)
{
Note *n = savemng->getNoteByUUID(item->text(COLUMN_UUID));
if (n == nullptr)
{
QMessageBox::critical(this, tr("WorkPad"), "Failed to get this note, the memory pointer is empty", QMessageBox::Ok, QMessageBox::Ok);
clearAndDisableFields();
return;
}
ui->plainTextEdit->blockSignals(true);
ui->contentEdit->blockSignals(true);
this->setWindowTitle(n->getTitle() + " - WorkPad");
ui->titleLabel->setText(n->getTitle());
ui->plainTextEdit->setDisabled(false);
ui->contentEdit->setDisabled(false);
ui->plainTextEdit->setPlainText(n->getContent());
ui->contentEdit->setPlainText(n->getContent());
ui->markdownViewer->setMarkdown(ui->contentEdit->toPlainText());
ui->markdownViewer2->setMarkdown(n->getContent());
ui->plainTextEdit->blockSignals(false);
ui->contentEdit->blockSignals(false);
}
else
{
clearAndDisableFields();
}
}
else
{
clearAndDisableFields();
ui->actionAdd->setDisabled(true);
}
}
void MainWindow::save()
{
ui->actionSave->setDisabled(true);
if (this->currentIndex > -1)
{
Note *n = this->savemng->getNoteByIndex(this->currentIndex);
n->setTitle(ui->titleEdit->text());
n->setContent(ui->contentEdit->toPlainText());
}
this->savemng->flushSave();
}
void MainWindow::titleChanged()
{
timer->stop();
if (this->currentIndex > -1)
{
Note *n = this->savemng->getNoteByIndex(this->currentIndex);
n->setTitle(ui->titleEdit->text());
ui->noteList->item(this->currentIndex)->setText(ui->titleEdit->text());
}
ui->actionSave->setDisabled(false);
timer->start(1000);
}
void MainWindow::showAboutBox()
{
AboutDialog dialog;
@@ -108,42 +129,261 @@ void MainWindow::showAboutBox()
dialog.exec();
}
void MainWindow::contentChanged()
void MainWindow::prepareMenu(const QPoint &pos)
{
if (ui->treeWidget->selectedItems().length() == 1) {
QTreeWidgetItem *item = ui->treeWidget->selectedItems()[0];
QMenu menu(this);
QAction *deleteAction = new QAction(tr("Delete"), this);
connect(deleteAction, &QAction::triggered, this, &MainWindow::deleteItem);
menu.addAction(deleteAction);
QAction *renameAction = new QAction(tr("Rename"), this);
connect(renameAction, &QAction::triggered, this, &MainWindow::editName);
menu.addAction(renameAction);
if (item->text(COLUMN_TYPE) == TYPE_NOTE)
{
QAction *moveAction = new QAction(tr("Move to..."), this);
connect(moveAction, &QAction::triggered, this, &MainWindow::moveNote);
menu.addAction(moveAction);
}
menu.exec(ui->treeWidget->mapToGlobal(pos));
}
}
void MainWindow::deleteItem()
{
if (ui->treeWidget->selectedItems().length() == 1) {
QTreeWidgetItem *item = ui->treeWidget->selectedItems()[0];
QString uuid = item->text(COLUMN_UUID);
if (item->text(COLUMN_TYPE) == TYPE_NOTE)
{
QString uuidFolder = item->parent()->text(COLUMN_UUID);
Note *n = savemng->getNoteByUUID(uuid);
if (n == nullptr)
{
return;
}
if (!savemng->removeNote(uuidFolder, uuid))
{
QMessageBox::critical(this, tr("WorkPad"), "Failed to remove this note", QMessageBox::Ok, QMessageBox::Ok);
return;
}
delete n;
}
else
{
Folder *f = savemng->getFolderByUUID(uuid);
if (f == nullptr)
{
return;
}
if (!savemng->removeFolder(uuid))
{
QMessageBox::critical(this, tr("WorkPad"), "Failed to remove this folder", QMessageBox::Ok, QMessageBox::Ok);
return;
}
delete f;
}
savemng->flushSave();
updateListView();
}
}
void MainWindow::moveNote()
{
if (ui->treeWidget->selectedItems().length() == 1) {
QTreeWidgetItem *item = ui->treeWidget->selectedItems()[0];
if (item->text(COLUMN_TYPE) == TYPE_NOTE)
{
QString uuidParent = item->parent()->text(COLUMN_UUID);
MoveDialog dialog(savemng->getFolders(), this);
if (dialog.exec() != QDialog::Accepted) {
return;
}
QString uuidFolder = dialog.getSelectedUUID();
if (uuidFolder.length() == 0)
{
return;
}
// Check if parent is not the same folder
if (uuidFolder == uuidParent)
{
return;
}
QString uuid = item->text(COLUMN_UUID);
Note *n = savemng->getNoteByUUID(uuid);
if (n == nullptr)
{
return;
}
// Add to new folder
Folder *f = savemng->getFolderByUUID(uuidFolder);
if (f == nullptr)
{
QMessageBox::critical(this, tr("WorkPad"), "The folder is not found", QMessageBox::Ok, QMessageBox::Ok);
return;
}
f->append(n);
// Remove from parent folder
Folder *oldFolder = savemng->getFolderByUUID(uuidParent);
if (oldFolder == nullptr)
{
QMessageBox::critical(this, tr("WorkPad"), "The previous folder is not found, cannot delete the old version of this note", QMessageBox::Ok, QMessageBox::Ok);
return;
}
oldFolder->remove(uuid);
}
savemng->flushSave();
updateListView();
}
}
void MainWindow::editName()
{
if (ui->treeWidget->selectedItems().length() == 1) {
QTreeWidgetItem *item = ui->treeWidget->selectedItems()[0];
QString uuid = item->text(COLUMN_UUID);
RenameDialog dialog(item->text(COLUMN_NAME), this);
if (dialog.exec() != QDialog::Accepted)
{
return;
}
QString newName = dialog.getNewName();
if (item->text(COLUMN_TYPE) == TYPE_NOTE)
{
Note *n = savemng->getNoteByUUID(uuid);
if (n == nullptr)
{
QMessageBox::critical(this, tr("WorkPad"), "The note is not found", QMessageBox::Ok, QMessageBox::Ok);
return;
}
n->setTitle(newName);
}
else
{
Folder *f = savemng->getFolderByUUID(uuid);
if (f == nullptr)
{
QMessageBox::critical(this, tr("WorkPad"), "The folder is not found", QMessageBox::Ok, QMessageBox::Ok);
return;
}
f->setName(newName);
}
savemng->flushSave();
updateListView();
selectTreeItem(uuid);
}
}
void MainWindow::markdownContentChanged()
{
timer->stop();
if (this->currentIndex > -1)
ui->plainTextEdit->blockSignals(true);
ui->contentEdit->blockSignals(true);
if (ui->treeWidget->selectedItems().length() == 1)
{
Note *n = this->savemng->getNoteByIndex(this->currentIndex);
n->setContent(ui->contentEdit->toPlainText());
ui->markdownViewer->setMarkdown(ui->contentEdit->toPlainText());
QString uuid = ui->treeWidget->selectedItems()[0]->text(COLUMN_UUID);
Note *n = savemng->getNoteByUUID(uuid);
if (n != nullptr) {
QString content = ui->contentEdit->toPlainText();
ui->markdownViewer->setMarkdown(content);
ui->markdownViewer2->setMarkdown(content);
ui->plainTextEdit->setPlainText(content);
n->setContent(content);
}
}
ui->plainTextEdit->blockSignals(false);
ui->contentEdit->blockSignals(false);
ui->actionSave->setDisabled(false);
timer->start(1000);
}
void MainWindow::plainContentChanged()
{
timer->stop();
ui->plainTextEdit->blockSignals(true);
ui->contentEdit->blockSignals(true);
if (ui->treeWidget->selectedItems().length() == 1)
{
QString uuid = ui->treeWidget->selectedItems()[0]->text(COLUMN_UUID);
Note *n = savemng->getNoteByUUID(uuid);
if (n != nullptr) {
QString content = ui->plainTextEdit->toPlainText();
ui->markdownViewer->setMarkdown(content);
ui->markdownViewer2->setMarkdown(content);
ui->contentEdit->setPlainText(content);
n->setContent(content);
}
}
ui->plainTextEdit->blockSignals(false);
ui->contentEdit->blockSignals(false);
ui->actionSave->setDisabled(false);
timer->start(1000);
}
void MainWindow::updateListView()
{
ui->noteList->clear();
foreach (Note *n, savemng->getNotes())
ui->treeWidget->clear();
foreach (Folder *f, savemng->getFolders())
{
ui->noteList->addItem(n->getTitle());
QTreeWidgetItem *topLevel = new QTreeWidgetItem();
topLevel->setText(COLUMN_NAME, f->getName());
topLevel->setText(COLUMN_UUID, f->getUUID());
topLevel->setText(COLUMN_TYPE, TYPE_FOLDER);
foreach (Note *n, f->getNotes())
{
QTreeWidgetItem *children = new QTreeWidgetItem();
children->setText(COLUMN_NAME, n->getTitle());
children->setText(COLUMN_UUID, n->getUUID());
children->setText(COLUMN_TYPE, TYPE_NOTE);
topLevel->addChild(children);
}
ui->treeWidget->addTopLevelItem(topLevel);
}
}
void MainWindow::clearAndDisableFields()
{
ui->contentEdit->blockSignals(true);
ui->titleEdit->blockSignals(true);
ui->plainTextEdit->blockSignals(true);
this->currentIndex = -1;
ui->actionRemove->setDisabled(true);
ui->titleEdit->setDisabled(true);
ui->contentEdit->setDisabled(true);
ui->titleEdit->clear();
ui->plainTextEdit->setDisabled(true);
ui->plainTextEdit->clear();
ui->contentEdit->clear();
ui->markdownViewer->clear();
ui->markdownViewer2->clear();
ui->titleLabel->setText("");
this->setWindowTitle("WorkPad");
ui->contentEdit->blockSignals(false);
ui->titleEdit->blockSignals(false);
ui->plainTextEdit->blockSignals(false);
}
void MainWindow::selectTreeItem(QString uuid)
{
ui->treeWidget->clearSelection();
int c = ui->treeWidget->topLevelItemCount();
int cc = 0;
for (int i = 0; i < c; i++)
{
QTreeWidgetItem *topLevel = ui->treeWidget->topLevelItem(i);
if (topLevel->text(COLUMN_UUID) == uuid)
{
topLevel->setSelected(true);
}
cc = topLevel->childCount();
for (int y = 0; y < cc; y++)
{
QTreeWidgetItem *child = topLevel->child(y);
if (child->text(COLUMN_UUID) == uuid)
{
child->setSelected(true);
topLevel->setExpanded(true);
}
}
}
}

View File

@@ -5,10 +5,18 @@
#include <QMainWindow>
#include <QMessageBox>
#include <QTimer>
#include <QTreeWidgetItem>
#include <QMenu>
#include <QPoint>
#include "../services/savemanager.h"
#include "aboutdialog.h"
#define COLUMN_NAME 0
#define COLUMN_UUID 1
#define COLUMN_TYPE 2
#define TYPE_FOLDER "1"
#define TYPE_NOTE "2"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@@ -24,21 +32,24 @@ public:
private slots:
void createNote();
void selectionChanged(int);
void removeSelected();
void createFolder();
void selectionChanged();
void save();
void contentChanged();
void titleChanged();
void markdownContentChanged();
void plainContentChanged();
void showAboutBox();
void prepareMenu(const QPoint &pos);
void deleteItem();
void moveNote();
void editName();
private:
Ui::MainWindow *ui;
SaveManager *savemng;
QTimer *timer;
int currentIndex = -1;
void updateListView();
void clearAndDisableFields();
void selectTreeItem(QString uuid);
};
#endif // MAINWINDOW_H

View File

@@ -17,20 +17,34 @@
</size>
</property>
<property name="windowTitle">
<string>TaskNote</string>
<string>WorkPad</string>
</property>
<property name="unifiedTitleAndToolBarOnMac">
<bool>true</bool>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="noteList">
<widget class="QTreeWidget" name="treeWidget">
<property name="maximumSize">
<size>
<width>250</width>
<height>16777215</height>
</size>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="animated">
<bool>true</bool>
</property>
<column>
<property name="text">
<string notr="true">Workspace</string>
</property>
</column>
</widget>
</item>
<item>
@@ -43,83 +57,118 @@
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>13</height>
</size>
<widget class="QTabWidget" name="tabWidget">
<property name="tabPosition">
<enum>QTabWidget::South</enum>
</property>
<property name="text">
<string>Title</string>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="titleEdit">
<property name="enabled">
<bool>false</bool>
<property name="currentIndex">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QPlainTextEdit" name="contentEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<kerning>false</kerning>
</font>
</property>
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Plain text</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="titleLabel">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QTextEdit" name="markdownViewer">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="autoFormatting">
<set>QTextEdit::AutoAll</set>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByMouse</set>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Mardown editor</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPlainTextEdit" name="contentEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<kerning>false</kerning>
</font>
</property>
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="markdownViewer">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="autoFormatting">
<set>QTextEdit::AutoAll</set>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Markdown viewer</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QTextEdit" name="markdownViewer2">
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
@@ -160,32 +209,29 @@
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionAdd_folder"/>
<addaction name="actionAdd"/>
<addaction name="actionRemove"/>
<addaction name="separator"/>
<addaction name="actionSave"/>
<addaction name="separator"/>
<addaction name="actionAbout"/>
</widget>
<action name="actionAdd">
<property name="icon">
<iconset resource="../../icons.qrc">
<normaloff>:/icon/resources/outline_add_circle_outline_black_48dp.png</normaloff>:/icon/resources/outline_add_circle_outline_black_48dp.png</iconset>
</property>
<property name="text">
<string>Add</string>
</property>
</action>
<action name="actionRemove">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../../icons.qrc">
<normaloff>:/icon/resources/outline_delete_forever_black_48dp.png</normaloff>:/icon/resources/outline_delete_forever_black_48dp.png</iconset>
<normaloff>:/icon/resources/new_file.png</normaloff>:/icon/resources/new_file.png</iconset>
</property>
<property name="text">
<string>Remove</string>
<string>New note</string>
</property>
<property name="toolTip">
<string>Create a new note</string>
</property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action>
<action name="actionSave">
@@ -199,6 +245,9 @@
<property name="text">
<string>Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="actionAbout">
<property name="icon">
@@ -209,6 +258,21 @@
<string>About</string>
</property>
</action>
<action name="actionAdd_folder">
<property name="icon">
<iconset resource="../../icons.qrc">
<normaloff>:/icon/resources/new_folder.png</normaloff>:/icon/resources/new_folder.png</iconset>
</property>
<property name="text">
<string>New folder</string>
</property>
<property name="toolTip">
<string>Create a new folder</string>
</property>
<property name="shortcut">
<string>Ctrl+F, Ctrl+N</string>
</property>
</action>
</widget>
<resources>
<include location="../../icons.qrc"/>

37
src/frames/movedialog.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include "movedialog.h"
#include "ui_movedialog.h"
MoveDialog::MoveDialog(QVector<Folder*> folders, QWidget *parent) :
QDialog(parent),
ui(new Ui::MoveDialog)
{
ui->setupUi(this);
if (folders.length() > 0)
{
this->folders = folders;
foreach (Folder *f, this->folders)
{
ui->comboBox->addItem(f->getName());
}
ui->comboBox->setCurrentIndex(0);
}
else
{
ui->comboBox->setDisabled(true);
}
}
MoveDialog::~MoveDialog()
{
delete ui;
}
QString MoveDialog::getSelectedUUID()
{
int i = ui->comboBox->currentIndex();
if (i == -1)
{
return "";
}
return folders[i]->getUUID();
}

28
src/frames/movedialog.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef MOVEDIALOG_H
#define MOVEDIALOG_H
#include <QDialog>
#include "../models/folder.h"
namespace Ui {
class MoveDialog;
}
class MoveDialog : public QDialog
{
Q_OBJECT
public:
explicit MoveDialog(QVector<Folder*> folders, QWidget *parent = nullptr);
~MoveDialog();
QString getSelectedUUID();
private:
Ui::MoveDialog *ui;
QVector<Folder*> folders;
};
#endif // MOVEDIALOG_H

108
src/frames/movedialog.ui Normal file
View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MoveDialog</class>
<widget class="QDialog" name="MoveDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>142</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>142</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>142</height>
</size>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>20</x>
<y>100</y>
<width>361</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>141</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>24</pointsize>
</font>
</property>
<property name="text">
<string>Move to</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>361</width>
<height>25</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>MoveDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>MoveDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,20 @@
#include "renamedialog.h"
#include "ui_renamedialog.h"
RenameDialog::RenameDialog(QString oldName, QWidget *parent) :
QDialog(parent),
ui(new Ui::RenameDialog)
{
ui->setupUi(this);
ui->lineEdit->setText(oldName);
}
RenameDialog::~RenameDialog()
{
delete ui;
}
QString RenameDialog::getNewName()
{
return ui->lineEdit->text();
}

24
src/frames/renamedialog.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef RENAMEDIALOG_H
#define RENAMEDIALOG_H
#include <QDialog>
namespace Ui {
class RenameDialog;
}
class RenameDialog : public QDialog
{
Q_OBJECT
public:
explicit RenameDialog(QString oldName, QWidget *parent = nullptr);
~RenameDialog();
QString getNewName();
private:
Ui::RenameDialog *ui;
};
#endif // RENAMEDIALOG_H

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RenameDialog</class>
<widget class="QDialog" name="RenameDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>145</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>20</x>
<y>100</y>
<width>361</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>141</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>24</pointsize>
</font>
</property>
<property name="text">
<string>Rename</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>381</width>
<height>25</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>RenameDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>RenameDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -6,6 +6,7 @@ int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowState(Qt::WindowState::WindowMaximized);
w.show();
return a.exec();
}

83
src/models/folder.cpp Normal file
View File

@@ -0,0 +1,83 @@
#include "folder.h"
Folder::Folder(QString name)
{
QUuid uid = QUuid::createUuid();
this->uuid = uid.toString(QUuid::StringFormat::WithoutBraces);
this->name = name;
}
Folder::Folder(QJsonObject obj)
{
QUuid uid = QUuid::createUuid();
QString newUuid = uid.toString(QUuid::StringFormat::WithoutBraces);
this->uuid = obj["uuid"].toString(newUuid);
this->name = obj["name"].toString("<unamed folder>");
foreach (QJsonValue value, obj["notes"].toArray()) {
this->notes.append(new Note(value.toObject()));
}
}
Folder::~Folder()
{
foreach (Note *n, notes)
{
delete n;
}
}
QString Folder::getName()
{
return name;
}
void Folder::setName(QString name)
{
this->name = name;
}
QString Folder::getUUID()
{
return uuid;
}
QVector<Note *> Folder::getNotes()
{
return notes;
}
void Folder::append(Note *n)
{
notes.append(n);
}
int Folder::remove(QString uuid)
{
int res = 0;
int idx = -1;
for (int i = 0; i < notes.length(); i++)
{
if (notes[i]->getUUID() == uuid)
{
idx = i;
res = 1;
}
}
notes.removeAt(idx);
return res;
}
QJsonObject Folder::toJson()
{
QJsonObject folder;
QJsonArray arr;
foreach (Note *n, notes) {
arr.append(n->toJson());
}
folder["name"] = this->name;
folder["uuid"] = this->uuid;
folder["notes"] = arr;
return folder;
}

33
src/models/folder.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef FOLDER_H
#define FOLDER_H
#include <QString>
#include <QJsonObject>
#include <QJsonArray>
#include "note.h"
class Folder
{
private:
QString uuid;
QString name;
QVector<Note*> notes;
public:
Folder(QString name);
Folder(QJsonObject obj);
~Folder();
QString getName();
void setName(QString name);
QString getUUID();
QVector<Note*> getNotes();
void append(Note *n);
int remove(QString uuid);
QJsonObject toJson();
};
#endif // FOLDER_H

View File

@@ -1,9 +1,20 @@
#include "note.h"
Note::Note()
Note::Note(QString name)
{
QUuid uid = QUuid::createUuid();
this->uuid = uid.toString(QUuid::StringFormat::WithoutBraces);
this->title = name;
}
Note::Note(QJsonObject obj)
{
QUuid uid = QUuid::createUuid();
QString newUuid = uid.toString(QUuid::StringFormat::WithoutBraces);
this->uuid = obj["uuid"].toString(newUuid);
this->title = obj["title"].toString("<untitled note>");
this->content = obj["content"].toString();
}
QJsonObject Note::toJson()
@@ -14,18 +25,7 @@ QJsonObject Note::toJson()
o["content"] = this->content;
return o;
}
Note *Note::fromJson(QJsonObject o)
{
Note *n = new Note();
n->uuid = o["uuid"].toString(n->uuid);
n->title = o["title"].toString();
n->content = o["content"].toString();
n->encrypted = o["encrypted"].toBool(false);
return n;
}
QString Note::getUuid()
QString Note::getUUID()
{
return uuid;
}
@@ -37,11 +37,7 @@ QString Note::getTitle()
QString Note::getContent()
{
if (!this->encrypted)
{
return content;
}
return "";
return content;
}
void Note::setTitle(QString value)
{
@@ -50,7 +46,5 @@ void Note::setTitle(QString value)
void Note::setContent(QString value)
{
if (!this->encrypted) {
this->content = value;
}
}

View File

@@ -14,12 +14,13 @@
class Note
{
public:
Note();
Note(QString name);
Note(QJsonObject obj);
QJsonObject toJson();
static Note* fromJson(QJsonObject o);
QString getUuid();
QString getUUID();
QString getTitle();
QString getContent();
@@ -29,7 +30,6 @@ private:
QString uuid;
QString title;
QString content;
bool encrypted;
};
#endif // NOTE_H

View File

@@ -3,29 +3,33 @@
SaveManager::SaveManager()
{
openSave();
if (oldSaveVersionExist())
{
migrate();
}
}
SaveManager::~SaveManager()
{
flushSave();
foreach (Note *n, notes)
foreach (Folder *f, folders)
{
delete n;
delete f;
}
}
void SaveManager::flushSave()
{
QJsonArray json_notes;
QJsonArray json_folders;
foreach (Note *n, notes)
foreach (Folder *f, folders)
{
json_notes.append(n->toJson());
json_folders.append(f->toJson());
}
QJsonObject obj
{
{"notes", json_notes},
{"folders", json_folders},
};
QJsonDocument doc(obj);
@@ -38,37 +42,152 @@ void SaveManager::flushSave()
delete f;
}
QVector<Note *> SaveManager::getNotes()
QVector<Folder *> SaveManager::getFolders()
{
return notes;
return folders;
}
void SaveManager::addNote(Note *n)
Note *SaveManager::newNote(QString uuidFolder, QString name)
{
this->notes.append(n);
flushSave();
}
bool SaveManager::removeNoteByIndex(int i)
{
if ((i < 0) || (i >= this->notes.length()))
{
return false;
}
Note *n = this->notes[i];
this->notes.removeAt(i);
delete n;
flushSave();
return true;
}
Note *SaveManager::getNoteByIndex(int i)
{
if ((i < 0) || (i >= this->notes.length()))
Folder *f = getFolderByUUID(uuidFolder);
if (f == nullptr)
{
return nullptr;
}
return this->notes[i];
if (name.length() == 0)
{
name = "<untitle note>";
}
Note *n = new Note(name);
f->append(n);
flushSave();
return n;
}
Folder *SaveManager::newFolder(QString name)
{
if (name.length() == 0)
{
name = "<untitle folder>";
}
Folder *f = new Folder(name);
folders.append(f);
flushSave();
return f;
}
Folder *SaveManager::getFolderByUUID(QString uuid)
{
Folder *folder = nullptr;
foreach (Folder *f, folders)
{
if (f->getUUID() == uuid)
{
folder = f;
}
}
return folder;
}
Note *SaveManager::getNoteByUUID(QString uuid)
{
Note *note = nullptr;
foreach (Folder *f, folders)
{
foreach (Note *n, f->getNotes())
{
if (n->getUUID() == uuid)
{
note = n;
}
}
}
return note;
}
int SaveManager::addNoteToFolder(QString uuidFolder, Note *n)
{
Folder *f = getFolderByUUID(uuidFolder);
if (f == nullptr)
{
return 0;
}
f->append(n);
return 1;
}
int SaveManager::removeFolder(QString uuid)
{
int res = 0;
int idx = -1;
for (int i = 0; i < folders.length(); i++)
{
if (folders[i]->getUUID() == uuid)
{
idx = i;
res = 1;
}
}
folders.removeAt(idx);
return res;
}
int SaveManager::removeNote(QString uuidFolder, QString uuid)
{
Folder *f = getFolderByUUID(uuidFolder);
if (f == nullptr)
{
return 0;
}
return f->remove(uuid);
}
bool SaveManager::oldSaveVersionExist()
{
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
path.replace("WorkPad", "TaskNote");
if (!QDir(path).exists())
{
return false;
}
path += "/data/";
if (!QDir(path).exists())
{
return false;
}
path += OLD_FILENAME;
return QFile::exists(QDir::cleanPath(path));
}
void SaveManager::migrate()
{
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
path.replace("WorkPad", "TaskNote");
if (!QDir(path).exists())
{
return;
}
path += "/data/";
if (!QDir(path).exists())
{
return;
}
path = QDir::cleanPath(path + OLD_FILENAME);
QFile* file = new QFile(path);
file->open(QIODevice::ReadOnly);
auto json = QString(file->readAll());
file->close();
delete file;
QJsonObject obj = QJsonDocument::fromJson(json.toUtf8()).object();
Folder *f = newFolder("Backup from older version");
QJsonArray arr = obj["notes"].toArray();
for (int i = 0; i < arr.size(); i++)
{
f->append(new Note(arr[i].toObject()));
}
flushSave();
QFile::remove(path);
}
QString SaveManager::getSaveFilePath() {
@@ -95,9 +214,9 @@ void SaveManager::openSave() {
delete file;
QJsonObject obj = QJsonDocument::fromJson(json.toUtf8()).object();
QJsonArray arr = obj["notes"].toArray();
QJsonArray arr = obj["folders"].toArray();
for (int i = 0; i < arr.size(); i++)
{
this->notes.append(Note::fromJson(arr[i].toObject()));
this->folders.append(new Folder(arr[i].toObject()));
}
}

View File

@@ -1,7 +1,8 @@
#ifndef SAVEMANAGER_H
#define SAVEMANAGER_H
#define SAVE_FILENAME "data.json"
#define SAVE_FILENAME "workspace.json"
#define OLD_FILENAME "data.json"
#include <QStandardPaths>
#include <QDir>
@@ -11,6 +12,7 @@
#include <QVector>
#include "../models/note.h"
#include "../models/folder.h"
class SaveManager
{
@@ -20,16 +22,23 @@ public:
void flushSave();
QVector<Note*> getNotes();
QVector<Folder*> getFolders();
Note *newNote(QString uuidFolder, QString name);
Folder *newFolder(QString name);
Folder *getFolderByUUID(QString uuid);
Note *getNoteByUUID(QString uuid);
int addNoteToFolder(QString uuidFolder, Note *n);
int removeFolder(QString uuid);
int removeNote(QString uuidFolder, QString uuid);
void addNote(Note *n);
bool removeNoteByIndex(int i);
Note *getNoteByIndex(int i);
private:
QString getSaveFilePath();
void openSave();
bool oldSaveVersionExist();
void migrate();
QVector<Note*> notes;
QVector<Folder*> folders;
};
#endif // SAVEMANAGER_H