refactor: add VNotebookSelector for notebook management

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-12-04 20:49:23 +08:00
parent fe4fb25105
commit 9a197b5087
20 changed files with 555 additions and 400 deletions

View File

@ -24,40 +24,37 @@ void VNewNotebookDialog::setupUI()
if (!info.isEmpty()) { if (!info.isEmpty()) {
infoLabel = new QLabel(info); infoLabel = new QLabel(info);
} }
nameLabel = new QLabel(tr("&Name")); nameLabel = new QLabel(tr("Notebook &name:"));
nameEdit = new QLineEdit(defaultName); nameEdit = new QLineEdit(defaultName);
nameEdit->selectAll(); nameEdit->selectAll();
nameLabel->setBuddy(nameEdit); nameLabel->setBuddy(nameEdit);
QHBoxLayout *nameLayout = new QHBoxLayout();
nameLayout->addWidget(nameLabel);
nameLayout->addWidget(nameEdit);
QLabel *pathLabel = new QLabel(tr("&Path")); QLabel *pathLabel = new QLabel(tr("Notebook &path:"));
pathEdit = new QLineEdit(defaultPath); pathEdit = new QLineEdit(defaultPath);
pathLabel->setBuddy(pathEdit); pathLabel->setBuddy(pathEdit);
browseBtn = new QPushButton(tr("&Browse")); browseBtn = new QPushButton(tr("&Browse"));
QHBoxLayout *pathLayout = new QHBoxLayout(); QHBoxLayout *pathLayout = new QHBoxLayout();
pathLayout->addWidget(pathLabel);
pathLayout->addWidget(pathEdit); pathLayout->addWidget(pathEdit);
pathLayout->addWidget(browseBtn); pathLayout->addWidget(browseBtn);
okBtn = new QPushButton(tr("&OK")); okBtn = new QPushButton(tr("&OK"));
okBtn->setDefault(true); okBtn->setDefault(true);
cancelBtn = new QPushButton(tr("&Cancel")); 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(); QHBoxLayout *btmLayout = new QHBoxLayout();
btmLayout->addStretch(); btmLayout->addStretch();
btmLayout->addWidget(okBtn); btmLayout->addWidget(okBtn);
btmLayout->addWidget(cancelBtn); btmLayout->addWidget(cancelBtn);
QVBoxLayout *mainLayout = new QVBoxLayout(); QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addLayout(topLayout); if (infoLabel) {
mainLayout->addWidget(infoLabel);
}
mainLayout->addLayout(nameLayout);
mainLayout->addLayout(pathLayout);
mainLayout->addLayout(btmLayout); mainLayout->addLayout(btmLayout);
setLayout(mainLayout); setLayout(mainLayout);

View File

@ -21,36 +21,36 @@ void VNotebookInfoDialog::setupUI()
if (!info.isEmpty()) { if (!info.isEmpty()) {
infoLabel = new QLabel(info); infoLabel = new QLabel(info);
} }
nameLabel = new QLabel(tr("&Name")); nameLabel = new QLabel(tr("Notebook &name:"));
nameEdit = new QLineEdit(defaultName); nameEdit = new QLineEdit(defaultName);
nameEdit->selectAll(); nameEdit->selectAll();
nameLabel->setBuddy(nameEdit); nameLabel->setBuddy(nameEdit);
QHBoxLayout *nameLayout = new QHBoxLayout();
nameLayout->addWidget(nameLabel);
nameLayout->addWidget(nameEdit);
QLabel *pathLabel = new QLabel(tr("&Path")); QLabel *pathLabel = new QLabel(tr("Notebook &path:"));
pathEdit = new QLineEdit(defaultPath); pathEdit = new QLineEdit(defaultPath);
pathLabel->setBuddy(pathEdit); pathLabel->setBuddy(pathEdit);
pathEdit->setEnabled(false); pathEdit->setReadOnly(true);
QHBoxLayout *pathLayout = new QHBoxLayout();
pathLayout->addWidget(pathLabel);
pathLayout->addWidget(pathEdit);
okBtn = new QPushButton(tr("&OK")); okBtn = new QPushButton(tr("&OK"));
okBtn->setDefault(true); okBtn->setDefault(true);
cancelBtn = new QPushButton(tr("&Cancel")); cancelBtn = new QPushButton(tr("&Cancel"));
QVBoxLayout *topLayout = new QVBoxLayout();
if (infoLabel) {
topLayout->addWidget(infoLabel);
}
topLayout->addWidget(nameLabel);
topLayout->addWidget(nameEdit);
topLayout->addWidget(pathLabel);
topLayout->addWidget(pathEdit);
QHBoxLayout *btmLayout = new QHBoxLayout(); QHBoxLayout *btmLayout = new QHBoxLayout();
btmLayout->addStretch(); btmLayout->addStretch();
btmLayout->addWidget(okBtn); btmLayout->addWidget(okBtn);
btmLayout->addWidget(cancelBtn); btmLayout->addWidget(cancelBtn);
QVBoxLayout *mainLayout = new QVBoxLayout(); QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addLayout(topLayout); if (infoLabel) {
mainLayout->addWidget(infoLabel);
}
mainLayout->addLayout(nameLayout);
mainLayout->addLayout(pathLayout);
mainLayout->addLayout(btmLayout); mainLayout->addLayout(btmLayout);
setLayout(mainLayout); setLayout(mainLayout);

View File

@ -44,7 +44,8 @@ SOURCES += main.cpp\
vtoc.cpp \ vtoc.cpp \
vsingleinstanceguard.cpp \ vsingleinstanceguard.cpp \
vdirectory.cpp \ vdirectory.cpp \
vfile.cpp vfile.cpp \
vnotebookselector.cpp
HEADERS += vmainwindow.h \ HEADERS += vmainwindow.h \
vdirectorytree.h \ vdirectorytree.h \
@ -77,7 +78,8 @@ HEADERS += vmainwindow.h \
vtoc.h \ vtoc.h \
vsingleinstanceguard.h \ vsingleinstanceguard.h \
vdirectory.h \ vdirectory.h \
vfile.h vfile.h \
vnotebookselector.h
RESOURCES += \ RESOURCES += \
vnote.qrc vnote.qrc

View File

@ -97,7 +97,7 @@ QString VDirectory::retriveRelativePath(const VDirectory *p_dir) const
} }
} }
QJsonObject VDirectory::createDirectoryJson() const QJsonObject VDirectory::createDirectoryJson()
{ {
QJsonObject dirJson; QJsonObject dirJson;
dirJson["version"] = "1"; dirJson["version"] = "1";

View File

@ -56,12 +56,13 @@ public:
inline QString retriveRelativePath() const; inline QString retriveRelativePath() const;
inline QString getNotebook() const; inline QString getNotebook() const;
static QJsonObject createDirectoryJson();
private: private:
// Get the path of @p_dir recursively // Get the path of @p_dir recursively
QString retrivePath(const VDirectory *p_dir) const; QString retrivePath(const VDirectory *p_dir) const;
// Get teh relative path of @p_dir recursively related to the notebook path // Get teh relative path of @p_dir recursively related to the notebook path
QString retriveRelativePath(const VDirectory *p_dir) const; QString retriveRelativePath(const VDirectory *p_dir) const;
QJsonObject createDirectoryJson() const;
bool createFileInConfig(const QString &p_name, int p_index = -1); bool createFileInConfig(const QString &p_name, int p_index = -1);
bool createSubDirectoryInConfig(const QString &p_name, int p_index = -1); bool createSubDirectoryInConfig(const QString &p_name, int p_index = -1);

View File

@ -6,9 +6,10 @@
#include "vnote.h" #include "vnote.h"
#include "vdirectory.h" #include "vdirectory.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "veditarea.h"
VDirectoryTree::VDirectoryTree(VNote *vnote, QWidget *parent) VDirectoryTree::VDirectoryTree(VNote *vnote, QWidget *parent)
: QTreeWidget(parent), vnote(vnote) : QTreeWidget(parent), vnote(vnote), m_editArea(NULL)
{ {
setColumnCount(1); setColumnCount(1);
setHeaderHidden(true); setHeaderHidden(true);
@ -343,6 +344,7 @@ void VDirectoryTree::deleteDirectory()
tr("This will delete any files under this directory."), QMessageBox::Ok | QMessageBox::Cancel, tr("This will delete any files under this directory."), QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Ok, this); QMessageBox::Ok, this);
if (ret == QMessageBox::Ok) { if (ret == QMessageBox::Ok) {
m_editArea->closeFile(curDir, true);
VDirectory *parentDir = curDir->getParentDirectory(); VDirectory *parentDir = curDir->getParentDirectory();
Q_ASSERT(parentDir); Q_ASSERT(parentDir);
parentDir->deleteSubDirectory(curDir); parentDir->deleteSubDirectory(curDir);

View File

@ -9,12 +9,14 @@
#include "vnotebook.h" #include "vnotebook.h"
class VNote; class VNote;
class VEditArea;
class VDirectoryTree : public QTreeWidget class VDirectoryTree : public QTreeWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit VDirectoryTree(VNote *vnote, QWidget *parent = 0); explicit VDirectoryTree(VNote *vnote, QWidget *parent = 0);
inline void setEditArea(VEditArea *p_editArea);
signals: signals:
void currentDirectoryChanged(VDirectory *p_directory); void currentDirectoryChanged(VDirectory *p_directory);
@ -59,6 +61,7 @@ private:
VNote *vnote; VNote *vnote;
QPointer<VNotebook> m_notebook; QPointer<VNotebook> m_notebook;
QVector<QPointer<VDirectory> > m_copiedDirs; QVector<QPointer<VDirectory> > m_copiedDirs;
VEditArea *m_editArea;
// Actions // Actions
QAction *newRootDirAct; QAction *newRootDirAct;
@ -77,4 +80,9 @@ inline QPointer<VDirectory> VDirectoryTree::getVDirectory(QTreeWidgetItem *p_ite
return p_item->data(0, Qt::UserRole).value<VDirectory *>(); return p_item->data(0, Qt::UserRole).value<VDirectory *>();
} }
inline void VDirectoryTree::setEditArea(VEditArea *p_editArea)
{
m_editArea = p_editArea;
}
#endif // VDIRECTORYTREE_H #endif // VDIRECTORYTREE_H

View File

@ -7,7 +7,7 @@
#include "vfile.h" #include "vfile.h"
VEditArea::VEditArea(VNote *vnote, QWidget *parent) VEditArea::VEditArea(VNote *vnote, QWidget *parent)
: QWidget(parent), vnote(vnote), curWindowIndex(0) : QWidget(parent), vnote(vnote), curWindowIndex(-1)
{ {
setupUI(); setupUI();
} }
@ -16,9 +16,8 @@ void VEditArea::setupUI()
{ {
splitter = new QSplitter(this); splitter = new QSplitter(this);
// Add a window
insertSplitWindow(0); insertSplitWindow(0);
setCurrentWindow(0, true); setCurrentWindow(0, false);
QHBoxLayout *mainLayout = new QHBoxLayout(); QHBoxLayout *mainLayout = new QHBoxLayout();
mainLayout->addWidget(splitter); mainLayout->addWidget(splitter);
@ -43,17 +42,6 @@ void VEditArea::insertSplitWindow(int idx)
this, &VEditArea::handleOutlineChanged); this, &VEditArea::handleOutlineChanged);
connect(win, &VEditWindow::curHeaderChanged, connect(win, &VEditWindow::curHeaderChanged,
this, &VEditArea::handleCurHeaderChanged); this, &VEditArea::handleCurHeaderChanged);
int nrWin = splitter->count();
if (nrWin == 1) {
// Disable removing split
win->setRemoveSplitEnable(false);
} else {
// Enable removing split
for (int i = 0; i < nrWin; ++i) {
getWindow(i)->setRemoveSplitEnable(true);
}
}
} }
void VEditArea::removeSplitWindow(VEditWindow *win) void VEditArea::removeSplitWindow(VEditWindow *win)
@ -61,21 +49,12 @@ void VEditArea::removeSplitWindow(VEditWindow *win)
if (!win) { if (!win) {
return; return;
} }
win->hide(); win->hide();
win->setParent(this);
disconnect(win, 0, this, 0);
// Should be deleted later // Should be deleted later
win->deleteLater(); win->deleteLater();
int nrWin = splitter->count();
if (nrWin == 2) {
// Disable removing split
getWindow(0)->setRemoveSplitEnable(false);
getWindow(1)->setRemoveSplitEnable(false);
} else {
// Enable removing split
for (int i = 0; i < nrWin; ++i) {
getWindow(i)->setRemoveSplitEnable(true);
}
}
} }
// A given file can be opened in multiple split windows. A given file could be // A given file can be opened in multiple split windows. A given file could be
@ -107,6 +86,11 @@ void VEditArea::openFile(VFile *p_file, OpenFileMode p_mode)
} }
// Open it in current window // Open it in current window
if (curWindowIndex == -1) {
// insert a new split
insertSplitWindow(0);
curWindowIndex = 0;
}
winIdx = curWindowIndex; winIdx = curWindowIndex;
tabIdx = openFileInWindow(winIdx, p_file, p_mode); tabIdx = openFileInWindow(winIdx, p_file, p_mode);
@ -151,9 +135,8 @@ void VEditArea::setCurrentWindow(int windowIndex, bool setFocus)
if (curWindowIndex == windowIndex) { if (curWindowIndex == windowIndex) {
goto out; goto out;
} }
qDebug() << "current window" << windowIndex;
curWindowIndex = windowIndex; curWindowIndex = windowIndex;
if (setFocus) { if (curWindowIndex > -1 && setFocus) {
getWindow(windowIndex)->focusWindow(); getWindow(windowIndex)->focusWindow();
} }
@ -164,6 +147,13 @@ out:
void VEditArea::updateWindowStatus() void VEditArea::updateWindowStatus()
{ {
if (curWindowIndex == -1) {
Q_ASSERT(splitter->count() == 0);
emit curTabStatusChanged(NULL, false);
emit outlineChanged(VToc());
emit curHeaderChanged(VAnchor());
return;
}
VEditWindow *win = getWindow(curWindowIndex); VEditWindow *win = getWindow(curWindowIndex);
win->requestUpdateTabStatus(); win->requestUpdateTabStatus();
win->requestUpdateOutline(); win->requestUpdateOutline();
@ -175,25 +165,83 @@ bool VEditArea::closeFile(const VFile *p_file, bool p_forced)
if (!p_file) { if (!p_file) {
return true; return true;
} }
int nrWin = splitter->count();
bool ret = false; bool ret = false;
for (int i = 0; i < nrWin; ++i) { int i = 0;
while (i < splitter->count()) {
VEditWindow *win = getWindow(i); VEditWindow *win = getWindow(i);
int nrWin = splitter->count();
ret = ret || win->closeFile(p_file, p_forced); ret = ret || win->closeFile(p_file, p_forced);
if (nrWin == splitter->count()) {
++i;
}
} }
updateWindowStatus(); updateWindowStatus();
return ret; return ret;
} }
bool VEditArea::closeFile(const VDirectory *p_dir, bool p_forced)
{
if (!p_dir) {
return true;
}
int i = 0;
while (i < splitter->count()) {
VEditWindow *win = getWindow(i);
if (!p_forced) {
setCurrentWindow(i, false);
}
int nrWin = splitter->count();
if (!win->closeFile(p_dir, p_forced)) {
return false;
}
// win may be removed after closeFile()
if (nrWin == splitter->count()) {
++i;
}
}
updateWindowStatus();
return true;
}
bool VEditArea::closeFile(const VNotebook *p_notebook, bool p_forced)
{
if (!p_notebook) {
return true;
}
int i = 0;
while (i < splitter->count()) {
VEditWindow *win = getWindow(i);
if (!p_forced) {
setCurrentWindow(i, false);
}
int nrWin = splitter->count();
if (!win->closeFile(p_notebook, p_forced)) {
return false;
}
// win may be removed after closeFile()
if (nrWin == splitter->count()) {
++i;
}
}
updateWindowStatus();
return true;
}
bool VEditArea::closeAllFiles(bool p_forced) bool VEditArea::closeAllFiles(bool p_forced)
{ {
int nrWin = splitter->count(); int i = 0;
for (int i = 0; i < nrWin; ++i) { while (i < splitter->count()) {
VEditWindow *win = getWindow(i); VEditWindow *win = getWindow(i);
if (!p_forced) {
setCurrentWindow(i, false); setCurrentWindow(i, false);
}
int nrWin = splitter->count();
if (!win->closeAllFiles(p_forced)) { if (!win->closeAllFiles(p_forced)) {
return false; return false;
} }
if (nrWin == splitter->count()) {
++i;
}
} }
updateWindowStatus(); updateWindowStatus();
return true; return true;
@ -241,14 +289,12 @@ void VEditArea::handleRemoveSplitRequest(VEditWindow *curWindow)
} }
int idx = splitter->indexOf(curWindow); int idx = splitter->indexOf(curWindow);
// curWindow will be deleted later
removeSplitWindow(curWindow); removeSplitWindow(curWindow);
if (idx >= splitter->count()) { if (idx >= splitter->count()) {
idx = splitter->count() - 1; idx = splitter->count() - 1;
} }
// At least one split window left
Q_ASSERT(idx >= 0);
setCurrentWindow(idx, true); setCurrentWindow(idx, true);
} }
@ -321,3 +367,11 @@ void VEditArea::handleDirectoryUpdated(const VDirectory *p_dir)
getWindow(i)->updateDirectoryInfo(p_dir); getWindow(i)->updateDirectoryInfo(p_dir);
} }
} }
void VEditArea::handleNotebookUpdated(const VNotebook *p_notebook)
{
int nrWin = splitter->count();
for (int i = 0; i < nrWin; ++i) {
getWindow(i)->updateNotebookInfo(p_notebook);
}
}

View File

@ -25,6 +25,9 @@ public:
explicit VEditArea(VNote *vnote, QWidget *parent = 0); explicit VEditArea(VNote *vnote, QWidget *parent = 0);
bool isFileOpened(const VFile *p_file); bool isFileOpened(const VFile *p_file);
bool closeAllFiles(bool p_forced); bool closeAllFiles(bool p_forced);
bool closeFile(const VFile *p_file, bool p_forced);
bool closeFile(const VDirectory *p_dir, bool p_forced);
bool closeFile(const VNotebook *p_notebook, bool p_forced);
signals: signals:
void curTabStatusChanged(const VFile *p_file, bool p_editMode); void curTabStatusChanged(const VFile *p_file, bool p_editMode);
@ -36,7 +39,6 @@ protected:
public slots: public slots:
void openFile(VFile *p_file, OpenFileMode p_mode); void openFile(VFile *p_file, OpenFileMode p_mode);
bool closeFile(const VFile *p_file, bool p_forced);
void editFile(); void editFile();
void saveFile(); void saveFile();
void readFile(); void readFile();
@ -44,6 +46,7 @@ public slots:
void handleOutlineItemActivated(const VAnchor &anchor); void handleOutlineItemActivated(const VAnchor &anchor);
void handleFileUpdated(const VFile *p_file); void handleFileUpdated(const VFile *p_file);
void handleDirectoryUpdated(const VDirectory *p_dir); void handleDirectoryUpdated(const VDirectory *p_dir);
void handleNotebookUpdated(const VNotebook *p_notebook);
private slots: private slots:
void handleSplitWindowRequest(VEditWindow *curWindow); void handleSplitWindowRequest(VEditWindow *curWindow);
@ -72,6 +75,7 @@ private:
inline VEditWindow* VEditArea::getWindow(int windowIndex) const inline VEditWindow* VEditArea::getWindow(int windowIndex) const
{ {
Q_ASSERT(windowIndex < splitter->count());
return dynamic_cast<VEditWindow *>(splitter->widget(windowIndex)); return dynamic_cast<VEditWindow *>(splitter->widget(windowIndex));
} }

View File

@ -22,7 +22,8 @@ VEditTab::VEditTab(VFile *p_file, OpenFileMode p_mode, QWidget *p_parent)
: QStackedWidget(p_parent), m_file(p_file), isEditMode(false), : QStackedWidget(p_parent), m_file(p_file), isEditMode(false),
mdConverterType(vconfig.getMdConverterType()) mdConverterType(vconfig.getMdConverterType())
{ {
qDebug() << "ready to open" << p_file->getName(); tableOfContent.filePath = p_file->retrivePath();
curHeader.filePath = p_file->retrivePath();
Q_ASSERT(!m_file->isOpened()); Q_ASSERT(!m_file->isOpened());
m_file->open(); m_file->open();
setupUI(); setupUI();

View File

@ -50,6 +50,8 @@ void VEditWindow::setupCornerWidget()
rightMenu->addAction(removeSplitAct); rightMenu->addAction(removeSplitAct);
rightBtn->setMenu(rightMenu); rightBtn->setMenu(rightMenu);
setCornerWidget(rightBtn, Qt::TopRightCorner); setCornerWidget(rightBtn, Qt::TopRightCorner);
connect(rightMenu, &QMenu::aboutToShow,
this, &VEditWindow::updateSplitMenu);
// Left corner button // Left corner button
tabListAct = new QActionGroup(this); tabListAct = new QActionGroup(this);
@ -78,21 +80,13 @@ void VEditWindow::removeSplit()
closeAllFiles(false); closeAllFiles(false);
} }
void VEditWindow::setRemoveSplitEnable(bool enabled)
{
removeSplitAct->setVisible(enabled);
}
void VEditWindow::removeEditTab(int p_index) void VEditWindow::removeEditTab(int p_index)
{ {
if (p_index > -1 && p_index < tabBar()->count()) { Q_ASSERT(p_index > -1 && p_index < tabBar()->count());
VEditTab *editor = getTab(p_index); VEditTab *editor = getTab(p_index);
removeTab(p_index); removeTab(p_index);
delete editor; delete editor;
if (tabBar()->count() == 0) {
emit requestRemoveSplit(this);
}
}
} }
int VEditWindow::insertEditTab(int p_index, VFile *p_file, QWidget *p_page) int VEditWindow::insertEditTab(int p_index, VFile *p_file, QWidget *p_page)
@ -100,7 +94,6 @@ int VEditWindow::insertEditTab(int p_index, VFile *p_file, QWidget *p_page)
int idx = insertTab(p_index, p_page, p_file->getName()); int idx = insertTab(p_index, p_page, p_file->getName());
QTabBar *tabs = tabBar(); QTabBar *tabs = tabBar();
tabs->setTabToolTip(idx, generateTooltip(p_file)); tabs->setTabToolTip(idx, generateTooltip(p_file));
noticeStatus(currentIndex());
return idx; return idx;
} }
@ -121,7 +114,6 @@ int VEditWindow::openFile(VFile *p_file, OpenFileMode p_mode)
out: out:
setCurrentIndex(idx); setCurrentIndex(idx);
focusWindow(); focusWindow();
noticeStatus(idx);
return idx; return idx;
} }
@ -145,9 +137,50 @@ bool VEditWindow::closeFile(const VFile *p_file, bool p_forced)
if (ok) { if (ok) {
removeEditTab(idx); removeEditTab(idx);
} }
if (count() == 0) {
emit requestRemoveSplit(this);
}
return ok; return ok;
} }
bool VEditWindow::closeFile(const VDirectory *p_dir, bool p_forced)
{
Q_ASSERT(p_dir);
int i = 0;
while (i < count()) {
VEditTab *editor = getTab(i);
QPointer<VFile> file = editor->getFile();
if (p_dir->containsFile(file)) {
if (!closeFile(file, p_forced)) {
return false;
}
// Closed a file, so don't need to add i.
} else {
++i;
}
}
return true;
}
bool VEditWindow::closeFile(const VNotebook *p_notebook, bool p_forced)
{
Q_ASSERT(p_notebook);
int i = 0;
while (i < count()) {
VEditTab *editor = getTab(i);
QPointer<VFile> file = editor->getFile();
if (p_notebook->containsFile(file)) {
if (!closeFile(file, p_forced)) {
return false;
}
// Closed a file, so don't need to add i.
} else {
++i;
}
}
return true;
}
bool VEditWindow::closeAllFiles(bool p_forced) bool VEditWindow::closeAllFiles(bool p_forced)
{ {
int nrTab = count(); int nrTab = count();
@ -168,7 +201,7 @@ bool VEditWindow::closeAllFiles(bool p_forced)
break; break;
} }
} }
if (ret) { if (count() == 0) {
emit requestRemoveSplit(this); emit requestRemoveSplit(this);
} }
return ret; return ret;
@ -192,7 +225,7 @@ int VEditWindow::openFileInTab(VFile *p_file, OpenFileMode p_mode)
int VEditWindow::findTabByFile(const VFile *p_file) const int VEditWindow::findTabByFile(const VFile *p_file) const
{ {
int nrTabs = tabBar()->count(); int nrTabs = count();
for (int i = 0; i < nrTabs; ++i) { for (int i = 0; i < nrTabs; ++i) {
if (getTab(i)->getFile() == p_file) { if (getTab(i)->getFile() == p_file) {
return i; return i;
@ -209,10 +242,13 @@ bool VEditWindow::handleTabCloseRequest(int index)
if (ok) { if (ok) {
removeEditTab(index); removeEditTab(index);
} }
noticeStatus(currentIndex());
// User clicks the close button. We should make this window // User clicks the close button. We should make this window
// to be current window. // to be current window.
emit getFocused(); emit getFocused();
if (count() == 0) {
emit requestRemoveSplit(this);
}
return ok; return ok;
} }
@ -221,14 +257,12 @@ void VEditWindow::readFile()
VEditTab *editor = getTab(currentIndex()); VEditTab *editor = getTab(currentIndex());
Q_ASSERT(editor); Q_ASSERT(editor);
editor->readFile(); editor->readFile();
noticeStatus(currentIndex());
} }
void VEditWindow::saveAndReadFile() void VEditWindow::saveAndReadFile()
{ {
saveFile(); saveFile();
readFile(); readFile();
noticeStatus(currentIndex());
} }
void VEditWindow::editFile() void VEditWindow::editFile()
@ -236,7 +270,6 @@ void VEditWindow::editFile()
VEditTab *editor = getTab(currentIndex()); VEditTab *editor = getTab(currentIndex());
Q_ASSERT(editor); Q_ASSERT(editor);
editor->editFile(); editor->editFile();
noticeStatus(currentIndex());
} }
void VEditWindow::saveFile() void VEditWindow::saveFile()
@ -307,7 +340,6 @@ void VEditWindow::handleTabbarClicked(int index)
{ {
// The child will emit getFocused here // The child will emit getFocused here
focusWindow(); focusWindow();
noticeStatus(index);
} }
void VEditWindow::mousePressEvent(QMouseEvent *event) void VEditWindow::mousePressEvent(QMouseEvent *event)
@ -320,8 +352,10 @@ void VEditWindow::contextMenuRequested(QPoint pos)
{ {
QMenu menu(this); QMenu menu(this);
if (canRemoveSplit()) {
menu.addAction(removeSplitAct); menu.addAction(removeSplitAct);
menu.exec(this->mapToGlobal(pos)); menu.exec(this->mapToGlobal(pos));
}
} }
void VEditWindow::tabListJump(QAction *action) void VEditWindow::tabListJump(QAction *action)
@ -362,6 +396,22 @@ void VEditWindow::updateTabListMenu()
} }
} }
void VEditWindow::updateSplitMenu()
{
if (canRemoveSplit()) {
removeSplitAct->setVisible(true);
} else {
removeSplitAct->setVisible(false);
}
}
bool VEditWindow::canRemoveSplit()
{
QSplitter *splitter = dynamic_cast<QSplitter *>(parent());
Q_ASSERT(splitter);
return splitter->count() > 1;
}
void VEditWindow::handleOutlineChanged(const VToc &p_toc) void VEditWindow::handleOutlineChanged(const VToc &p_toc)
{ {
// Only propagate it if it is current tab // Only propagate it if it is current tab
@ -406,6 +456,7 @@ void VEditWindow::scrollCurTab(const VAnchor &p_anchor)
// Update tab status, outline and current header. // Update tab status, outline and current header.
void VEditWindow::noticeStatus(int index) void VEditWindow::noticeStatus(int index)
{ {
qDebug() << "tab" << index;
noticeTabStatus(index); noticeTabStatus(index);
if (index == -1) { if (index == -1) {
@ -440,7 +491,7 @@ void VEditWindow::updateDirectoryInfo(const VDirectory *p_dir)
return; return;
} }
int nrTab = tabBar()->count(); int nrTab = count();
for (int i = 0; i < nrTab; ++i) { for (int i = 0; i < nrTab; ++i) {
VEditTab *editor = getTab(i); VEditTab *editor = getTab(i);
QPointer<VFile> file = editor->getFile(); QPointer<VFile> file = editor->getFile();
@ -449,3 +500,19 @@ void VEditWindow::updateDirectoryInfo(const VDirectory *p_dir)
} }
} }
} }
void VEditWindow::updateNotebookInfo(const VNotebook *p_notebook)
{
if (!p_notebook) {
return;
}
int nrTab = count();
for (int i = 0; i < nrTab; ++i) {
VEditTab *editor = getTab(i);
QPointer<VFile> file = editor->getFile();
if (p_notebook->containsFile(file)) {
noticeStatus(i);
}
}
}

View File

@ -23,12 +23,13 @@ public:
int findTabByFile(const VFile *p_file) const; int findTabByFile(const VFile *p_file) const;
int openFile(VFile *p_file, OpenFileMode p_mode); int openFile(VFile *p_file, OpenFileMode p_mode);
bool closeFile(const VFile *p_file, bool p_forced); bool closeFile(const VFile *p_file, bool p_forced);
bool closeFile(const VDirectory *p_dir, bool p_forced);
bool closeFile(const VNotebook *p_notebook, bool p_forced);
void editFile(); void editFile();
void saveFile(); void saveFile();
void readFile(); void readFile();
void saveAndReadFile(); void saveAndReadFile();
bool closeAllFiles(bool p_forced); bool closeAllFiles(bool p_forced);
void setRemoveSplitEnable(bool enabled);
void requestUpdateTabStatus(); void requestUpdateTabStatus();
void requestUpdateOutline(); void requestUpdateOutline();
void requestUpdateCurHeader(); void requestUpdateCurHeader();
@ -37,6 +38,7 @@ public:
void scrollCurTab(const VAnchor &p_anchor); void scrollCurTab(const VAnchor &p_anchor);
void updateFileInfo(const VFile *p_file); void updateFileInfo(const VFile *p_file);
void updateDirectoryInfo(const VDirectory *p_dir); void updateDirectoryInfo(const VDirectory *p_dir);
void updateNotebookInfo(const VNotebook *p_notebook);
protected: protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
@ -61,6 +63,7 @@ private slots:
void handleCurHeaderChanged(const VAnchor &p_anchor); void handleCurHeaderChanged(const VAnchor &p_anchor);
void handleTabStatusChanged(); void handleTabStatusChanged();
void updateTabListMenu(); void updateTabListMenu();
void updateSplitMenu();
private: private:
void setupCornerWidget(); void setupCornerWidget();
@ -73,6 +76,7 @@ private:
void noticeStatus(int index); void noticeStatus(int index);
inline QString generateTooltip(const VFile *p_file) const; inline QString generateTooltip(const VFile *p_file) const;
inline QString generateTabText(const QString &p_name, bool p_modified) const; inline QString generateTabText(const QString &p_name, bool p_modified) const;
bool canRemoveSplit();
VNote *vnote; VNote *vnote;
// Button in the right corner // Button in the right corner

View File

@ -5,16 +5,15 @@
#include "vnote.h" #include "vnote.h"
#include "vfilelist.h" #include "vfilelist.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "dialog/vnewnotebookdialog.h"
#include "dialog/vnotebookinfodialog.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "veditarea.h" #include "veditarea.h"
#include "voutline.h" #include "voutline.h"
#include "vnotebookselector.h"
extern VConfigManager vconfig; extern VConfigManager vconfig;
VMainWindow::VMainWindow(QWidget *parent) VMainWindow::VMainWindow(QWidget *parent)
: QMainWindow(parent), notebookComboMuted(false) : QMainWindow(parent)
{ {
setWindowIcon(QIcon(":/resources/icons/vnote.ico")); setWindowIcon(QIcon(":/resources/icons/vnote.ico"));
// Must be called before those who uses VConfigManager // Must be called before those who uses VConfigManager
@ -28,7 +27,7 @@ VMainWindow::VMainWindow(QWidget *parent)
initDockWindows(); initDockWindows();
restoreStateAndGeometry(); restoreStateAndGeometry();
updateNotebookComboBox(vnote->getNotebooks()); notebookSelector->update();
} }
void VMainWindow::setupUI() void VMainWindow::setupUI()
@ -41,6 +40,8 @@ void VMainWindow::setupUI()
editArea = new VEditArea(vnote); editArea = new VEditArea(vnote);
editArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); editArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
fileList->setEditArea(editArea); fileList->setEditArea(editArea);
directoryTree->setEditArea(editArea);
notebookSelector->setEditArea(editArea);
// Main Splitter // Main Splitter
mainSplitter = new QSplitter(); mainSplitter = new QSplitter();
@ -52,15 +53,13 @@ void VMainWindow::setupUI()
mainSplitter->setStretchFactor(2, 1); mainSplitter->setStretchFactor(2, 1);
// Signals // Signals
connect(notebookComboBox, SIGNAL(currentIndexChanged(int)), this,
SLOT(setCurNotebookIndex(int)));
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged, connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
fileList, &VFileList::setDirectory); fileList, &VFileList::setDirectory);
connect(directoryTree, &VDirectoryTree::directoryUpdated, connect(directoryTree, &VDirectoryTree::directoryUpdated,
editArea, &VEditArea::handleDirectoryUpdated); editArea, &VEditArea::handleDirectoryUpdated);
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
this, &VMainWindow::handleCurrentDirectoryChanged); connect(notebookSelector, &VNotebookSelector::notebookUpdated,
editArea, &VEditArea::handleNotebookUpdated);
connect(fileList, &VFileList::fileClicked, connect(fileList, &VFileList::fileClicked,
editArea, &VEditArea::openFile); editArea, &VEditArea::openFile);
@ -71,23 +70,6 @@ void VMainWindow::setupUI()
connect(editArea, &VEditArea::curTabStatusChanged, connect(editArea, &VEditArea::curTabStatusChanged,
this, &VMainWindow::handleCurTabStatusChanged); this, &VMainWindow::handleCurTabStatusChanged);
connect(newNotebookBtn, &QPushButton::clicked,
this, &VMainWindow::onNewNotebookBtnClicked);
connect(deleteNotebookBtn, &QPushButton::clicked,
this, &VMainWindow::onDeleteNotebookBtnClicked);
connect(notebookInfoBtn, &QPushButton::clicked,
this, &VMainWindow::onNotebookInfoBtnClicked);
connect(vnote, &VNote::notebookDeleted,
this, &VMainWindow::notebookComboBoxDeleted);
connect(vnote, &VNote::notebookRenamed,
this, &VMainWindow::notebookComboBoxRenamed);
connect(vnote, &VNote::notebookAdded,
this, &VMainWindow::notebookComboBoxAdded);
connect(this, &VMainWindow::curNotebookChanged,
directoryTree, &VDirectoryTree::setNotebook);
setCentralWidget(mainSplitter); setCentralWidget(mainSplitter);
// Create and show the status bar // Create and show the status bar
statusBar(); statusBar();
@ -108,9 +90,9 @@ QWidget *VMainWindow::setupDirectoryPanel()
notebookInfoBtn->setToolTip(tr("View and edit current notebook's information")); notebookInfoBtn->setToolTip(tr("View and edit current notebook's information"));
notebookInfoBtn->setProperty("OnMainWindow", true); notebookInfoBtn->setProperty("OnMainWindow", true);
notebookComboBox = new QComboBox(); notebookSelector = new VNotebookSelector(vnote);
notebookComboBox->setProperty("OnMainWindow", true); notebookSelector->setProperty("OnMainWindow", true);
notebookComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); notebookSelector->setSizeAdjustPolicy(QComboBox::AdjustToContents);
directoryTree = new VDirectoryTree(vnote); directoryTree = new VDirectoryTree(vnote);
QHBoxLayout *nbBtnLayout = new QHBoxLayout; QHBoxLayout *nbBtnLayout = new QHBoxLayout;
@ -122,7 +104,7 @@ QWidget *VMainWindow::setupDirectoryPanel()
nbBtnLayout->setContentsMargins(0, 0, 0, 0); nbBtnLayout->setContentsMargins(0, 0, 0, 0);
QVBoxLayout *nbLayout = new QVBoxLayout; QVBoxLayout *nbLayout = new QVBoxLayout;
nbLayout->addLayout(nbBtnLayout); nbLayout->addLayout(nbBtnLayout);
nbLayout->addWidget(notebookComboBox); nbLayout->addWidget(notebookSelector);
nbLayout->addWidget(directoryLabel); nbLayout->addWidget(directoryLabel);
nbLayout->addWidget(directoryTree); nbLayout->addWidget(directoryTree);
nbLayout->setContentsMargins(5, 0, 0, 0); nbLayout->setContentsMargins(5, 0, 0, 0);
@ -130,6 +112,20 @@ QWidget *VMainWindow::setupDirectoryPanel()
nbContainer->setLayout(nbLayout); nbContainer->setLayout(nbLayout);
nbContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); nbContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
connect(notebookSelector, &VNotebookSelector::curNotebookChanged,
directoryTree, &VDirectoryTree::setNotebook);
connect(notebookSelector, &VNotebookSelector::curNotebookChanged,
this, &VMainWindow::handleCurrentNotebookChanged);
connect(newNotebookBtn, &QPushButton::clicked,
notebookSelector, &VNotebookSelector::newNotebook);
connect(deleteNotebookBtn, SIGNAL(clicked(bool)),
notebookSelector, SLOT(deleteNotebook()));
connect(notebookInfoBtn, SIGNAL(clicked(bool)),
notebookSelector, SLOT(editNotebookInfo()));
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
this, &VMainWindow::handleCurrentDirectoryChanged);
return nbContainer; return nbContainer;
} }
@ -366,158 +362,6 @@ void VMainWindow::initDockWindows()
viewMenu->addAction(toolDock->toggleViewAction()); viewMenu->addAction(toolDock->toggleViewAction());
} }
void VMainWindow::updateNotebookComboBox(const QVector<VNotebook *> &p_notebooks)
{
notebookComboMuted = true;
notebookComboBox->clear();
for (int i = 0; i < p_notebooks.size(); ++i) {
notebookComboBox->addItem(QIcon(":/resources/icons/notebook_item.svg"),
p_notebooks[i]->getName());
}
notebookComboMuted = false;
int index = vconfig.getCurNotebookIndex();
if (p_notebooks.isEmpty()) {
index = -1;
}
if (notebookComboBox->currentIndex() == index) {
setCurNotebookIndex(index);
} else {
notebookComboBox->setCurrentIndex(index);
}
}
void VMainWindow::notebookComboBoxAdded(const VNotebook *p_notebook, int p_idx)
{
notebookComboMuted = true;
notebookComboBox->insertItem(p_idx, QIcon(":/resources/icons/notebook_item.svg"),
p_notebook->getName());
notebookComboMuted = false;
if (notebookComboBox->currentIndex() == vconfig.getCurNotebookIndex()) {
setCurNotebookIndex(vconfig.getCurNotebookIndex());
} else {
notebookComboBox->setCurrentIndex(vconfig.getCurNotebookIndex());
}
}
void VMainWindow::notebookComboBoxDeleted(int p_oriIdx)
{
Q_ASSERT(p_oriIdx >= 0 && p_oriIdx < notebookComboBox->count());
notebookComboMuted = true;
notebookComboBox->removeItem(p_oriIdx);
notebookComboMuted = false;
if (notebookComboBox->currentIndex() == vconfig.getCurNotebookIndex()) {
setCurNotebookIndex(vconfig.getCurNotebookIndex());
} else {
notebookComboBox->setCurrentIndex(vconfig.getCurNotebookIndex());
}
}
void VMainWindow::notebookComboBoxRenamed(const VNotebook *p_notebook, int p_idx)
{
Q_ASSERT(p_idx >= 0 && p_idx < notebookComboBox->count());
notebookComboBox->setItemText(p_idx, p_notebook->getName());
// Renaming a notebook won't change current index
}
// Maybe called multiple times
void VMainWindow::setCurNotebookIndex(int index)
{
if (notebookComboMuted) {
return;
}
Q_ASSERT(index < vnote->getNotebooks().size());
// Update directoryTree
VNotebook *notebook = NULL;
if (index > -1) {
vconfig.setCurNotebookIndex(index);
notebook = vnote->getNotebooks()[index];
newRootDirAct->setEnabled(true);
} else {
newRootDirAct->setEnabled(false);
}
emit curNotebookChanged(notebook);
}
void VMainWindow::onNewNotebookBtnClicked()
{
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)) {
info = "Name already exists.";
defaultName = name;
defaultPath = path;
continue;
}
vnote->createNotebook(name, path);
}
break;
} while (true);
}
bool VMainWindow::isConflictWithExistingNotebooks(const QString &name)
{
const QVector<VNotebook *> &notebooks = vnote->getNotebooks();
for (int i = 0; i < notebooks.size(); ++i) {
if (notebooks[i]->getName() == name) {
return true;
}
}
return false;
}
void VMainWindow::onDeleteNotebookBtnClicked()
{
int curIndex = notebookComboBox->currentIndex();
QString curName = vnote->getNotebooks()[curIndex]->getName();
QString curPath = vnote->getNotebooks()[curIndex]->getPath();
QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Are you sure you want to delete notebook \"%1\"?")
.arg(curName), QMessageBox::Ok | QMessageBox::Cancel, this);
msgBox.setInformativeText(QString("This will delete any files in this notebook (\"%1\").").arg(curPath));
msgBox.setDefaultButton(QMessageBox::Cancel);
if (msgBox.exec() == QMessageBox::Ok) {
vnote->removeNotebook(curIndex);
}
}
void VMainWindow::onNotebookInfoBtnClicked()
{
int curIndex = notebookComboBox->currentIndex();
if (curIndex < 0) {
return;
}
QString info;
QString curName = vnote->getNotebooks()[curIndex]->getName();
QString defaultPath = vnote->getNotebooks()[curIndex]->getPath();
QString defaultName(curName);
do {
VNotebookInfoDialog dialog(tr("Notebook information"), info, defaultName,
defaultPath, this);
if (dialog.exec() == QDialog::Accepted) {
QString name = dialog.getNameInput();
if (name == curName) {
return;
}
if (isConflictWithExistingNotebooks(name)) {
info = "Name already exists.";
defaultName = name;
continue;
}
vnote->renameNotebook(curIndex, name);
}
break;
} while (true);
}
void VMainWindow::importNoteFromFile() void VMainWindow::importNoteFromFile()
{ {
static QString lastPath = QDir::homePath(); static QString lastPath = QDir::homePath();
@ -806,3 +650,8 @@ void VMainWindow::handleCurrentDirectoryChanged(const VDirectory *p_dir)
{ {
newNoteAct->setEnabled(p_dir); newNoteAct->setEnabled(p_dir);
} }
void VMainWindow::handleCurrentNotebookChanged(const VNotebook *p_notebook)
{
newRootDirAct->setEnabled(p_notebook);
}

View File

@ -24,6 +24,7 @@ class VFileList;
class VEditArea; class VEditArea;
class QToolBox; class QToolBox;
class VOutline; class VOutline;
class VNotebookSelector;
class VMainWindow : public QMainWindow class VMainWindow : public QMainWindow
{ {
@ -34,15 +35,6 @@ public:
const QVector<QPair<QString, QString> > &getPalette() const; const QVector<QPair<QString, QString> > &getPalette() const;
private slots: private slots:
void setCurNotebookIndex(int index);
// Create a notebook
void onNewNotebookBtnClicked();
void onDeleteNotebookBtnClicked();
void onNotebookInfoBtnClicked();
void updateNotebookComboBox(const QVector<VNotebook *> &p_notebooks);
void notebookComboBoxAdded(const VNotebook *p_notebook, int p_idx);
void notebookComboBoxDeleted(int p_oriIdx);
void notebookComboBoxRenamed(const VNotebook *p_notebook, int p_idx);
void importNoteFromFile(); void importNoteFromFile();
void changeMarkdownConverter(QAction *action); void changeMarkdownConverter(QAction *action);
void aboutMessage(); void aboutMessage();
@ -55,9 +47,7 @@ private slots:
void curEditFileInfo(); void curEditFileInfo();
void deleteCurNote(); void deleteCurNote();
void handleCurrentDirectoryChanged(const VDirectory *p_dir); void handleCurrentDirectoryChanged(const VDirectory *p_dir);
void handleCurrentNotebookChanged(const VNotebook *p_notebook);
signals:
void curNotebookChanged(VNotebook *p_notebook);
protected: protected:
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
@ -69,7 +59,6 @@ private:
void initToolBar(); void initToolBar();
void initMenuBar(); void initMenuBar();
void initDockWindows(); void initDockWindows();
bool isConflictWithExistingNotebooks(const QString &name);
void initPredefinedColorPixmaps(); void initPredefinedColorPixmaps();
void initRenderBackgroundMenu(QMenu *menu); void initRenderBackgroundMenu(QMenu *menu);
void initEditorBackgroundMenu(QMenu *menu); void initEditorBackgroundMenu(QMenu *menu);
@ -79,14 +68,12 @@ private:
void saveStateAndGeometry(); void saveStateAndGeometry();
void restoreStateAndGeometry(); void restoreStateAndGeometry();
// If true, comboBox changes will not trigger any signal out
bool notebookComboMuted;
VNote *vnote; VNote *vnote;
QPointer<VFile> m_curFile; QPointer<VFile> m_curFile;
QLabel *notebookLabel; QLabel *notebookLabel;
QLabel *directoryLabel; QLabel *directoryLabel;
QComboBox *notebookComboBox; VNotebookSelector *notebookSelector;
QPushButton *newNotebookBtn; QPushButton *newNotebookBtn;
QPushButton *deleteNotebookBtn; QPushButton *deleteNotebookBtn;
QPushButton *notebookInfoBtn; QPushButton *notebookInfoBtn;

View File

@ -75,89 +75,12 @@ void VNote::updateTemplate()
postTemplateHtml = VUtils::readFileFromDisk(vconfig.getPostTemplatePath()); postTemplateHtml = VUtils::readFileFromDisk(vconfig.getPostTemplatePath());
} }
const QVector<VNotebook *> &VNote::getNotebooks() const QVector<VNotebook *> &VNote::getNotebooks() const
{ {
return m_notebooks; return m_notebooks;
} }
void VNote::createNotebook(const QString &name, const QString &path) QVector<VNotebook *> &VNote::getNotebooks()
{ {
// Create a directory config file in @path return m_notebooks;
QJsonObject configJson;
configJson["version"] = "1";
configJson["sub_directories"] = QJsonArray();
configJson["files"] = QJsonArray();
if (!vconfig.writeDirectoryConfig(path, configJson)) {
return;
}
// Update notebooks settings
VNotebook *nb = new VNotebook(name, path, this);
m_notebooks.prepend(nb);
vconfig.setNotebooks(m_notebooks);
// Set current index to the new notebook
vconfig.setCurNotebookIndex(0);
emit notebookAdded(nb, 0);
}
void VNote::removeNotebook(int idx)
{
Q_ASSERT(idx >= 0 && idx < m_notebooks.size());
VNotebook *nb = m_notebooks[idx];
QString name = nb->getName();
QString path = nb->getPath();
// Update notebook settings
int curIndex = vconfig.getCurNotebookIndex();
m_notebooks.remove(idx);
vconfig.setNotebooks(m_notebooks);
if (m_notebooks.isEmpty()) {
vconfig.setCurNotebookIndex(-1);
} else if (idx == curIndex) {
vconfig.setCurNotebookIndex(0);
}
// Close all the directory and files
notebookPathHash.remove(name);
nb->close();
delete nb;
qDebug() << "notebook" << name << "deleted";
// Delete the directory
QDir dir(path);
if (!dir.removeRecursively()) {
qWarning() << "failed to delete" << path << "recursively";
}
emit notebookDeleted(idx);
}
void VNote::renameNotebook(int idx, const QString &newName)
{
Q_ASSERT(idx >= 0 && idx < m_notebooks.size());
VNotebook *nb = m_notebooks[idx];
QString name = nb->getName();
notebookPathHash.remove(name);
nb->setName(newName);
vconfig.setNotebooks(m_notebooks);
emit notebookRenamed(nb, idx);
}
QString VNote::getNotebookPath(const QString &name)
{
QString path = notebookPathHash.value(name);
if (path.isEmpty()) {
for (int i = 0; i < m_notebooks.size(); ++i) {
if (m_notebooks[i]->getName() == name) {
path = m_notebooks[i]->getPath();
break;
}
}
if (!path.isEmpty()) {
notebookPathHash.insert(name, path);
}
}
return path;
} }

View File

@ -18,7 +18,8 @@ class VNote : public QObject
public: public:
VNote(QObject *parent = 0); VNote(QObject *parent = 0);
const QVector<VNotebook *>& getNotebooks(); const QVector<VNotebook *> &getNotebooks() const;
QVector<VNotebook *> &getNotebooks();
void initTemplate(); void initTemplate();
@ -29,27 +30,15 @@ public:
static QString preTemplateHtml; static QString preTemplateHtml;
static QString postTemplateHtml; static QString postTemplateHtml;
void createNotebook(const QString &name, const QString &path);
void removeNotebook(int idx);
void renameNotebook(int idx, const QString &newName);
QString getNotebookPath(const QString &name);
inline const QVector<QPair<QString, QString> > &getPallete() const; inline const QVector<QPair<QString, QString> > &getPallete() const;
void initPalette(QPalette palette); void initPalette(QPalette palette);
public slots: public slots:
void updateTemplate(); void updateTemplate();
signals:
void notebookAdded(const VNotebook *p_notebook, int p_idx);
void notebookDeleted(int p_oriIdx);
void notebookRenamed(const VNotebook *p_notebook, int p_idx);
private: private:
// Maintain all the notebooks. Other holder should use QPointer. // Maintain all the notebooks. Other holder should use QPointer.
QVector<VNotebook *> m_notebooks; QVector<VNotebook *> m_notebooks;
QHash<QString, QString> notebookPathHash;
QVector<QPair<QString, QString> > m_palette; QVector<QPair<QString, QString> > m_palette;
}; };

View File

@ -1,6 +1,10 @@
#include "vnotebook.h" #include "vnotebook.h"
#include <QDir>
#include <QDebug>
#include "vdirectory.h" #include "vdirectory.h"
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vconfigmanager.h"
#include "vfile.h"
VNotebook::VNotebook(const QString &name, const QString &path, QObject *parent) VNotebook::VNotebook(const QString &name, const QString &path, QObject *parent)
: QObject(parent), m_name(name), m_path(path) : QObject(parent), m_name(name), m_path(path)
@ -23,16 +27,6 @@ QString VNotebook::getPath() const
return m_path; return m_path;
} }
void VNotebook::setName(const QString &name)
{
m_name = name;
}
void VNotebook::setPath(const QString &path)
{
m_path = path;
}
void VNotebook::close() void VNotebook::close()
{ {
m_rootDir->close(); m_rootDir->close();
@ -42,3 +36,48 @@ bool VNotebook::open()
{ {
return m_rootDir->open(); return m_rootDir->open();
} }
VNotebook *VNotebook::createNotebook(const QString &p_name, const QString &p_path,
QObject *p_parent)
{
VNotebook *nb = new VNotebook(p_name, p_path, p_parent);
if (!nb) {
return nb;
}
// Create directory config in @p_path
QJsonObject configJson = VDirectory::createDirectoryJson();
if (!VConfigManager::writeDirectoryConfig(p_path, configJson)) {
delete nb;
return NULL;
}
return nb;
}
void VNotebook::deleteNotebook(VNotebook *p_notebook)
{
if (!p_notebook) {
return;
}
p_notebook->close();
delete p_notebook;
QString path = p_notebook->getPath();
QDir dir(path);
if (!dir.removeRecursively()) {
qWarning() << "failed to delete" << path;
}
}
void VNotebook::rename(const QString &p_name)
{
if (p_name == m_name || p_name.isEmpty()) {
return;
}
m_name = p_name;
}
bool VNotebook::containsFile(const VFile *p_file) const
{
return m_rootDir->containsFile(p_file);
}

View File

@ -5,6 +5,7 @@
#include <QString> #include <QString>
class VDirectory; class VDirectory;
class VFile;
class VNotebook : public QObject class VNotebook : public QObject
{ {
@ -18,12 +19,16 @@ public:
// Close all the directory and files of this notebook. // Close all the directory and files of this notebook.
// Please make sure all files belonging to this notebook have been closed in the tab. // Please make sure all files belonging to this notebook have been closed in the tab.
void close(); void close();
bool containsFile(const VFile *p_file) const;
QString getName() const; QString getName() const;
QString getPath() const; QString getPath() const;
void setName(const QString &name);
void setPath(const QString &path);
inline VDirectory *getRootDir(); inline VDirectory *getRootDir();
void rename(const QString &p_name);
static VNotebook *createNotebook(const QString &p_name, const QString &p_path,
QObject *p_parent = 0);
static void deleteNotebook(VNotebook *p_notebook);
signals: signals:
void contentChanged(); void contentChanged();

173
src/vnotebookselector.cpp Normal file
View File

@ -0,0 +1,173 @@
#include "vnotebookselector.h"
#include <QDebug>
#include <QJsonObject>
#include "vnotebook.h"
#include "vconfigmanager.h"
#include "dialog/vnewnotebookdialog.h"
#include "dialog/vnotebookinfodialog.h"
#include "vnotebook.h"
#include "vdirectory.h"
#include "utils/vutils.h"
#include "vnote.h"
#include "veditarea.h"
extern VConfigManager vconfig;
VNotebookSelector::VNotebookSelector(VNote *vnote, QWidget *p_parent)
: QComboBox(p_parent), m_vnote(vnote), m_notebooks(m_vnote->getNotebooks()),
m_editArea(NULL)
{
connect(this, SIGNAL(currentIndexChanged(int)),
this, SLOT(handleCurIndexChanged(int)));
}
void VNotebookSelector::updateComboBox()
{
int index = vconfig.getCurNotebookIndex();
disconnect(this, SIGNAL(currentIndexChanged(int)),
this, SLOT(handleCurIndexChanged(int)));
clear();
for (int i = 0; i < m_notebooks.size(); ++i) {
addItem(QIcon(":/resources/icons/notebook_item.svg"), m_notebooks[i]->getName());
}
setCurrentIndex(-1);
connect(this, SIGNAL(currentIndexChanged(int)),
this, SLOT(handleCurIndexChanged(int)));
if (m_notebooks.isEmpty() && index != -1) {
index = -1;
vconfig.setCurNotebookIndex(index);
}
setCurrentIndex(index);
qDebug() << "notebooks" << m_notebooks.size() << "current index" << index;
}
void VNotebookSelector::handleCurIndexChanged(int p_index)
{
qDebug() << "current index changed" << p_index;
VNotebook *nb = NULL;
if (p_index > -1) {
nb = m_notebooks[p_index];
}
vconfig.setCurNotebookIndex(p_index);
emit curNotebookChanged(nb);
}
void VNotebookSelector::update()
{
updateComboBox();
}
void VNotebookSelector::newNotebook()
{
QString info;
QString defaultName("new_notebook");
QString defaultPath;
do {
VNewNotebookDialog dialog(tr("Create notebook"), info, defaultName,
defaultPath, this);
if (dialog.exec() == QDialog::Accepted) {
QString name = dialog.getNameInput();
QString path = dialog.getPathInput();
if (findNotebook(name)) {
info = "Name already exists. Please choose another name.";
defaultName = name;
defaultPath = path;
continue;
}
createNotebook(name, path);
}
break;
} while (true);
}
VNotebook *VNotebookSelector::findNotebook(const QString &p_name)
{
for (int i = 0; i < m_notebooks.size(); ++i) {
if (m_notebooks[i]->getName() == p_name) {
return m_notebooks[i];
}
}
return NULL;
}
void VNotebookSelector::createNotebook(const QString &p_name, const QString &p_path)
{
VNotebook *nb = VNotebook::createNotebook(p_name, p_path, m_vnote);
m_notebooks.append(nb);
vconfig.setNotebooks(m_notebooks);
addItem(QIcon(":/resources/icons/notebook_item.svg"), nb->getName());
setCurrentIndex(m_notebooks.size() - 1);
}
void VNotebookSelector::deleteNotebook()
{
int curIndex = currentIndex();
VNotebook *notebook = m_notebooks[curIndex];
QString curName = notebook->getName();
QString curPath = notebook->getPath();
int ret = VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
QString("Are you sure to delete notebook %1?").arg(curName),
QString("This will delete any files in this notebook (%1).").arg(curPath),
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok, this);
if (ret == QMessageBox::Ok) {
m_editArea->closeFile(notebook, true);
deleteNotebook(notebook);
}
}
void VNotebookSelector::deleteNotebook(VNotebook *p_notebook)
{
int idx = indexOfNotebook(p_notebook);
m_notebooks.remove(idx);
vconfig.setNotebooks(m_notebooks);
removeItem(idx);
VNotebook::deleteNotebook(p_notebook);
}
int VNotebookSelector::indexOfNotebook(const VNotebook *p_notebook)
{
for (int i = 0; i < m_notebooks.size(); ++i) {
if (m_notebooks[i] == p_notebook) {
return i;
}
}
return -1;
}
void VNotebookSelector::editNotebookInfo()
{
int curIndex = currentIndex();
Q_ASSERT(curIndex > -1);
VNotebook *notebook = m_notebooks[curIndex];
QString info;
QString curName = notebook->getName();
QString defaultPath = notebook->getPath();
QString defaultName(curName);
do {
VNotebookInfoDialog dialog(tr("Notebook information"), info, defaultName,
defaultPath, this);
if (dialog.exec() == QDialog::Accepted) {
QString name = dialog.getNameInput();
if (name == curName) {
return;
}
if (findNotebook(name)) {
info = "Name already exists. Please choose another name.";
defaultName = name;
continue;
}
notebook->rename(name);
setItemText(curIndex, name);
vconfig.setNotebooks(m_notebooks);
emit notebookUpdated(notebook);
}
break;
} while (true);
}

50
src/vnotebookselector.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef VNOTEBOOKSELECTOR_H
#define VNOTEBOOKSELECTOR_H
#include <QComboBox>
#include <QVector>
#include <QString>
class VNotebook;
class VNote;
class VEditArea;
class VNotebookSelector : public QComboBox
{
Q_OBJECT
public:
explicit VNotebookSelector(VNote *vnote, QWidget *p_parent = 0);
void update();
inline void setEditArea(VEditArea *p_editArea);
signals:
void curNotebookChanged(VNotebook *p_notebook);
// Info of current notebook was changed.
void notebookUpdated(const VNotebook *p_notebook);
public slots:
void newNotebook();
void deleteNotebook();
void editNotebookInfo();
private slots:
void handleCurIndexChanged(int p_index);
private:
void updateComboBox();
VNotebook *findNotebook(const QString &p_name);
int indexOfNotebook(const VNotebook *p_notebook);
void createNotebook(const QString &p_name, const QString &p_path);
void deleteNotebook(VNotebook *p_notebook);
VNote *m_vnote;
QVector<VNotebook *> &m_notebooks;
VEditArea *m_editArea;
};
inline void VNotebookSelector::setEditArea(VEditArea *p_editArea)
{
m_editArea = p_editArea;
}
#endif // VNOTEBOOKSELECTOR_H