diff --git a/src/dialog/vdirinfodialog.cpp b/src/dialog/vdirinfodialog.cpp index c6a9907b..7cf7aca5 100644 --- a/src/dialog/vdirinfodialog.cpp +++ b/src/dialog/vdirinfodialog.cpp @@ -2,10 +2,9 @@ #include "vdirinfodialog.h" VDirInfoDialog::VDirInfoDialog(const QString &title, const QString &info, - const QString &defaultName, const QString &defaultDescription, + const QString &defaultName, QWidget *parent) - : QDialog(parent), infoLabel(NULL), title(title), info(info), defaultName(defaultName), - defaultDescription(defaultDescription) + : QDialog(parent), infoLabel(NULL), title(title), info(info), defaultName(defaultName) { setupUI(); @@ -26,10 +25,6 @@ void VDirInfoDialog::setupUI() nameEdit->selectAll(); nameLabel->setBuddy(nameEdit); - QLabel *descriptionLabel = new QLabel(tr("&Description")); - descriptionEdit = new QLineEdit(defaultDescription); - descriptionLabel->setBuddy(descriptionEdit); - okBtn = new QPushButton(tr("&OK")); okBtn->setDefault(true); cancelBtn = new QPushButton(tr("&Cancel")); @@ -40,8 +35,6 @@ void VDirInfoDialog::setupUI() } topLayout->addWidget(nameLabel); topLayout->addWidget(nameEdit); - topLayout->addWidget(descriptionLabel); - topLayout->addWidget(descriptionEdit); QHBoxLayout *btmLayout = new QHBoxLayout(); btmLayout->addStretch(); @@ -65,8 +58,3 @@ QString VDirInfoDialog::getNameInput() const { return nameEdit->text(); } - -QString VDirInfoDialog::getDescriptionInput() const -{ - return descriptionEdit->text(); -} diff --git a/src/dialog/vdirinfodialog.h b/src/dialog/vdirinfodialog.h index 07a248f8..f84b877f 100644 --- a/src/dialog/vdirinfodialog.h +++ b/src/dialog/vdirinfodialog.h @@ -13,9 +13,8 @@ class VDirInfoDialog : public QDialog Q_OBJECT public: VDirInfoDialog(const QString &title, const QString &info, const QString &defaultName, - const QString &defaultDescription, QWidget *parent = 0); + QWidget *parent = 0); QString getNameInput() const; - QString getDescriptionInput() const; private slots: void enableOkButton(); @@ -26,13 +25,11 @@ private: QLabel *infoLabel; QLabel *nameLabel; QLineEdit *nameEdit; - QLineEdit *descriptionEdit; QPushButton *okBtn; QPushButton *cancelBtn; QString title; QString info; QString defaultName; - QString defaultDescription; }; #endif // VDIRINFODIALOG_H diff --git a/src/dialog/vnewdirdialog.cpp b/src/dialog/vnewdirdialog.cpp index c0bd8759..d893b4f4 100644 --- a/src/dialog/vnewdirdialog.cpp +++ b/src/dialog/vnewdirdialog.cpp @@ -2,10 +2,8 @@ #include "vnewdirdialog.h" VNewDirDialog::VNewDirDialog(const QString &title, const QString &name, const QString &defaultName, - const QString &description, const QString &defaultDescription, QWidget *parent) - : QDialog(parent), title(title), name(name), defaultName(defaultName), - description(description), defaultDescription(defaultDescription) + : QDialog(parent), title(title), name(name), defaultName(defaultName) { setupUI(); @@ -21,10 +19,6 @@ void VNewDirDialog::setupUI() nameEdit->selectAll(); nameLabel->setBuddy(nameEdit); - descriptionLabel = new QLabel(description); - descriptionEdit = new QLineEdit(defaultDescription); - descriptionLabel->setBuddy(descriptionEdit); - okBtn = new QPushButton(tr("&OK")); okBtn->setDefault(true); cancelBtn = new QPushButton(tr("&Cancel")); @@ -32,8 +26,6 @@ void VNewDirDialog::setupUI() QVBoxLayout *topLayout = new QVBoxLayout(); topLayout->addWidget(nameLabel); topLayout->addWidget(nameEdit); - topLayout->addWidget(descriptionLabel); - topLayout->addWidget(descriptionEdit); QHBoxLayout *btmLayout = new QHBoxLayout(); btmLayout->addStretch(); @@ -57,8 +49,3 @@ QString VNewDirDialog::getNameInput() const { return nameEdit->text(); } - -QString VNewDirDialog::getDescriptionInput() const -{ - return descriptionEdit->text(); -} diff --git a/src/dialog/vnewdirdialog.h b/src/dialog/vnewdirdialog.h index ba6bc55c..89663852 100644 --- a/src/dialog/vnewdirdialog.h +++ b/src/dialog/vnewdirdialog.h @@ -12,10 +12,9 @@ class VNewDirDialog : public QDialog { Q_OBJECT public: - VNewDirDialog(const QString &title, const QString &name, const QString &defaultName, - const QString &description, const QString &defaultDescription, QWidget *parent = 0); + VNewDirDialog(const QString &title, const QString &name, + const QString &defaultName, QWidget *parent = 0); QString getNameInput() const; - QString getDescriptionInput() const; private slots: void enableOkButton(const QString &editText); @@ -24,17 +23,13 @@ private: void setupUI(); QLabel *nameLabel; - QLabel *descriptionLabel; QLineEdit *nameEdit; - QLineEdit *descriptionEdit; QPushButton *okBtn; QPushButton *cancelBtn; QString title; QString name; QString defaultName; - QString description; - QString defaultDescription; }; #endif // VNEWDIRDIALOG_H diff --git a/src/dialog/vnewfiledialog.cpp b/src/dialog/vnewfiledialog.cpp index cb1131de..21ec5d9a 100644 --- a/src/dialog/vnewfiledialog.cpp +++ b/src/dialog/vnewfiledialog.cpp @@ -2,10 +2,8 @@ #include "vnewfiledialog.h" VNewFileDialog::VNewFileDialog(const QString &title, const QString &name, const QString &defaultName, - const QString &description, const QString &defaultDescription, QWidget *parent) - : QDialog(parent), title(title), name(name), defaultName(defaultName), - description(description), defaultDescription(defaultDescription) + : QDialog(parent), title(title), name(name), defaultName(defaultName) { setupUI(); @@ -21,10 +19,6 @@ void VNewFileDialog::setupUI() nameEdit->selectAll(); nameLabel->setBuddy(nameEdit); - descriptionLabel = new QLabel(description); - descriptionEdit = new QLineEdit(defaultDescription); - descriptionLabel->setBuddy(descriptionEdit); - okBtn = new QPushButton(tr("&OK")); okBtn->setDefault(true); cancelBtn = new QPushButton(tr("&Cancel")); @@ -32,8 +26,6 @@ void VNewFileDialog::setupUI() QVBoxLayout *topLayout = new QVBoxLayout(); topLayout->addWidget(nameLabel); topLayout->addWidget(nameEdit); - topLayout->addWidget(descriptionLabel); - topLayout->addWidget(descriptionEdit); QHBoxLayout *btmLayout = new QHBoxLayout(); btmLayout->addStretch(); @@ -57,8 +49,3 @@ QString VNewFileDialog::getNameInput() const { return nameEdit->text(); } - -QString VNewFileDialog::getDescriptionInput() const -{ - return descriptionEdit->text(); -} diff --git a/src/dialog/vnewfiledialog.h b/src/dialog/vnewfiledialog.h index 393c21ec..8906fb2a 100644 --- a/src/dialog/vnewfiledialog.h +++ b/src/dialog/vnewfiledialog.h @@ -13,9 +13,8 @@ class VNewFileDialog : public QDialog Q_OBJECT public: VNewFileDialog(const QString &title, const QString &name, const QString &defaultName, - const QString &description, const QString &defaultDescription, QWidget *parent = 0); + QWidget *parent = 0); QString getNameInput() const; - QString getDescriptionInput() const; private slots: void enableOkButton(const QString &editText); @@ -24,17 +23,13 @@ private: void setupUI(); QLabel *nameLabel; - QLabel *descriptionLabel; QLineEdit *nameEdit; - QLineEdit *descriptionEdit; QPushButton *okBtn; QPushButton *cancelBtn; QString title; QString name; QString defaultName; - QString description; - QString defaultDescription; }; #endif // VNEWFILEDIALOG_H diff --git a/src/vdirectorytree.cpp b/src/vdirectorytree.cpp index 617dfc8a..7b124482 100644 --- a/src/vdirectorytree.cpp +++ b/src/vdirectorytree.cpp @@ -3,9 +3,10 @@ #include "dialog/vnewdirdialog.h" #include "vconfigmanager.h" #include "dialog/vdirinfodialog.h" +#include "vnote.h" -VDirectoryTree::VDirectoryTree(QWidget *parent) - : QTreeWidget(parent) +VDirectoryTree::VDirectoryTree(VNote *vnote, QWidget *parent) + : QTreeWidget(parent), vnote(vnote) { setColumnCount(1); setHeaderHidden(true); @@ -43,19 +44,26 @@ void VDirectoryTree::initActions() this, &VDirectoryTree::deleteDirectory); } -void VDirectoryTree::setTreePath(const QString& path) +void VDirectoryTree::setNotebook(const QString& notebookName) { - if (path == treePath) { + if (notebook == notebookName) { return; } - treePath = path; - if (path.isEmpty()) { + notebook = notebookName; + treePath = ""; + if (notebook.isEmpty()) { clear(); return; } - - qDebug() << "set directory tree path:" << path; + const QVector ¬ebooks = vnote->getNotebooks(); + for (int i = 0; i < notebooks.size(); ++i) { + if (notebooks[i].getName() == notebook) { + treePath = notebooks[i].getPath(); + break; + } + } + Q_ASSERT(!treePath.isEmpty()); updateDirectoryTree(); if (topLevelItemCount() > 0) { @@ -76,21 +84,15 @@ void VDirectoryTree::updateDirectoryTree() for (int i = 0; i < nrTopLevelItems; ++i) { QTreeWidgetItem *item = topLevelItem(i); Q_ASSERT(item); - updateDirectoryTreeOne(*item, 1); + QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject(); + Q_ASSERT(!itemJson.isEmpty()); + updateDirectoryTreeOne(*item, itemJson["name"].toString(), 1); } } -// QJsonObject stored in each item's data[UserRole]: -// 1. @item's related item in its parent's [sub_directories] section; -// 2. "relative_path": the path where this item exists, relative to the treePath. -void VDirectoryTree::fillDirectoryTreeItem(QTreeWidgetItem &item, QJsonObject itemJson, const QString &relativePath) +void VDirectoryTree::fillDirectoryTreeItem(QTreeWidgetItem &item, QJsonObject itemJson) { item.setText(0, itemJson["name"].toString()); - QString description = itemJson["description"].toString(); - if (!description.isEmpty()) { - item.setToolTip(0, description); - } - itemJson["relative_path"] = relativePath; item.setData(0, Qt::UserRole, itemJson); } @@ -98,30 +100,21 @@ QTreeWidgetItem* VDirectoryTree::insertDirectoryTreeItem(QTreeWidgetItem *parent const QJsonObject &newItem) { QTreeWidgetItem *item; - QString relativePath; if (parent) { if (preceding) { item = new QTreeWidgetItem(parent, preceding); } else { item = new QTreeWidgetItem(parent); } - QJsonObject parentJson = parent->data(0, Qt::UserRole).toJsonObject(); - Q_ASSERT(!parentJson.isEmpty()); - QString parentRelativePath = parentJson["relative_path"].toString(); - QString parentName = parentJson["name"].toString(); - relativePath = QDir(parentRelativePath).filePath(parentName); } else { if (preceding) { item = new QTreeWidgetItem(this, preceding); } else { item = new QTreeWidgetItem(this); } - relativePath = ""; } - fillDirectoryTreeItem(*item, newItem, relativePath); - qDebug() << "insert new Item name:" << newItem["name"].toString() - << "relative_path:" << relativePath; + fillDirectoryTreeItem(*item, newItem); return item; } @@ -169,15 +162,17 @@ void VDirectoryTree::updateDirectoryTreeTopLevel() qDebug() << "updated" << dirJson.size() << "top-level items"; } -void VDirectoryTree::updateDirectoryTreeOne(QTreeWidgetItem &parent, int depth) +void VDirectoryTree::updateDirectoryTreeOne(QTreeWidgetItem &parent, const QString &relativePath, + int depth) { Q_ASSERT(parent.childCount() == 0); // Going deep enough if (depth <= 0) { return; } - QJsonObject parentJson = parent.data(0, Qt::UserRole).toJsonObject(); - QString relativePath = QDir(parentJson["relative_path"].toString()).filePath(parentJson["name"].toString()); + + qDebug() << "update directory" << relativePath; + QString path(QDir::cleanPath(treePath + QDir::separator() + relativePath)); if (!validatePath(path)) { qDebug() << "invalide notebook directory:" << path; @@ -209,24 +204,41 @@ void VDirectoryTree::updateDirectoryTreeOne(QTreeWidgetItem &parent, int depth) preItem = treeItem; // Update its sub-directory recursively - updateDirectoryTreeOne(*treeItem, depth - 1); + updateDirectoryTreeOne(*treeItem, QDir::cleanPath(QDir(relativePath).filePath(dirItem["name"].toString())), depth - 1); } } +QString VDirectoryTree::calculateItemRelativePath(QTreeWidgetItem *item) +{ + if (!item) { + return "."; + } + QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject(); + Q_ASSERT(!itemJson.isEmpty()); + QString name = itemJson["name"].toString(); + Q_ASSERT(!name.isEmpty()); + return QDir::cleanPath(calculateItemRelativePath(item->parent()) + + QDir::separator() + name); +} + void VDirectoryTree::updateItemSubtree(QTreeWidgetItem *item) { QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject(); Q_ASSERT(!itemJson.isEmpty()); + QString relativePath = calculateItemRelativePath(item); int nrChild = item->childCount(); if (nrChild == 0) { - updateDirectoryTreeOne(*item, 2); + updateDirectoryTreeOne(*item, relativePath, 2); } else { for (int i = 0; i < nrChild; ++i) { QTreeWidgetItem *childItem = item->child(i); if (childItem->childCount() > 0) { continue; } - updateDirectoryTreeOne(*childItem, 1); + QJsonObject childJson = childItem->data(0, Qt::UserRole).toJsonObject(); + Q_ASSERT(!childJson.isEmpty()); + updateDirectoryTreeOne(*childItem, + QDir::cleanPath(QDir(relativePath).filePath(childJson["name"].toString())), 1); } } } @@ -264,20 +276,17 @@ void VDirectoryTree::newSiblingDirectory() QString text("&Directory name:"); QString defaultText("new_directory"); - QString defaultDescription(""); do { VNewDirDialog dialog(QString("Create a new directory under %1").arg(parentItemName), text, - defaultText, tr("&Description:"), defaultDescription, this); + defaultText, this); if (dialog.exec() == QDialog::Accepted) { QString name = dialog.getNameInput(); - QString description = dialog.getDescriptionInput(); if (isConflictNameWithChildren(parentItem, name)) { text = "Name already exists.\nPlease choose another name:"; defaultText = name; - defaultDescription = description; continue; } - QTreeWidgetItem *newItem = createDirectoryAndUpdateTree(parentItem, name, description); + QTreeWidgetItem *newItem = createDirectoryAndUpdateTree(parentItem, name); if (newItem) { this->setCurrentItem(newItem); } @@ -297,20 +306,18 @@ void VDirectoryTree::newSubDirectory() QString text("&Directory name:"); QString defaultText("new_directory"); - QString defaultDescription(""); + do { VNewDirDialog dialog(QString("Create a new directory under %1").arg(curItemName), text, - defaultText, tr("&Description:"), defaultDescription, this); + defaultText, this); if (dialog.exec() == QDialog::Accepted) { QString name = dialog.getNameInput(); - QString description = dialog.getDescriptionInput(); if (isConflictNameWithChildren(curItem, name)) { text = "Name already exists.\nPlease choose another name:"; defaultText = name; - defaultDescription = description; continue; } - QTreeWidgetItem *newItem = createDirectoryAndUpdateTree(curItem, name, description); + QTreeWidgetItem *newItem = createDirectoryAndUpdateTree(curItem, name); if (newItem) { this->setCurrentItem(newItem); } @@ -323,20 +330,18 @@ void VDirectoryTree::newRootDirectory() { QString text("&Directory name:"); QString defaultText("new_directory"); - QString defaultDescription(""); + do { VNewDirDialog dialog(tr("Create a new root directory"), text, - defaultText, tr("&Description:"), defaultDescription, this); + defaultText, this); if (dialog.exec() == QDialog::Accepted) { QString name = dialog.getNameInput(); - QString description = dialog.getDescriptionInput(); if (isConflictNameWithChildren(NULL, name)) { text = "Name already exists.\nPlease choose another name:"; defaultText = name; - defaultDescription = description; continue; } - QTreeWidgetItem *newItem = createDirectoryAndUpdateTree(NULL, name, description); + QTreeWidgetItem *newItem = createDirectoryAndUpdateTree(NULL, name); if (newItem) { this->setCurrentItem(newItem); } @@ -364,15 +369,10 @@ void VDirectoryTree::deleteDirectory() } QTreeWidgetItem* VDirectoryTree::createDirectoryAndUpdateTree(QTreeWidgetItem *parent, - const QString &name, const QString &description) + const QString &name) { - QString relativePath(""); - QJsonObject parentJson; - if (parent) { - parentJson = parent->data(0, Qt::UserRole).toJsonObject(); - relativePath = QDir(parentJson["relative_path"].toString()).filePath(parentJson["name"].toString()); - } - QString path = QDir(treePath).filePath(relativePath); + QString relativePath = calculateItemRelativePath(parent); + QString path = QDir::cleanPath(QDir(treePath).filePath(relativePath)); QDir dir(path); if (!dir.mkdir(name)) { qWarning() << "error: fail to create directory" << name << "under" << path; @@ -388,7 +388,7 @@ QTreeWidgetItem* VDirectoryTree::createDirectoryAndUpdateTree(QTreeWidgetItem *p configJson["sub_directories"] = QJsonArray(); configJson["files"] = QJsonArray(); - if (!VConfigManager::writeDirectoryConfig(QDir(path).filePath(name), configJson)) { + if (!VConfigManager::writeDirectoryConfig(QDir::cleanPath(QDir(path).filePath(name)), configJson)) { return NULL; } @@ -397,12 +397,11 @@ QTreeWidgetItem* VDirectoryTree::createDirectoryAndUpdateTree(QTreeWidgetItem *p Q_ASSERT(!configJson.isEmpty()); QJsonObject itemJson; itemJson["name"] = name; - itemJson["description"] = description; QJsonArray subDirArray = configJson["sub_directories"].toArray(); subDirArray.append(itemJson); configJson["sub_directories"] = subDirArray; if (!VConfigManager::writeDirectoryConfig(path, configJson)) { - VConfigManager::deleteDirectoryConfig(QDir(path).filePath(name)); + VConfigManager::deleteDirectoryConfig(QDir::cleanPath(QDir(path).filePath(name))); dir.rmdir(name); return NULL; } @@ -412,12 +411,15 @@ QTreeWidgetItem* VDirectoryTree::createDirectoryAndUpdateTree(QTreeWidgetItem *p void VDirectoryTree::deleteDirectoryAndUpdateTree(QTreeWidgetItem *item) { + if (!item) { + return; + } QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject(); QString itemName = itemJson["name"].toString(); - QString relativePath = itemJson["relative_path"].toString(); + QString parentRelativePath = calculateItemRelativePath(item->parent()); // Update parent's config file to exclude this directory - QString path = QDir(treePath).filePath(relativePath); + QString path = QDir::cleanPath(QDir(treePath).filePath(parentRelativePath)); QJsonObject configJson = VConfigManager::readDirectoryConfig(path); Q_ASSERT(!configJson.isEmpty()); QJsonArray subDirArray = configJson["sub_directories"].toArray(); @@ -441,7 +443,7 @@ void VDirectoryTree::deleteDirectoryAndUpdateTree(QTreeWidgetItem *item) } // Delete the entire directory - QString dirName = QDir(path).filePath(itemName); + QString dirName = QDir::cleanPath(QDir(path).filePath(itemName)); QDir dir(dirName); if (!dir.removeRecursively()) { qWarning() << "error: fail to delete" << dirName << "recursively"; @@ -485,8 +487,8 @@ void VDirectoryTree::currentDirectoryItemChanged(QTreeWidgetItem *currentItem) } QJsonObject itemJson = currentItem->data(0, Qt::UserRole).toJsonObject(); Q_ASSERT(!itemJson.isEmpty()); - itemJson["root_path"] = treePath; - qDebug() << "click dir:" << itemJson; + itemJson["notebook"] = notebook; + itemJson["relative_path"] = calculateItemRelativePath(currentItem); emit currentDirectoryChanged(itemJson); } @@ -498,35 +500,29 @@ void VDirectoryTree::editDirectoryInfo() } QJsonObject curItemJson = curItem->data(0, Qt::UserRole).toJsonObject(); QString curItemName = curItemJson["name"].toString(); - QString curDescription = curItemJson["description"].toString(); QString info; QString defaultName = curItemName; - QString defaultDescription = curDescription; do { - VDirInfoDialog dialog(tr("Directory Information"), info, defaultName, - defaultDescription, this); + VDirInfoDialog dialog(tr("Directory Information"), info, defaultName, this); if (dialog.exec() == QDialog::Accepted) { QString name = dialog.getNameInput(); - QString description = dialog.getDescriptionInput(); - if (name == curItemName && description == curDescription) { + if (name == curItemName) { return; } if (isConflictNameWithChildren(curItem->parent(), name)) { info = "Name already exists.\nPlease choose another name:"; defaultName = name; - defaultDescription = description; continue; } - setDirectoryInfo(curItem, name, description); + renameDirectory(curItem, name); } break; } while (true); } -void VDirectoryTree::setDirectoryInfo(QTreeWidgetItem *item, const QString &newName, - const QString &newDescription) +void VDirectoryTree::renameDirectory(QTreeWidgetItem *item, const QString &newName) { if (!item) { return; @@ -534,14 +530,10 @@ void VDirectoryTree::setDirectoryInfo(QTreeWidgetItem *item, const QString &newN QJsonObject itemJson = item->data(0, Qt::UserRole).toJsonObject(); QString name = itemJson["name"].toString(); - QString relativePath(""); - QJsonObject parentJson; QTreeWidgetItem *parent = item->parent(); - if (parent) { - parentJson = parent->data(0, Qt::UserRole).toJsonObject(); - relativePath = QDir(parentJson["relative_path"].toString()).filePath(parentJson["name"].toString()); - } - QString path = QDir(treePath).filePath(relativePath); + QString parentRelativePath = calculateItemRelativePath(parent); + + QString path = QDir::cleanPath(QDir(treePath).filePath(parentRelativePath)); QDir dir(path); if (!dir.rename(name, newName)) { @@ -562,7 +554,6 @@ void VDirectoryTree::setDirectoryInfo(QTreeWidgetItem *item, const QString &newN QJsonObject tmp = subDirArray[index].toObject(); if (tmp["name"].toString() == name) { tmp["name"] = newName; - tmp["description"] = newDescription; subDirArray[index] = tmp; break; } @@ -576,16 +567,30 @@ void VDirectoryTree::setDirectoryInfo(QTreeWidgetItem *item, const QString &newN // Update item itemJson["name"] = newName; - itemJson["description"] = newDescription; item->setData(0, Qt::UserRole, itemJson); item->setText(0, newName); - item->setToolTip(0, newDescription); - // Reconstruct every child - for (int i = 0; i < item->childCount(); ++i) { - QTreeWidgetItem *tmp = item->child(i); - item->removeChild(tmp); - delete tmp; - } - updateDirectoryTreeOne(*item, 2); + QString oldPath = QDir::cleanPath(QDir(parentRelativePath).filePath(name)); + QString newPath = QDir::cleanPath(QDir(parentRelativePath).filePath(newName)); + qDebug() << "directory renamed" << oldPath << "to" << newPath; + emit directoryRenamed(notebook, oldPath, newPath); +} + +void VDirectoryTree::handleNotebookRenamed(const QVector ¬ebooks, + const QString &oldName, const QString &newName) +{ + if (oldName == notebook) { + // Update treePath (though treePath actually will not be changed) + notebook = newName; + treePath.clear(); + const QVector ¬ebooks = vnote->getNotebooks(); + for (int i = 0; i < notebooks.size(); ++i) { + if (notebooks[i].getName() == notebook) { + treePath = notebooks[i].getPath(); + break; + } + } + Q_ASSERT(!treePath.isEmpty()); + qDebug() << "directoryTree update notebook" << oldName << "to" << newName << "path" << treePath; + } } diff --git a/src/vdirectorytree.h b/src/vdirectorytree.h index a252cad8..19bc3950 100644 --- a/src/vdirectorytree.h +++ b/src/vdirectorytree.h @@ -3,21 +3,28 @@ #include #include +#include "vnotebook.h" + +class VNote; class VDirectoryTree : public QTreeWidget { Q_OBJECT public: - explicit VDirectoryTree(QWidget *parent = 0); + explicit VDirectoryTree(VNote *vnote, QWidget *parent = 0); signals: void currentDirectoryChanged(QJsonObject itemJson); + void directoryRenamed(const QString ¬ebook, const QString &oldRelativePath, + const QString &newRelativePath); public slots: - void setTreePath(const QString& path); + void setNotebook(const QString ¬ebookName); void newRootDirectory(); void deleteDirectory(); void editDirectoryInfo(); + void handleNotebookRenamed(const QVector ¬ebooks, const QString &oldName, + const QString &newName); private slots: // Read config file and pdate the subtree of @item in the directory tree. @@ -31,30 +38,33 @@ private slots: void currentDirectoryItemChanged(QTreeWidgetItem *currentItem); private: + QString calculateItemRelativePath(QTreeWidgetItem *item); // Clean and pdate the TreeWidget according to treePath void updateDirectoryTree(); // Update the top-level items of the directory tree. Will not clean the tree at first. void updateDirectoryTreeTopLevel(); - // Update one directory, going into @depth levels. Not cleaning the tree item at first, - // so you must ensure @parent has no child before calling this function. - void updateDirectoryTreeOne(QTreeWidgetItem &parent, int depth); + + // @relativePath is the relative path of the direcotry we are updating + void updateDirectoryTreeOne(QTreeWidgetItem &parent, const QString &relativePath, int depth); // Validate if a directory is valid bool validatePath(const QString &path); - // Fill the QTreeWidgetItem according to its QJsonObject. - // @relative_path is the path related to treePath. - void fillDirectoryTreeItem(QTreeWidgetItem &item, QJsonObject itemJson, const QString &relativePath); + + void fillDirectoryTreeItem(QTreeWidgetItem &item, QJsonObject itemJson); void initActions(); - QTreeWidgetItem* createDirectoryAndUpdateTree(QTreeWidgetItem *parent, const QString &name, - const QString &description); + QTreeWidgetItem* createDirectoryAndUpdateTree(QTreeWidgetItem *parent, const QString &name); void deleteDirectoryAndUpdateTree(QTreeWidgetItem *item); // If @name conflict with the children's names of @parent. bool isConflictNameWithChildren(const QTreeWidgetItem *parent, const QString &name); + QTreeWidgetItem* insertDirectoryTreeItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding, const QJsonObject &newItem); void removeDirectoryTreeItem(QTreeWidgetItem *item); - void setDirectoryInfo(QTreeWidgetItem *item, const QString &newName, const QString &newDescription); + void renameDirectory(QTreeWidgetItem *item, const QString &newName); - // The path of the directory tree root + VNote *vnote; + + QString notebook; + // Used for cache QString treePath; // Actions diff --git a/src/veditor.cpp b/src/veditor.cpp index 3e82c0b4..dedb013d 100644 --- a/src/veditor.cpp +++ b/src/veditor.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "veditor.h" #include "vedit.h" #include "vdocument.h" @@ -11,16 +12,20 @@ #include "hgmarkdownhighlighter.h" #include "vconfigmanager.h" #include "vmarkdownconverter.h" +#include "vnotebook.h" extern VConfigManager vconfig; -VEditor::VEditor(const QString &path, const QString &name, bool modifiable, - QWidget *parent) +VEditor::VEditor(const QString &path, bool modifiable, QWidget *parent) : QStackedWidget(parent), mdConverterType(vconfig.getMdConverterType()) { - DocType docType = isMarkdown(name) ? DocType::Markdown : DocType::Html; - QString fileText = VUtils::readFileFromDisk(QDir(path).filePath(name)); - noteFile = new VNoteFile(path, name, fileText, docType, modifiable); + DocType docType = isMarkdown(path) ? DocType::Markdown : DocType::Html; + QString basePath = QFileInfo(path).path(); + QString fileName = QFileInfo(path).fileName(); + qDebug() << "VEditor basePath" << basePath << "file" << fileName; + QString fileText = VUtils::readFileFromDisk(path); + noteFile = new VNoteFile(basePath, fileName, fileText, + docType, modifiable); isEditMode = false; @@ -105,7 +110,7 @@ void VEditor::previewByConverter() QString toc = mdConverter.generateToc(content, vconfig.getMarkdownExtensions()); html.replace(tocExp, toc); QString completeHtml = VNote::preTemplateHtml + html + VNote::postTemplateHtml; - webPreviewer->setHtml(completeHtml, QUrl::fromLocalFile(noteFile->path + QDir::separator())); + webPreviewer->setHtml(completeHtml, QUrl::fromLocalFile(noteFile->basePath + QDir::separator())); } void VEditor::showFileEditMode() @@ -171,7 +176,7 @@ bool VEditor::saveFile() return true; } textEditor->saveFile(); - bool ret = VUtils::writeFileToDisk(QDir(noteFile->path).filePath(noteFile->name), + bool ret = VUtils::writeFileToDisk(QDir(noteFile->basePath).filePath(noteFile->fileName), noteFile->content); if (!ret) { QMessageBox msgBox(QMessageBox::Warning, tr("Fail to save to file"), @@ -196,7 +201,8 @@ void VEditor::setupMarkdownPreview() QWebChannel *channel = new QWebChannel(this); channel->registerObject(QStringLiteral("content"), &document); page->setWebChannel(channel); - webPreviewer->setHtml(VNote::templateHtml, QUrl::fromLocalFile(noteFile->path + QDir::separator())); + webPreviewer->setHtml(VNote::templateHtml, + QUrl::fromLocalFile(noteFile->basePath + QDir::separator())); } addWidget(webPreviewer); diff --git a/src/veditor.h b/src/veditor.h index 50c39a71..051423c6 100644 --- a/src/veditor.h +++ b/src/veditor.h @@ -12,12 +12,12 @@ class QTextBrowser; class VEdit; class QWebEngineView; +class VNote; class VEditor : public QStackedWidget { public: - VEditor(const QString &path, const QString &name, bool modifiable, - QWidget *parent = 0); + VEditor(const QString &path, bool modifiable, QWidget *parent = 0); ~VEditor(); bool requestClose(); // Enter edit mode diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index ea633639..3645658b 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -5,8 +5,8 @@ #include "dialog/vnewfiledialog.h" #include "vnote.h" -VFileList::VFileList(QWidget *parent) - : QListWidget(parent) +VFileList::VFileList(VNote *vnote, QWidget *parent) + : QListWidget(parent), vnote(vnote) { setContextMenuPolicy(Qt::CustomContextMenu); initActions(); @@ -37,17 +37,24 @@ void VFileList::setDirectory(QJsonObject dirJson) return; } - directoryName = dirJson["name"].toString(); - rootPath = dirJson["root_path"].toString(); - relativePath = QDir(dirJson["relative_path"].toString()).filePath(directoryName); - qDebug() << "FileList update:" << rootPath << relativePath << directoryName; + notebook = dirJson["notebook"].toString(); + relativePath = dirJson["relative_path"].toString(); + rootPath = ""; + const QVector ¬ebooks = vnote->getNotebooks(); + for (int i = 0; i < notebooks.size(); ++i) { + if (notebooks[i].getName() == notebook) { + rootPath = notebooks[i].getPath(); + break; + } + } + Q_ASSERT(!rootPath.isEmpty()); updateFileList(); } void VFileList::clearDirectoryInfo() { - directoryName = rootPath = relativePath = ""; + notebook = relativePath = rootPath = ""; clear(); } @@ -89,9 +96,6 @@ QListWidgetItem* VFileList::insertFileListItem(QJsonObject fileJson, bool atFron { Q_ASSERT(!fileJson.isEmpty()); QListWidgetItem *item = new QListWidgetItem(fileJson["name"].toString()); - if (!fileJson["description"].toString().isEmpty()) { - item->setToolTip(fileJson["description"].toString()); - } item->setData(Qt::UserRole, fileJson); if (atFront) { @@ -118,20 +122,17 @@ void VFileList::newFile() { QString text("&Note name:"); QString defaultText("new_note"); - QString defaultDescription(""); do { - VNewFileDialog dialog(QString("Create a new note under %1").arg(directoryName), text, - defaultText, tr("&Description:"), defaultDescription, this); + VNewFileDialog dialog(QString("Create a new note under %1").arg(getDirectoryName()), text, + defaultText, this); if (dialog.exec() == QDialog::Accepted) { QString name = dialog.getNameInput(); - QString description = dialog.getDescriptionInput(); if (isConflictNameWithExisting(name)) { text = "Name already exists.\nPlease choose another name:"; defaultText = name; - defaultDescription = description; continue; } - QListWidgetItem *newItem = createFileAndUpdateList(name, description); + QListWidgetItem *newItem = createFileAndUpdateList(name); if (newItem) { setCurrentItem(newItem); // Qt seems not to update the QListWidget correctly. Manually force it to repaint. @@ -140,7 +141,8 @@ void VFileList::newFile() // Open this file in edit mode QJsonObject itemJson = newItem->data(Qt::UserRole).toJsonObject(); Q_ASSERT(!itemJson.isEmpty()); - itemJson["path"] = QDir::cleanPath(QDir(rootPath).filePath(relativePath)); + itemJson["notebook"] = notebook; + itemJson["relative_path"] = QDir::cleanPath(QDir(relativePath).filePath(name)); itemJson["mode"] = OpenFileMode::Edit; emit fileCreated(itemJson); } @@ -164,7 +166,8 @@ void VFileList::deleteFile() msgBox.setDefaultButton(QMessageBox::Ok); if (msgBox.exec() == QMessageBox::Ok) { // First close this file forcely - curItemJson["path"] = QDir::cleanPath(QDir(rootPath).filePath(relativePath)); + curItemJson["notebook"] = notebook; + curItemJson["relative_path"] = QDir::cleanPath(QDir(relativePath).filePath(curItemName)); emit fileDeleted(curItemJson); deleteFileAndUpdateList(curItem); @@ -176,7 +179,7 @@ void VFileList::contextMenuRequested(QPoint pos) QListWidgetItem *item = itemAt(pos); QMenu menu(this); - if (directoryName.isEmpty()) { + if (notebook.isEmpty()) { return; } menu.addAction(newFileAct); @@ -201,8 +204,7 @@ bool VFileList::isConflictNameWithExisting(const QString &name) return false; } -QListWidgetItem* VFileList::createFileAndUpdateList(const QString &name, - const QString &description) +QListWidgetItem* VFileList::createFileAndUpdateList(const QString &name) { QString path = QDir(rootPath).filePath(relativePath); QString filePath = QDir(path).filePath(name); @@ -224,7 +226,6 @@ QListWidgetItem* VFileList::createFileAndUpdateList(const QString &name, Q_ASSERT(!dirJson.isEmpty()); QJsonObject fileJson; fileJson["name"] = name; - fileJson["description"] = description; QJsonArray fileArray = dirJson["files"].toArray(); fileArray.push_front(fileJson); dirJson["files"] = fileArray; @@ -291,7 +292,8 @@ void VFileList::handleItemClicked(QListWidgetItem *currentItem) update(); QJsonObject itemJson = currentItem->data(Qt::UserRole).toJsonObject(); Q_ASSERT(!itemJson.isEmpty()); - itemJson["path"] = QDir::cleanPath(QDir(rootPath).filePath(relativePath)); + itemJson["notebook"] = notebook; + itemJson["relative_path"] = QDir::cleanPath(QDir(relativePath).filePath(itemJson["name"].toString())); itemJson["mode"] = OpenFileMode::Read; emit fileClicked(itemJson); } @@ -324,7 +326,6 @@ bool VFileList::importFile(const QString &name) Q_ASSERT(!dirJson.isEmpty()); QJsonObject fileJson; fileJson["name"] = srcName; - fileJson["description"] = ""; QJsonArray fileArray = dirJson["files"].toArray(); fileArray.push_front(fileJson); dirJson["files"] = fileArray; @@ -337,3 +338,30 @@ bool VFileList::importFile(const QString &name) return insertFileListItem(fileJson, true); } + +void VFileList::handleNotebookRenamed(const QVector ¬ebooks, + const QString &oldName, const QString &newName) +{ + if (oldName == notebook) { + // Update treePath (though treePath actually will not be changed) + notebook = newName; + rootPath.clear(); + const QVector ¬ebooks = vnote->getNotebooks(); + for (int i = 0; i < notebooks.size(); ++i) { + if (notebooks[i].getName() == notebook) { + rootPath = notebooks[i].getPath(); + break; + } + } + Q_ASSERT(!rootPath.isEmpty()); + } +} + +void VFileList::handleDirectoryRenamed(const QString ¬ebook, + const QString &oldRelativePath, const QString &newRelativePath) +{ + if (notebook == this->notebook + && oldRelativePath == relativePath) { + relativePath = newRelativePath; + } +} diff --git a/src/vfilelist.h b/src/vfilelist.h index 8d33d076..ee0676ea 100644 --- a/src/vfilelist.h +++ b/src/vfilelist.h @@ -3,14 +3,18 @@ #include #include +#include +#include +#include "vnotebook.h" class QAction; +class VNote; class VFileList : public QListWidget { Q_OBJECT public: - explicit VFileList(QWidget *parent = 0); + explicit VFileList(VNote *vnote, QWidget *parent = 0); bool importFile(const QString &name); signals: @@ -26,6 +30,10 @@ private slots: public slots: void setDirectory(QJsonObject dirJson); + void handleNotebookRenamed(const QVector ¬ebooks, const QString &oldName, + const QString &newName); + void handleDirectoryRenamed(const QString ¬ebook, const QString &oldRelativePath, + const QString &newRelativePath); private: void updateFileList(); @@ -33,18 +41,29 @@ private: void removeFileListItem(QListWidgetItem *item); void initActions(); bool isConflictNameWithExisting(const QString &name); - QListWidgetItem *createFileAndUpdateList(const QString &name, - const QString &description); + QListWidgetItem *createFileAndUpdateList(const QString &name); void deleteFileAndUpdateList(QListWidgetItem *item); void clearDirectoryInfo(); + inline QString getDirectoryName(); - QString rootPath; + VNote *vnote; + QString notebook; + // Current directory's relative path QString relativePath; - QString directoryName; + // Used for cache + QString rootPath; // Actions QAction *newFileAct; QAction *deleteFileAct; }; +inline QString VFileList::getDirectoryName() +{ + if (relativePath.isEmpty()) { + return ""; + } + return QFileInfo(QDir::cleanPath(relativePath)).fileName(); +} + #endif // VFILELIST_H diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index 146ee79a..152ea528 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -11,7 +11,7 @@ extern VConfigManager vconfig; VMainWindow::VMainWindow(QWidget *parent) - : QMainWindow(parent) + : QMainWindow(parent), notebookComboMuted(false) { // Must be called before those who uses VConfigManager vnote = new VNote(); @@ -50,7 +50,7 @@ void VMainWindow::setupUI() notebookComboBox = new QComboBox(); notebookComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); - directoryTree = new VDirectoryTree(); + directoryTree = new VDirectoryTree(vnote); QHBoxLayout *nbBtnLayout = new QHBoxLayout; nbBtnLayout->addWidget(notebookLabel); @@ -74,11 +74,11 @@ void VMainWindow::setupUI() nbContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); // File list widget - fileList = new VFileList(); + fileList = new VFileList(vnote); fileList->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); // Editor tab widget - tabs = new VTabWidget(); + tabs = new VTabWidget(vnote); tabs->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); tabs->setTabBarAutoHide(true); @@ -94,24 +94,41 @@ void VMainWindow::setupUI() // Signals connect(notebookComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurNotebookIndex(int))); - connect(this, SIGNAL(curNotebookIndexChanged(const QString&)), directoryTree, - SLOT(setTreePath(const QString&))); + + connect(vnote, &VNote::notebooksRenamed, + fileList, &VFileList::handleNotebookRenamed); connect(directoryTree, &VDirectoryTree::currentDirectoryChanged, fileList, &VFileList::setDirectory); + connect(directoryTree, &VDirectoryTree::directoryRenamed, + fileList, &VFileList::handleDirectoryRenamed); + connect(fileList, &VFileList::fileClicked, tabs, &VTabWidget::openFile); connect(fileList, &VFileList::fileDeleted, tabs, &VTabWidget::closeFile); connect(fileList, &VFileList::fileCreated, tabs, &VTabWidget::openFile); + connect(newNotebookBtn, &QPushButton::clicked, this, &VMainWindow::onNewNotebookBtnClicked); connect(deleteNotebookBtn, &QPushButton::clicked, this, &VMainWindow::onDeleteNotebookBtnClicked); connect(notebookInfoBtn, &QPushButton::clicked, this, &VMainWindow::onNotebookInfoBtnClicked); + connect(vnote, &VNote::notebooksChanged, this, &VMainWindow::updateNotebookComboBox); + connect(vnote, &VNote::notebooksDeleted, + this, &VMainWindow::notebookComboBoxDeleted); + connect(vnote, &VNote::notebooksRenamed, + this, &VMainWindow::notebookComboBoxRenamed); + connect(vnote, &VNote::notebooksAdded, + this, &VMainWindow::notebookComboBoxAdded); + + connect(this, &VMainWindow::curNotebookChanged, + directoryTree, &VDirectoryTree::setNotebook); + connect(vnote, &VNote::notebooksRenamed, + directoryTree, &VDirectoryTree::handleNotebookRenamed); connect(newRootDirBtn, &QPushButton::clicked, directoryTree, &VDirectoryTree::newRootDirectory); connect(deleteDirBtn, &QPushButton::clicked, @@ -207,38 +224,87 @@ void VMainWindow::initMenuBar() 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(); + notebookComboMuted = true; notebookComboBox->clear(); - if (notebooks.isEmpty()) { - return; - } - for (int i = 0; i addItem(notebooks[i].getName()); } + notebookComboMuted = false; - qDebug() << "update notebook combobox with" << notebookComboBox->count() - << "items, current notebook" << curIndex; - notebookComboBox->setCurrentIndex(curIndex); + int index = vconfig.getCurNotebookIndex(); + if (notebooks.isEmpty()) { + index = -1; + } + if (notebookComboBox->currentIndex() == index) { + setCurNotebookIndex(index); + } else { + notebookComboBox->setCurrentIndex(index); + } } +void VMainWindow::notebookComboBoxAdded(const QVector ¬ebooks, int idx) +{ + notebookComboMuted = true; + notebookComboBox->insertItem(idx, notebooks[idx].getName()); + notebookComboMuted = false; + if (notebookComboBox->currentIndex() == vconfig.getCurNotebookIndex()) { + setCurNotebookIndex(vconfig.getCurNotebookIndex()); + } else { + notebookComboBox->setCurrentIndex(vconfig.getCurNotebookIndex()); + } +} + +void VMainWindow::notebookComboBoxDeleted(const QVector ¬ebooks, const QString &deletedName) +{ + notebookComboMuted = true; + int nrItem = notebookComboBox->count(); + for (int i = 0; i < nrItem; ++i) { + if (notebookComboBox->itemText(i) == deletedName) { + notebookComboBox->removeItem(i); + break; + } + } + notebookComboMuted = false; + + if (notebookComboBox->currentIndex() == vconfig.getCurNotebookIndex()) { + setCurNotebookIndex(vconfig.getCurNotebookIndex()); + } else { + notebookComboBox->setCurrentIndex(vconfig.getCurNotebookIndex()); + } + Q_ASSERT(notebooks.size() == notebookComboBox->count()); +} + +void VMainWindow::notebookComboBoxRenamed(const QVector ¬ebooks, + const QString &oldName, const QString &newName) +{ + int nrItem = notebookComboBox->count(); + for (int i = 0; i < nrItem; ++i) { + if (notebookComboBox->itemText(i) == oldName) { + notebookComboBox->setItemText(i, newName); + break; + } + } + // 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 - QString treePath; + QString notebook; if (index > -1) { vconfig.setCurNotebookIndex(index); - treePath = vnote->getNotebooks()[index].getPath(); + notebook = vnote->getNotebooks()[index].getName(); } - emit curNotebookIndexChanged(treePath); + emit curNotebookChanged(notebook); } void VMainWindow::onNewNotebookBtnClicked() { - qDebug() << "request to create a notebook"; QString info; QString defaultName("new_notebook"); QString defaultPath; diff --git a/src/vmainwindow.h b/src/vmainwindow.h index 3afba7f7..7478b060 100644 --- a/src/vmainwindow.h +++ b/src/vmainwindow.h @@ -27,19 +27,22 @@ public: ~VMainWindow(); private slots: - // Change current notebook index and update the directory tree void setCurNotebookIndex(int index); // Create a notebook void onNewNotebookBtnClicked(); void onDeleteNotebookBtnClicked(); void onNotebookInfoBtnClicked(); void updateNotebookComboBox(const QVector ¬ebooks); + void notebookComboBoxAdded(const QVector ¬ebooks, int idx); + void notebookComboBoxDeleted(const QVector ¬ebooks, const QString &deletedName); + void notebookComboBoxRenamed(const QVector ¬ebooks, + const QString &oldName, const QString &newName); void importNoteFromFile(); void changeMarkdownConverter(QAction *action); void aboutMessage(); signals: - void curNotebookIndexChanged(const QString &path); + void curNotebookChanged(const QString ¬ebookName); private: void setupUI(); @@ -48,6 +51,9 @@ private: void initMenuBar(); bool isConflictWithExistingNotebooks(const QString &name); + // If true, comboBox changes will not trigger any signal out + bool notebookComboMuted; + QLabel *notebookLabel; QLabel *directoryLabel; QComboBox *notebookComboBox; diff --git a/src/vnote.cpp b/src/vnote.cpp index 50b4fd54..484f275b 100644 --- a/src/vnote.cpp +++ b/src/vnote.cpp @@ -46,7 +46,6 @@ 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)) { @@ -60,13 +59,14 @@ void VNote::createNotebook(const QString &name, const QString &path) // Set current index to the new notebook vconfig.setCurNotebookIndex(0); - emit notebooksChanged(notebooks); + emit notebooksAdded(notebooks, 0); } void VNote::removeNotebook(const QString &name) { // Update notebooks settings QString path; + int curIndex = vconfig.getCurNotebookIndex(); int index; for (index = 0; index < notebooks.size(); ++index) { if (notebooks[index].getName() == name) { @@ -79,7 +79,11 @@ void VNote::removeNotebook(const QString &name) } notebooks.remove(index); vconfig.setNotebooks(notebooks); - vconfig.setCurNotebookIndex(notebooks.isEmpty() ? -1 : 0); + if (notebooks.isEmpty()) { + vconfig.setCurNotebookIndex(-1); + } else if (index == curIndex) { + vconfig.setCurNotebookIndex(0); + } // Delete the directory QDir dir(path); @@ -88,7 +92,7 @@ void VNote::removeNotebook(const QString &name) } else { qDebug() << "delete" << path << "recursively"; } - emit notebooksChanged(notebooks); + emit notebooksDeleted(notebooks, name); } void VNote::renameNotebook(const QString &name, const QString &newName) @@ -108,5 +112,5 @@ void VNote::renameNotebook(const QString &name, const QString &newName) notebooks[index].setName(newName); vconfig.setNotebooks(notebooks); - emit notebooksChanged(notebooks); + emit notebooksRenamed(notebooks, name, newName); } diff --git a/src/vnote.h b/src/vnote.h index 56c826f0..319c7401 100644 --- a/src/vnote.h +++ b/src/vnote.h @@ -32,7 +32,12 @@ public: void renameNotebook(const QString &name, const QString &newName); signals: + // Force to do a fully update void notebooksChanged(const QVector ¬ebooks); + void notebooksAdded(const QVector ¬ebooks, int idx); + void notebooksDeleted(const QVector ¬ebooks, const QString &deletedName); + void notebooksRenamed(const QVector ¬ebooks, + const QString &oldName, const QString &newName); private: QVector notebooks; diff --git a/src/vnotefile.cpp b/src/vnotefile.cpp index 21d2888a..7dd44312 100644 --- a/src/vnotefile.cpp +++ b/src/vnotefile.cpp @@ -1,9 +1,9 @@ #include "vnotefile.h" -VNoteFile::VNoteFile(const QString &path, const QString &name, +VNoteFile::VNoteFile(const QString &basePath, const QString &fileName, const QString &content, DocType docType, bool modifiable) - : path(path), name(name), content(content), docType(docType), - modifiable(modifiable) + : basePath(basePath), fileName(fileName), + content(content), docType(docType), modifiable(modifiable) { } diff --git a/src/vnotefile.h b/src/vnotefile.h index afc93b04..693c87f4 100644 --- a/src/vnotefile.h +++ b/src/vnotefile.h @@ -7,11 +7,11 @@ class VNoteFile { public: - VNoteFile(const QString &path, const QString &name, const QString &content, + VNoteFile(const QString &basePath, const QString &fileName, const QString &content, DocType docType, bool modifiable); - QString path; - QString name; + QString basePath; + QString fileName; QString content; DocType docType; bool modifiable; diff --git a/src/vtabwidget.cpp b/src/vtabwidget.cpp index 94cea20b..9ec870d7 100644 --- a/src/vtabwidget.cpp +++ b/src/vtabwidget.cpp @@ -7,8 +7,8 @@ extern VConfigManager vconfig; -VTabWidget::VTabWidget(QWidget *parent) - : QTabWidget(parent) +VTabWidget::VTabWidget(VNote *vnote, QWidget *parent) + : QTabWidget(parent), vnote(vnote) { setTabsClosable(true); setMovable(true); @@ -20,24 +20,25 @@ VTabWidget::VTabWidget(QWidget *parent) void VTabWidget::openWelcomePage() { - int idx = openFileInTab(vconfig.getWelcomePagePath(), "", false); + int idx = openFileInTab("", vconfig.getWelcomePagePath(), false); setTabText(idx, "Welcome to VNote"); setTabToolTip(idx, "VNote"); } -int VTabWidget::insertTabWithData(int index, QWidget *page, const QString &label, +int VTabWidget::insertTabWithData(int index, QWidget *page, const QJsonObject &tabData) { + QString label = getFileName(tabData["relative_path"].toString()); int idx = insertTab(index, page, label); QTabBar *tabs = tabBar(); tabs->setTabData(idx, tabData); - Q_ASSERT(tabs->tabText(idx) == label); + return idx; } -int VTabWidget::appendTabWithData(QWidget *page, const QString &label, const QJsonObject &tabData) +int VTabWidget::appendTabWithData(QWidget *page, const QJsonObject &tabData) { - return insertTabWithData(count(), page, label, tabData); + return insertTabWithData(count(), page, tabData); } void VTabWidget::openFile(QJsonObject fileJson) @@ -45,22 +46,23 @@ void VTabWidget::openFile(QJsonObject fileJson) if (fileJson.isEmpty()) { return; } - qDebug() << "open file:" << fileJson; - QString path = fileJson["path"].toString(); - QString name = fileJson["name"].toString(); + QString notebook = fileJson["notebook"].toString(); + QString relativePath = fileJson["relative_path"].toString(); int mode = OpenFileMode::Read; if (fileJson.contains("mode")) { mode = fileJson["mode"].toInt(); } + qDebug() << "open notebook[" << notebook << "] path[" << relativePath << "]" << mode; + // Find if it has been opened already - int idx = findTabByFile(path, name); + int idx = findTabByFile(notebook, relativePath); if (idx > -1) { goto out; } - idx = openFileInTab(path, name, true); + idx = openFileInTab(notebook, relativePath, true); out: setCurrentIndex(idx); @@ -78,11 +80,11 @@ void VTabWidget::closeFile(QJsonObject fileJson) } qDebug() << "close file:" << fileJson; - QString path = fileJson["path"].toString(); - QString name = fileJson["name"].toString(); + QString notebook = fileJson["notebook"].toString(); + QString relativePath = fileJson["relative_path"].toString(); // Find if it has been opened already - int idx = findTabByFile(path, name); + int idx = findTabByFile(notebook, relativePath); if (idx == -1) { return; } @@ -93,25 +95,34 @@ void VTabWidget::closeFile(QJsonObject fileJson) delete page; } -int VTabWidget::openFileInTab(const QString &path, const QString &name, bool modifiable) +int VTabWidget::openFileInTab(const QString ¬ebook, const QString &relativePath, + bool modifiable) { - VEditor *editor = new VEditor(path, name, modifiable); + QString rootPath; + const QVector ¬ebooks = vnote->getNotebooks(); + for (int i = 0; i < notebooks.size(); ++i) { + if (notebooks[i].getName() == notebook) { + rootPath = notebooks[i].getPath(); + break; + } + } + + VEditor *editor = new VEditor(QDir::cleanPath(QDir(rootPath).filePath(relativePath)), + modifiable); QJsonObject tabJson; - tabJson["path"] = path; - tabJson["name"] = name; - int idx = appendTabWithData(editor, name, tabJson); - setTabToolTip(idx, path); - return idx; + tabJson["notebook"] = notebook; + tabJson["relative_path"] = relativePath; + return appendTabWithData(editor, tabJson); } -int VTabWidget::findTabByFile(const QString &path, const QString &name) +int VTabWidget::findTabByFile(const QString ¬ebook, const QString &relativePath) const { QTabBar *tabs = tabBar(); int nrTabs = tabs->count(); for (int i = 0; i < nrTabs; ++i) { QJsonObject tabJson = tabs->tabData(i).toJsonObject(); - if (tabJson["name"] == name && tabJson["path"] == path) { + if (tabJson["notebook"] == notebook && tabJson["relative_path"] == relativePath) { return i; } } diff --git a/src/vtabwidget.h b/src/vtabwidget.h index 60523763..a4268763 100644 --- a/src/vtabwidget.h +++ b/src/vtabwidget.h @@ -4,12 +4,16 @@ #include #include #include +#include +#include + +class VNote; class VTabWidget : public QTabWidget { Q_OBJECT public: - explicit VTabWidget(QWidget *parent = 0); + explicit VTabWidget(VNote *vnote, QWidget *parent = 0); signals: @@ -26,10 +30,18 @@ private slots: private: void openWelcomePage(); - int insertTabWithData(int index, QWidget *page, const QString &label, const QJsonObject &tabData); - int appendTabWithData(QWidget *page, const QString &label, const QJsonObject &tabData); - int findTabByFile(const QString &path, const QString &name); - int openFileInTab(const QString &path, const QString &name, bool modifiable); + int insertTabWithData(int index, QWidget *page, const QJsonObject &tabData); + int appendTabWithData(QWidget *page, const QJsonObject &tabData); + int findTabByFile(const QString ¬ebook, const QString &relativePath) const; + int openFileInTab(const QString ¬ebook, const QString &relativePath, bool modifiable); + inline QString getFileName(const QString &relativePath) const; + + VNote *vnote; }; +inline QString VTabWidget::getFileName(const QString &path) const +{ + return QFileInfo(QDir::cleanPath(path)).fileName(); +} + #endif // VTABWIDGET_H