refactor directory and file related logics

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-10-25 22:25:34 +08:00
parent 51d0eedcb2
commit 5409ce9769
20 changed files with 386 additions and 265 deletions

View File

@ -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();
}

View File

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

View File

@ -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();
}

View File

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

View File

@ -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();
}

View File

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

View File

@ -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> &notebooks = 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> &notebooks,
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> &notebooks = 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);
}

View File

@ -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 &notebook, const QString &oldRelativePath,
const QString &newRelativePath);
public slots:
void setTreePath(const QString& path);
void setNotebook(const QString &notebookName);
void newRootDirectory();
void deleteDirectory();
void editDirectoryInfo();
void handleNotebookRenamed(const QVector<VNotebook> &notebooks, 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

View File

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

View File

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

View File

@ -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> &notebooks = 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> &notebooks,
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> &notebooks = 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 &notebook,
const QString &oldRelativePath, const QString &newRelativePath)
{
if (notebook == this->notebook
&& oldRelativePath == relativePath) {
relativePath = newRelativePath;
}
}

View File

@ -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> &notebooks, const QString &oldName,
const QString &newName);
void handleDirectoryRenamed(const QString &notebook, 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

View File

@ -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> &notebooks)
{
// Clearing and inserting items will emit the signal which corrupt the vconfig's
// current index. We save it first and then set the combobox index to the
// right one to resrote it.
int curIndex = vconfig.getCurNotebookIndex();
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> &notebooks, 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> &notebooks, 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> &notebooks,
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;

View File

@ -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> &notebooks);
void notebookComboBoxAdded(const QVector<VNotebook> &notebooks, int idx);
void notebookComboBoxDeleted(const QVector<VNotebook> &notebooks, const QString &deletedName);
void notebookComboBoxRenamed(const QVector<VNotebook> &notebooks,
const QString &oldName, const QString &newName);
void importNoteFromFile();
void changeMarkdownConverter(QAction *action);
void aboutMessage();
signals:
void curNotebookIndexChanged(const QString &path);
void curNotebookChanged(const QString &notebookName);
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;

View File

@ -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);
}

View File

@ -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> &notebooks);
void notebooksAdded(const QVector<VNotebook> &notebooks, int idx);
void notebooksDeleted(const QVector<VNotebook> &notebooks, const QString &deletedName);
void notebooksRenamed(const QVector<VNotebook> &notebooks,
const QString &oldName, const QString &newName);
private:
QVector<VNotebook> notebooks;

View File

@ -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)
{
}

View File

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

View File

@ -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 &notebook, 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> &notebooks = 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 &notebook, 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;
}
}

View File

@ -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 &notebook, const QString &relativePath) const;
int openFileInTab(const QString &notebook, 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