From 4d9946bfe180436fa60f908e791b7ccce0a0c9b4 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sun, 16 Oct 2016 22:48:21 +0800 Subject: [PATCH] support creating new notebook Thanks to [benjsperry](https://github.com/driftyco/ionicons) for the icons. Signed-off-by: Le Tan --- VNote.pro | 14 +-- vnewdirdialog.cpp => dialog/vnewdirdialog.cpp | 0 vnewdirdialog.h => dialog/vnewdirdialog.h | 0 .../vnewfiledialog.cpp | 0 vnewfiledialog.h => dialog/vnewfiledialog.h | 0 dialog/vnewnotebookdialog.cpp | 86 ++++++++++++++++++ dialog/vnewnotebookdialog.h | 41 +++++++++ resources/icons/create_notebook.png | Bin 0 -> 223 bytes resources/icons/delete_notebook.png | Bin 0 -> 160 bytes resources/icons/notebook_info.png | Bin 0 -> 2236 bytes vdirectorytree.cpp | 2 +- vfilelist.cpp | 2 +- vmainwindow.cpp | 83 +++++++++++++++-- vmainwindow.h | 13 ++- vnote.cpp | 27 +++++- vnote.h | 9 +- vnote.qrc | 3 + 17 files changed, 257 insertions(+), 23 deletions(-) rename vnewdirdialog.cpp => dialog/vnewdirdialog.cpp (100%) rename vnewdirdialog.h => dialog/vnewdirdialog.h (100%) rename vnewfiledialog.cpp => dialog/vnewfiledialog.cpp (100%) rename vnewfiledialog.h => dialog/vnewfiledialog.h (100%) create mode 100644 dialog/vnewnotebookdialog.cpp create mode 100644 dialog/vnewnotebookdialog.h create mode 100755 resources/icons/create_notebook.png create mode 100755 resources/icons/delete_notebook.png create mode 100755 resources/icons/notebook_info.png diff --git a/VNote.pro b/VNote.pro index 36cae7fa..8c1fe8af 100644 --- a/VNote.pro +++ b/VNote.pro @@ -17,10 +17,10 @@ SOURCES += main.cpp\ vdirectorytree.cpp \ vnote.cpp \ vnotebook.cpp \ - vnewdirdialog.cpp \ + dialog/vnewdirdialog.cpp \ vconfigmanager.cpp \ vfilelist.cpp \ - vnewfiledialog.cpp \ + dialog/vnewfiledialog.cpp \ vtabwidget.cpp \ vedit.cpp \ veditor.cpp \ @@ -31,16 +31,17 @@ SOURCES += main.cpp\ utils/peg-highlight/pmh_parser.c \ hgmarkdownhighlighter.cpp \ vstyleparser.cpp \ - utils/peg-highlight/pmh_styleparser.c + utils/peg-highlight/pmh_styleparser.c \ + dialog/vnewnotebookdialog.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ vnote.h \ vnotebook.h \ - vnewdirdialog.h \ + dialog/vnewdirdialog.h \ vconfigmanager.h \ vfilelist.h \ - vnewfiledialog.h \ + dialog/vnewfiledialog.h \ vtabwidget.h \ vedit.h \ veditor.h \ @@ -53,7 +54,8 @@ HEADERS += vmainwindow.h \ hgmarkdownhighlighter.h \ utils/peg-highlight/pmh_definitions.h \ vstyleparser.h \ - utils/peg-highlight/pmh_styleparser.h + utils/peg-highlight/pmh_styleparser.h \ + dialog/vnewnotebookdialog.h RESOURCES += \ vnote.qrc diff --git a/vnewdirdialog.cpp b/dialog/vnewdirdialog.cpp similarity index 100% rename from vnewdirdialog.cpp rename to dialog/vnewdirdialog.cpp diff --git a/vnewdirdialog.h b/dialog/vnewdirdialog.h similarity index 100% rename from vnewdirdialog.h rename to dialog/vnewdirdialog.h diff --git a/vnewfiledialog.cpp b/dialog/vnewfiledialog.cpp similarity index 100% rename from vnewfiledialog.cpp rename to dialog/vnewfiledialog.cpp diff --git a/vnewfiledialog.h b/dialog/vnewfiledialog.h similarity index 100% rename from vnewfiledialog.h rename to dialog/vnewfiledialog.h diff --git a/dialog/vnewnotebookdialog.cpp b/dialog/vnewnotebookdialog.cpp new file mode 100644 index 00000000..c7498c7d --- /dev/null +++ b/dialog/vnewnotebookdialog.cpp @@ -0,0 +1,86 @@ +#include +#include "vnewnotebookdialog.h" + +VNewNotebookDialog::VNewNotebookDialog(const QString &title, const QString &info, + const QString &defaultName, const QString &defaultPath, + QWidget *parent) + : QDialog(parent), title(title), info(info), defaultName(defaultName), defaultPath(defaultPath), + infoLabel(NULL) +{ + setupUI(); + + connect(nameEdit, &QLineEdit::textChanged, this, &VNewNotebookDialog::enableOkButton); + connect(pathEdit, &QLineEdit::textChanged, this, &VNewNotebookDialog::enableOkButton); + connect(browseBtn, &QPushButton::clicked, this, &VNewNotebookDialog::handleBrowseBtnClicked); + connect(okBtn, &QPushButton::clicked, this, &VNewNotebookDialog::accept); + connect(cancelBtn, &QPushButton::clicked, this, &VNewNotebookDialog::reject); + + enableOkButton(); +} + +void VNewNotebookDialog::setupUI() +{ + if (!info.isEmpty()) { + infoLabel = new QLabel(info); + } + nameLabel = new QLabel(tr("&Name")); + nameEdit = new QLineEdit(defaultName); + nameEdit->selectAll(); + nameLabel->setBuddy(nameEdit); + + QLabel *pathLabel = new QLabel(tr("&Path")); + pathEdit = new QLineEdit(defaultPath); + pathLabel->setBuddy(pathEdit); + browseBtn = new QPushButton(tr("&Browse")); + + QHBoxLayout *pathLayout = new QHBoxLayout(); + pathLayout->addWidget(pathEdit); + pathLayout->addWidget(browseBtn); + + okBtn = new QPushButton(tr("&OK")); + okBtn->setDefault(true); + cancelBtn = new QPushButton(tr("&Cancel")); + + QVBoxLayout *topLayout = new QVBoxLayout(); + if (infoLabel) { + topLayout->addWidget(infoLabel); + } + topLayout->addWidget(nameLabel); + topLayout->addWidget(nameEdit); + topLayout->addWidget(pathLabel); + topLayout->addLayout(pathLayout); + + QHBoxLayout *btmLayout = new QHBoxLayout(); + btmLayout->addStretch(); + btmLayout->addWidget(okBtn); + btmLayout->addWidget(cancelBtn); + + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->addLayout(topLayout); + mainLayout->addLayout(btmLayout); + setLayout(mainLayout); + + setWindowTitle(title); +} + +void VNewNotebookDialog::enableOkButton() +{ + okBtn->setEnabled(!pathEdit->text().isEmpty() && !nameEdit->text().isEmpty()); +} + +QString VNewNotebookDialog::getNameInput() const +{ + return nameEdit->text(); +} + +QString VNewNotebookDialog::getPathInput() const +{ + return pathEdit->text(); +} + +void VNewNotebookDialog::handleBrowseBtnClicked() +{ + QString dirPath = QFileDialog::getExistingDirectory(this, tr("Select a directory as the path of the notebook"), + "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + pathEdit->setText(dirPath); +} diff --git a/dialog/vnewnotebookdialog.h b/dialog/vnewnotebookdialog.h new file mode 100644 index 00000000..998c1bf9 --- /dev/null +++ b/dialog/vnewnotebookdialog.h @@ -0,0 +1,41 @@ +#ifndef VNEWNOTEBOOKDIALOG_H +#define VNEWNOTEBOOKDIALOG_H + +#include + +class QLabel; +class QLineEdit; +class QPushButton; +class QString; + +class VNewNotebookDialog : public QDialog +{ + Q_OBJECT +public: + VNewNotebookDialog(const QString &title, const QString &info, const QString &defaultName, + const QString &defaultPath, QWidget *parent = 0); + QString getNameInput() const; + QString getPathInput() const; + +private slots: + void enableOkButton(); + void handleBrowseBtnClicked(); + +private: + void setupUI(); + + QLabel *infoLabel; + QLabel *nameLabel; + QLineEdit *nameEdit; + QLineEdit *pathEdit; + QPushButton *browseBtn; + QPushButton *okBtn; + QPushButton *cancelBtn; + + QString title; + QString defaultName; + QString info; + QString defaultPath; +}; + +#endif // VNEWNOTEBOOKDIALOG_H diff --git a/resources/icons/create_notebook.png b/resources/icons/create_notebook.png new file mode 100755 index 0000000000000000000000000000000000000000..a76887a0813c78e0bf583167e34d2a319549e932 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7#Nv>)VXbLJAo8ifKP}kkOqRK={wH@DaMi@ zzhDN3XE)M-oOVwa$B>F!Z*Le1G8k~M9Q)VXbLJAo8ifKP}kkOqRK={wH@DaMi@ zzhDN3XE)M-91l+y$B>F!Z_gO=GB9v38~mBg#v9{3EzE%(qyr8VQs=WUH99B=a6qUp csL~9I>|Fo8EaN$nFVdQ&MBb@0P=Pq%m4rY literal 0 HcmV?d00001 diff --git a/resources/icons/notebook_info.png b/resources/icons/notebook_info.png new file mode 100755 index 0000000000000000000000000000000000000000..8e03190ac92c3c2da03cc24d9977fd61d2ded665 GIT binary patch literal 2236 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+Cx9H50G|+7Aa@ju@DR8cw`Dgl z2v(N_`2{mDGPAI9a`W&D2nmadNlHn}$SW!-tEg*gY3u0f=^Gdso0ytgSXx=z*gH77 zdwO~M`1<(=1O^3%L_|hK$0jDFq^6~3=H%w(7Zw$lR#aBk)YjEEw6wOhcXamjO_(@o z%8Z$_X3v>BZ^5D^%U7&iwR+9kb?Y~5+_Yuuw(UE2?>lt($kF2`PM$t<_QJ(Wm#<#C ze&g1iyZ0VGe)9DBiEaktaqI2fkJVF? zWsZOJNmLRHVF{UZA!Ff69Uo8Wu5CwJS~z(_RHizuT%p1udE~GEtMKXC+luF{f4y)1 z=c>P)^WXn&FD|n^e{)A6u9Wb<`{Q-}xXqcj@9F!^DNJ}i?V$TJe?za;8T-=<;(sll z9Q`{@digiCuWvlkzrXeV>>H9kH-G8>PnRzTzYPhtZNI#N=lteS-nAC<+;VTnR9`)_ z$T`!eZQYj0-k7gtQk(5IUp@Be@=C_td0S$1V}7J%T_}2d^}wCQD--o+udnb9HZF@z zJGklVvS%`%9T#L|2XA)!9Lm#g`og2BRb){DItu>MJ zGM8&{EAY-}BWasNOQGF|~ z-nZYIe65Iwm1Tm}o2afx!SDXoywP3PotZqib)wrO4Zr)#&)UW#-NfW!oEzQ5x!;ZT z!=6I#4LYy>y*&T%n(l$V4Gfo(UO&q(y7Tw4*ym^O8xJtlSzq6GQ<{%Q;cnvnH-9B0 z4^;hr_O9*3@8$ixb9T2oF@JD1sMc>|o3KZD!tT2p8FjW6JlogLn{ePzWp@AG`dc}V z_W1JiJx~^Yo*P%d5I@Tzznq=D;L?%GXdxK~qr!W;STEd~#<^hYUHyh@*HnR6u;%}I z-#OcF9%OuDUU+XA3;T!0&d=AxWDd9qr@za{Vc08n?#{Iv3|6{xb~fH%_>-3M?j7&m z|K)7w?moG|@W;>RAD^$?<9rAl5uic94;6Ctwy1wI`;)U%! z(Jkj|*fVl%9l!to%XC|8;oIjk80MMgD$4b9KHxenmgICodXY3wbdNjpyZT>2yQe+= z{E9gu_i9r~Sl$0-H{Da(q3i|AeY=f5w)i)!U3=^Mk?-@9FJ21yRq#NkdfM~7uio9y zJ*|J!TV$kruxjfd2{clji#%s<>QKOUwwWXRLfuk z#}rsMZ(tB$U~*vKU|>{WU}-?&yb|wVWknW1k) #include "vdirectorytree.h" -#include "vnewdirdialog.h" +#include "dialog/vnewdirdialog.h" #include "vconfigmanager.h" VDirectoryTree::VDirectoryTree(QWidget *parent) diff --git a/vfilelist.cpp b/vfilelist.cpp index 7a8e8ecd..d9b02e71 100644 --- a/vfilelist.cpp +++ b/vfilelist.cpp @@ -2,7 +2,7 @@ #include #include "vfilelist.h" #include "vconfigmanager.h" -#include "vnewfiledialog.h" +#include "dialog/vnewfiledialog.h" VFileList::VFileList(QWidget *parent) : QListWidget(parent) diff --git a/vmainwindow.cpp b/vmainwindow.cpp index d2d650d5..d4db6eba 100644 --- a/vmainwindow.cpp +++ b/vmainwindow.cpp @@ -5,17 +5,21 @@ #include "vfilelist.h" #include "vtabwidget.h" #include "vconfigmanager.h" +#include "dialog/vnewnotebookdialog.h" extern VConfigManager vconfig; VMainWindow::VMainWindow(QWidget *parent) : QMainWindow(parent) { + // Must be called before those who uses VConfigManager vnote = new VNote(); setupUI(); initActions(); initToolBar(); - updateNotebookComboBox(); + initMenuBar(); + + updateNotebookComboBox(vnote->getNotebooks()); } VMainWindow::~VMainWindow() @@ -28,12 +32,24 @@ void VMainWindow::setupUI() // Notebook directory browser tree notebookLabel = new QLabel(tr("Notebook")); directoryLabel = new QLabel(tr("Directory")); + newNotebookBtn = new QPushButton(QIcon(":/resources/icons/create_notebook.png"), ""); + newNotebookBtn->setToolTip(tr("Create a new notebook")); + deleteNotebookBtn = new QPushButton(QIcon(":/resources/icons/delete_notebook.png"), ""); + deleteNotebookBtn->setToolTip(tr("Delete current notebook")); + notebookInfoBtn = new QPushButton(QIcon(":/resources/icons/notebook_info.png"), ""); + notebookInfoBtn->setToolTip(tr("View and edit current notebook's information")); notebookComboBox = new QComboBox(); notebookComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); directoryTree = new VDirectoryTree(); + QHBoxLayout *nbBtnLayout = new QHBoxLayout; + nbBtnLayout->addWidget(notebookLabel); + nbBtnLayout->addStretch(); + nbBtnLayout->addWidget(newNotebookBtn); + nbBtnLayout->addWidget(deleteNotebookBtn); + nbBtnLayout->addWidget(notebookInfoBtn); QVBoxLayout *nbLayout = new QVBoxLayout; - nbLayout->addWidget(notebookLabel); + nbLayout->addLayout(nbBtnLayout); nbLayout->addWidget(notebookComboBox); nbLayout->addWidget(directoryLabel); nbLayout->addWidget(directoryTree); @@ -68,6 +84,10 @@ void VMainWindow::setupUI() fileList, &VFileList::setDirectory); connect(fileList, &VFileList::fileClicked, tabs, &VTabWidget::openFile); + connect(newNotebookBtn, &QPushButton::clicked, + this, &VMainWindow::onNewNotebookBtnClicked); + connect(vnote, &VNote::notebooksChanged, + this, &VMainWindow::updateNotebookComboBox); setCentralWidget(mainSplitter); // Create and show the status bar @@ -94,17 +114,27 @@ void VMainWindow::initActions() void VMainWindow::initToolBar() { - fileToolBar = addToolBar(tr("Note")); + QToolBar *fileToolBar = addToolBar(tr("Note")); fileToolBar->setMovable(false); fileToolBar->addAction(editNoteAct); fileToolBar->addAction(readNoteAct); fileToolBar->addAction(saveNoteAct); } -void VMainWindow::updateNotebookComboBox() +void VMainWindow::initMenuBar() { - const QVector ¬ebooks = vnote->getNotebooks(); + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + // To be implemented +} + +void VMainWindow::updateNotebookComboBox(const QVector ¬ebooks) +{ + // Clearing and inserting items will emit the signal which corrupt the vconfig's + // current index. We save it first and then set the combobox index to the + // right one to resrote it. + int curIndex = vconfig.getCurNotebookIndex(); notebookComboBox->clear(); if (notebooks.isEmpty()) { return; @@ -114,20 +144,53 @@ void VMainWindow::updateNotebookComboBox() } qDebug() << "update notebook combobox with" << notebookComboBox->count() - << "items"; - notebookComboBox->setCurrentIndex(vconfig.getCurNotebookIndex()); + << "items, current notebook" << curIndex; + notebookComboBox->setCurrentIndex(curIndex); } void VMainWindow::setCurNotebookIndex(int index) { Q_ASSERT(index < vnote->getNotebooks().size()); - qDebug() << "set current notebook index:" << index; - vconfig.setCurNotebookIndex(index); - // Update directoryTree QString treePath; if (index > -1) { + vconfig.setCurNotebookIndex(index); treePath = vnote->getNotebooks()[index].getPath(); } emit curNotebookIndexChanged(treePath); } + +void VMainWindow::onNewNotebookBtnClicked() +{ + qDebug() << "request to create a notebook"; + QString info; + QString defaultName("new_notebook"); + QString defaultPath; + do { + VNewNotebookDialog dialog(tr("Create a new notebook"), info, defaultName, + defaultPath, this); + if (dialog.exec() == QDialog::Accepted) { + QString name = dialog.getNameInput(); + QString path = dialog.getPathInput(); + if (isConflictWithExistingNotebooks(name, path)) { + info = "Name already exists or the path already has a notebook."; + defaultName = name; + defaultPath = path; + continue; + } + vnote->createNotebook(name, path); + } + break; + } while (true); +} + +bool VMainWindow::isConflictWithExistingNotebooks(const QString &name, const QString &path) +{ + const QVector ¬ebooks = vnote->getNotebooks(); + for (int i = 0; i < notebooks.size(); ++i) { + if (notebooks[i].getName() == name || notebooks[i].getPath() == path) { + return true; + } + } + return false; +} diff --git a/vmainwindow.h b/vmainwindow.h index 3145b83d..5fe44cd2 100644 --- a/vmainwindow.h +++ b/vmainwindow.h @@ -14,6 +14,8 @@ class VNote; class VFileList; class VTabWidget; class QAction; +class QPushButton; +class VNotebook; class VMainWindow : public QMainWindow { @@ -26,26 +28,31 @@ public: private slots: // Change current notebook index and update the directory tree void setCurNotebookIndex(int index); + // Create a notebook + void onNewNotebookBtnClicked(); + void updateNotebookComboBox(const QVector ¬ebooks); signals: void curNotebookIndexChanged(const QString &path); private: void setupUI(); - // Update notebookComboBox according to vnote - void updateNotebookComboBox(); void initActions(); void initToolBar(); + void initMenuBar(); + bool isConflictWithExistingNotebooks(const QString &name, const QString &path); QLabel *notebookLabel; QLabel *directoryLabel; QComboBox *notebookComboBox; + QPushButton *newNotebookBtn; + QPushButton *deleteNotebookBtn; + QPushButton *notebookInfoBtn; VDirectoryTree *directoryTree; VFileList *fileList; VTabWidget *tabs; QSplitter *mainSplitter; VNote *vnote; - QToolBar *fileToolBar; // Actions QAction *editNoteAct; diff --git a/vnote.cpp b/vnote.cpp index 96b533fb..b9b187f7 100644 --- a/vnote.cpp +++ b/vnote.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include "vnote.h" #include "utils/vutils.h" #include "vconfigmanager.h" @@ -8,11 +10,12 @@ VConfigManager vconfig; QString VNote::templateHtml; -VNote::VNote() +VNote::VNote() : QObject() { vconfig.initialize(); decorateTemplate(); notebooks = vconfig.getNotebooks(); + emit notebooksChanged(notebooks); } void VNote::decorateTemplate() @@ -25,3 +28,25 @@ const QVector& VNote::getNotebooks() { return notebooks; } + +void VNote::createNotebook(const QString &name, const QString &path) +{ + // Create a directory config file in @path + QJsonObject configJson; + configJson["version"] = "1"; + configJson["name"] = name; + configJson["sub_directories"] = QJsonArray(); + configJson["files"] = QJsonArray(); + if (!vconfig.writeDirectoryConfig(path, configJson)) { + return; + } + + // Update notebooks settings + notebooks.prepend(VNotebook(name, path)); + vconfig.setNotebooks(notebooks); + + // Set current index to the new notebook + vconfig.setCurNotebookIndex(0); + + emit notebooksChanged(notebooks); +} diff --git a/vnote.h b/vnote.h index ebb371b5..9d2b8898 100644 --- a/vnote.h +++ b/vnote.h @@ -5,10 +5,12 @@ #include #include #include +#include #include "vnotebook.h" -class VNote +class VNote : public QObject { + Q_OBJECT public: VNote(); @@ -18,6 +20,11 @@ public: static QString templateHtml; + void createNotebook(const QString &name, const QString &path); + +signals: + void notebooksChanged(const QVector ¬ebooks); + private: QVector notebooks; }; diff --git a/vnote.qrc b/vnote.qrc index 5148a7df..33c02972 100644 --- a/vnote.qrc +++ b/vnote.qrc @@ -36,5 +36,8 @@ resources/styles/solarized-light.mdhl resources/styles/solarized-dark.mdhl resources/vnote.ini + resources/icons/create_notebook.png + resources/icons/delete_notebook.png + resources/icons/notebook_info.png