support creating new notebook

Thanks to [benjsperry](https://github.com/driftyco/ionicons) for the
icons.

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-10-16 22:48:21 +08:00
parent 8d9278f491
commit 4d9946bfe1
17 changed files with 257 additions and 23 deletions

View File

@ -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

View File

@ -0,0 +1,86 @@
#include <QtWidgets>
#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);
}

View File

@ -0,0 +1,41 @@
#ifndef VNEWNOTEBOOKDIALOG_H
#define VNEWNOTEBOOKDIALOG_H
#include <QDialog>
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

BIN
resources/icons/notebook_info.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,6 +1,6 @@
#include <QtWidgets>
#include "vdirectorytree.h"
#include "vnewdirdialog.h"
#include "dialog/vnewdirdialog.h"
#include "vconfigmanager.h"
VDirectoryTree::VDirectoryTree(QWidget *parent)

View File

@ -2,7 +2,7 @@
#include <QtWidgets>
#include "vfilelist.h"
#include "vconfigmanager.h"
#include "vnewfiledialog.h"
#include "dialog/vnewfiledialog.h"
VFileList::VFileList(QWidget *parent)
: QListWidget(parent)

View File

@ -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<VNotebook> &notebooks = vnote->getNotebooks();
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
// To be implemented
}
void VMainWindow::updateNotebookComboBox(const QVector<VNotebook> &notebooks)
{
// 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<VNotebook> &notebooks = vnote->getNotebooks();
for (int i = 0; i < notebooks.size(); ++i) {
if (notebooks[i].getName() == name || notebooks[i].getPath() == path) {
return true;
}
}
return false;
}

View File

@ -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<VNotebook> &notebooks);
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;

View File

@ -1,5 +1,7 @@
#include <QSettings>
#include <QDebug>
#include <QJsonObject>
#include <QJsonArray>
#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<VNotebook>& 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);
}

View File

@ -5,10 +5,12 @@
#include <QVector>
#include <QSettings>
#include <QFont>
#include <QObject>
#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<VNotebook> &notebooks);
private:
QVector<VNotebook> notebooks;
};

View File

@ -36,5 +36,8 @@
<file>resources/styles/solarized-light.mdhl</file>
<file>resources/styles/solarized-dark.mdhl</file>
<file>resources/vnote.ini</file>
<file>resources/icons/create_notebook.png</file>
<file>resources/icons/delete_notebook.png</file>
<file>resources/icons/notebook_info.png</file>
</qresource>
</RCC>