mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
refactor directory and file related logics
Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
parent
51d0eedcb2
commit
5409ce9769
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<VNotebook> ¬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;
|
||||
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<VNotebook> ¬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<VNotebook> ¬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;
|
||||
}
|
||||
updateDirectoryTreeOne(*item, 2);
|
||||
}
|
||||
|
@ -3,21 +3,28 @@
|
||||
|
||||
#include <QTreeWidget>
|
||||
#include <QJsonObject>
|
||||
#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<VNotebook> ¬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
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <QTextBrowser>
|
||||
#include <QWebChannel>
|
||||
#include <QWebEngineView>
|
||||
#include <QFileInfo>
|
||||
#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);
|
||||
|
@ -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
|
||||
|
@ -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<VNotebook> ¬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<VNotebook> ¬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<VNotebook> ¬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;
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,18 @@
|
||||
|
||||
#include <QListWidget>
|
||||
#include <QJsonObject>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#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<VNotebook> ¬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
|
||||
|
@ -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<VNotebook> ¬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 < notebooks.size(); ++i) {
|
||||
notebookComboBox->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<VNotebook> ¬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<VNotebook> ¬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<VNotebook> ¬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;
|
||||
|
@ -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<VNotebook> ¬ebooks);
|
||||
void notebookComboBoxAdded(const QVector<VNotebook> ¬ebooks, int idx);
|
||||
void notebookComboBoxDeleted(const QVector<VNotebook> ¬ebooks, const QString &deletedName);
|
||||
void notebookComboBoxRenamed(const QVector<VNotebook> ¬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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -32,7 +32,12 @@ public:
|
||||
void renameNotebook(const QString &name, const QString &newName);
|
||||
|
||||
signals:
|
||||
// Force to do a fully update
|
||||
void notebooksChanged(const QVector<VNotebook> ¬ebooks);
|
||||
void notebooksAdded(const QVector<VNotebook> ¬ebooks, int idx);
|
||||
void notebooksDeleted(const QVector<VNotebook> ¬ebooks, const QString &deletedName);
|
||||
void notebooksRenamed(const QVector<VNotebook> ¬ebooks,
|
||||
const QString &oldName, const QString &newName);
|
||||
|
||||
private:
|
||||
QVector<VNotebook> notebooks;
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
QJsonObject tabJson;
|
||||
tabJson["path"] = path;
|
||||
tabJson["name"] = name;
|
||||
int idx = appendTabWithData(editor, name, tabJson);
|
||||
setTabToolTip(idx, path);
|
||||
return idx;
|
||||
QString rootPath;
|
||||
const QVector<VNotebook> ¬ebooks = vnote->getNotebooks();
|
||||
for (int i = 0; i < notebooks.size(); ++i) {
|
||||
if (notebooks[i].getName() == notebook) {
|
||||
rootPath = notebooks[i].getPath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int VTabWidget::findTabByFile(const QString &path, const QString &name)
|
||||
VEditor *editor = new VEditor(QDir::cleanPath(QDir(rootPath).filePath(relativePath)),
|
||||
modifiable);
|
||||
QJsonObject tabJson;
|
||||
tabJson["notebook"] = notebook;
|
||||
tabJson["relative_path"] = relativePath;
|
||||
return appendTabWithData(editor, tabJson);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,16 @@
|
||||
#include <QTabWidget>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user