diff --git a/src/dialog/vdirinfodialog.cpp b/src/dialog/vdirinfodialog.cpp new file mode 100644 index 00000000..c6a9907b --- /dev/null +++ b/src/dialog/vdirinfodialog.cpp @@ -0,0 +1,72 @@ +#include +#include "vdirinfodialog.h" + +VDirInfoDialog::VDirInfoDialog(const QString &title, const QString &info, + const QString &defaultName, const QString &defaultDescription, + QWidget *parent) + : QDialog(parent), infoLabel(NULL), title(title), info(info), defaultName(defaultName), + defaultDescription(defaultDescription) +{ + setupUI(); + + connect(nameEdit, &QLineEdit::textChanged, this, &VDirInfoDialog::enableOkButton); + connect(okBtn, &QPushButton::clicked, this, &VDirInfoDialog::accept); + connect(cancelBtn, &QPushButton::clicked, this, &VDirInfoDialog::reject); + + enableOkButton(); +} + +void VDirInfoDialog::setupUI() +{ + if (!info.isEmpty()) { + infoLabel = new QLabel(info); + } + nameLabel = new QLabel(tr("&Name")); + nameEdit = new QLineEdit(defaultName); + 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")); + + QVBoxLayout *topLayout = new QVBoxLayout(); + if (infoLabel) { + topLayout->addWidget(infoLabel); + } + topLayout->addWidget(nameLabel); + topLayout->addWidget(nameEdit); + topLayout->addWidget(descriptionLabel); + topLayout->addWidget(descriptionEdit); + + QHBoxLayout *btmLayout = new QHBoxLayout(); + btmLayout->addStretch(); + btmLayout->addWidget(okBtn); + btmLayout->addWidget(cancelBtn); + + QVBoxLayout *mainLayout = new QVBoxLayout(); + mainLayout->addLayout(topLayout); + mainLayout->addLayout(btmLayout); + setLayout(mainLayout); + + setWindowTitle(title); +} + +void VDirInfoDialog::enableOkButton() +{ + okBtn->setEnabled(!nameEdit->text().isEmpty()); +} + +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 new file mode 100644 index 00000000..07a248f8 --- /dev/null +++ b/src/dialog/vdirinfodialog.h @@ -0,0 +1,38 @@ +#ifndef VDIRINFODIALOG_H +#define VDIRINFODIALOG_H + +#include + +class QLabel; +class QLineEdit; +class QPushButton; +class QString; + +class VDirInfoDialog : public QDialog +{ + Q_OBJECT +public: + VDirInfoDialog(const QString &title, const QString &info, const QString &defaultName, + const QString &defaultDescription, QWidget *parent = 0); + QString getNameInput() const; + QString getDescriptionInput() const; + +private slots: + void enableOkButton(); + +private: + void setupUI(); + + 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/src.pro b/src/src.pro index 486f74b9..67f36a91 100644 --- a/src/src.pro +++ b/src/src.pro @@ -34,7 +34,8 @@ SOURCES += main.cpp\ utils/peg-highlight/pmh_styleparser.c \ dialog/vnewnotebookdialog.cpp \ vmarkdownconverter.cpp \ - dialog/vnotebookinfodialog.cpp + dialog/vnotebookinfodialog.cpp \ + dialog/vdirinfodialog.cpp HEADERS += vmainwindow.h \ vdirectorytree.h \ @@ -59,7 +60,8 @@ HEADERS += vmainwindow.h \ utils/peg-highlight/pmh_styleparser.h \ dialog/vnewnotebookdialog.h \ vmarkdownconverter.h \ - dialog/vnotebookinfodialog.h + dialog/vnotebookinfodialog.h \ + dialog/vdirinfodialog.h RESOURCES += \ vnote.qrc diff --git a/src/vdirectorytree.cpp b/src/vdirectorytree.cpp index a218d5e2..617dfc8a 100644 --- a/src/vdirectorytree.cpp +++ b/src/vdirectorytree.cpp @@ -2,6 +2,7 @@ #include "vdirectorytree.h" #include "dialog/vnewdirdialog.h" #include "vconfigmanager.h" +#include "dialog/vdirinfodialog.h" VDirectoryTree::VDirectoryTree(QWidget *parent) : QTreeWidget(parent) @@ -288,6 +289,9 @@ void VDirectoryTree::newSiblingDirectory() void VDirectoryTree::newSubDirectory() { QTreeWidgetItem *curItem = currentItem(); + if (!curItem) { + return; + } QJsonObject curItemJson = curItem->data(0, Qt::UserRole).toJsonObject(); QString curItemName = curItemJson["name"].toString(); @@ -344,6 +348,9 @@ void VDirectoryTree::newRootDirectory() void VDirectoryTree::deleteDirectory() { QTreeWidgetItem *curItem = currentItem(); + if (!curItem) { + return; + } QJsonObject curItemJson = curItem->data(0, Qt::UserRole).toJsonObject(); QString curItemName = curItemJson["name"].toString(); @@ -482,3 +489,103 @@ void VDirectoryTree::currentDirectoryItemChanged(QTreeWidgetItem *currentItem) qDebug() << "click dir:" << itemJson; emit currentDirectoryChanged(itemJson); } + +void VDirectoryTree::editDirectoryInfo() +{ + QTreeWidgetItem *curItem = currentItem(); + if (!curItem) { + return; + } + 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); + if (dialog.exec() == QDialog::Accepted) { + QString name = dialog.getNameInput(); + QString description = dialog.getDescriptionInput(); + if (name == curItemName && description == curDescription) { + return; + } + if (isConflictNameWithChildren(curItem->parent(), name)) { + info = "Name already exists.\nPlease choose another name:"; + defaultName = name; + defaultDescription = description; + continue; + } + setDirectoryInfo(curItem, name, description); + } + break; + } while (true); +} + +void VDirectoryTree::setDirectoryInfo(QTreeWidgetItem *item, const QString &newName, + const QString &newDescription) +{ + if (!item) { + return; + } + 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); + QDir dir(path); + + if (!dir.rename(name, newName)) { + qWarning() << "error: fail to rename directory" << name << "under" << path; + QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Could not rename directory \"%1\" under \"%2\".") + .arg(name).arg(path), QMessageBox::Ok, this); + msgBox.setInformativeText(QString("Please check if there already exists a directory named \"%1\".").arg(name)); + msgBox.exec(); + return; + } + + // Update parent's config file + QJsonObject configJson = VConfigManager::readDirectoryConfig(path); + Q_ASSERT(!configJson.isEmpty()); + QJsonArray subDirArray = configJson["sub_directories"].toArray(); + int index = 0; + for (index = 0; index < subDirArray.size(); ++index) { + QJsonObject tmp = subDirArray[index].toObject(); + if (tmp["name"].toString() == name) { + tmp["name"] = newName; + tmp["description"] = newDescription; + subDirArray[index] = tmp; + break; + } + } + Q_ASSERT(index != subDirArray.size()); + configJson["sub_directories"] = subDirArray; + if (!VConfigManager::writeDirectoryConfig(path, configJson)) { + dir.rename(newName, name); + return; + } + + // 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); +} diff --git a/src/vdirectorytree.h b/src/vdirectorytree.h index 627a794d..a252cad8 100644 --- a/src/vdirectorytree.h +++ b/src/vdirectorytree.h @@ -15,6 +15,9 @@ signals: public slots: void setTreePath(const QString& path); + void newRootDirectory(); + void deleteDirectory(); + void editDirectoryInfo(); private slots: // Read config file and pdate the subtree of @item in the directory tree. @@ -25,8 +28,6 @@ private slots: void contextMenuRequested(QPoint pos); void newSiblingDirectory(); void newSubDirectory(); - void newRootDirectory(); - void deleteDirectory(); void currentDirectoryItemChanged(QTreeWidgetItem *currentItem); private: @@ -51,6 +52,7 @@ private: QTreeWidgetItem* insertDirectoryTreeItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding, const QJsonObject &newItem); void removeDirectoryTreeItem(QTreeWidgetItem *item); + void setDirectoryInfo(QTreeWidgetItem *item, const QString &newName, const QString &newDescription); // The path of the directory tree root QString treePath; diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index 5c833bdb..146ee79a 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -112,6 +112,12 @@ void VMainWindow::setupUI() this, &VMainWindow::onNotebookInfoBtnClicked); connect(vnote, &VNote::notebooksChanged, this, &VMainWindow::updateNotebookComboBox); + connect(newRootDirBtn, &QPushButton::clicked, + directoryTree, &VDirectoryTree::newRootDirectory); + connect(deleteDirBtn, &QPushButton::clicked, + directoryTree, &VDirectoryTree::deleteDirectory); + connect(dirInfoBtn, &QPushButton::clicked, + directoryTree, &VDirectoryTree::editDirectoryInfo); setCentralWidget(mainSplitter); // Create and show the status bar