mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
complete rename logics
1. Handle directory rename correctly; 2. Handle file rename correctly; Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
parent
5e97ca8060
commit
62c75427e7
@ -91,3 +91,20 @@ void VUtils::processStyle(QString &style)
|
||||
style.replace("@" + map.first, map.second);
|
||||
}
|
||||
}
|
||||
|
||||
bool VUtils::isMarkdown(const QString &name)
|
||||
{
|
||||
const QVector<QString> mdPostfix({"md", "markdown", "mkd"});
|
||||
|
||||
QStringList list = name.split('.', QString::SkipEmptyParts);
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
const QString &postfix = list.last();
|
||||
for (int i = 0; i < mdPostfix.size(); ++i) {
|
||||
if (postfix == mdPostfix[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
static QString generateImageFileName(const QString &path, const QString &title,
|
||||
const QString &format = "png");
|
||||
static void processStyle(QString &style);
|
||||
static bool isMarkdown(const QString &fileName);
|
||||
private:
|
||||
static inline void addQssVarToMap(QVector<QPair<QString, QString> > &map,
|
||||
const QString &key, const QString &value);
|
||||
|
@ -178,19 +178,22 @@ void VEditArea::updateWindowStatus()
|
||||
win->requestUpdateCurHeader();
|
||||
}
|
||||
|
||||
void VEditArea::closeFile(QJsonObject fileJson)
|
||||
bool VEditArea::closeFile(QJsonObject fileJson)
|
||||
{
|
||||
if (fileJson.isEmpty()) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
QString notebook = fileJson["notebook"].toString();
|
||||
QString relativePath = fileJson["relative_path"].toString();
|
||||
bool isForced = fileJson["is_forced"].toBool();
|
||||
|
||||
int nrWin = splitter->count();
|
||||
bool ret = false;
|
||||
for (int i = 0; i < nrWin; ++i) {
|
||||
VEditWindow *win = getWindow(i);
|
||||
win->closeFile(notebook, relativePath);
|
||||
ret = ret || win->closeFile(notebook, relativePath, isForced);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void VEditArea::editFile()
|
||||
@ -225,6 +228,29 @@ void VEditArea::handleNotebookRenamed(const QVector<VNotebook> ¬ebooks,
|
||||
VEditWindow *win = getWindow(i);
|
||||
win->handleNotebookRenamed(notebooks, oldName, newName);
|
||||
}
|
||||
updateWindowStatus();
|
||||
}
|
||||
|
||||
void VEditArea::handleDirectoryRenamed(const QString ¬ebook, const QString &oldRelativePath,
|
||||
const QString &newRelativePath)
|
||||
{
|
||||
int nrWin = splitter->count();
|
||||
for (int i = 0; i < nrWin; ++i) {
|
||||
VEditWindow *win = getWindow(i);
|
||||
win->handleDirectoryRenamed(notebook, oldRelativePath, newRelativePath);
|
||||
}
|
||||
updateWindowStatus();
|
||||
}
|
||||
|
||||
void VEditArea::handleFileRenamed(const QString ¬ebook,
|
||||
const QString &oldRelativePath, const QString &newRelativePath)
|
||||
{
|
||||
int nrWin = splitter->count();
|
||||
for (int i = 0; i < nrWin; ++i) {
|
||||
VEditWindow *win = getWindow(i);
|
||||
win->handleFileRenamed(notebook, oldRelativePath, newRelativePath);
|
||||
}
|
||||
updateWindowStatus();
|
||||
}
|
||||
|
||||
void VEditArea::handleSplitWindowRequest(VEditWindow *curWindow)
|
||||
@ -305,3 +331,8 @@ void VEditArea::handleOutlineItemActivated(const VAnchor &anchor)
|
||||
// Notice current window
|
||||
getWindow(curWindowIndex)->scrollCurTab(anchor);
|
||||
}
|
||||
|
||||
bool VEditArea::isFileOpened(const QString ¬ebook, const QString &relativePath)
|
||||
{
|
||||
return !findTabsByFile(notebook, relativePath).isEmpty();
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ class VEditArea : public QWidget
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VEditArea(VNote *vnote, QWidget *parent = 0);
|
||||
bool isFileOpened(const QString ¬ebook, const QString &relativePath);
|
||||
|
||||
signals:
|
||||
void curTabStatusChanged(const QString ¬ebook, const QString &relativePath,
|
||||
@ -33,8 +34,7 @@ protected:
|
||||
|
||||
public slots:
|
||||
void openFile(QJsonObject fileJson);
|
||||
// Close the file forcely
|
||||
void closeFile(QJsonObject fileJson);
|
||||
bool closeFile(QJsonObject fileJson);
|
||||
void editFile();
|
||||
void saveFile();
|
||||
void readFile();
|
||||
@ -42,6 +42,10 @@ public slots:
|
||||
void handleNotebookRenamed(const QVector<VNotebook> ¬ebooks, const QString &oldName,
|
||||
const QString &newName);
|
||||
void handleOutlineItemActivated(const VAnchor &anchor);
|
||||
void handleDirectoryRenamed(const QString ¬ebook,
|
||||
const QString &oldRelativePath, const QString &newRelativePath);
|
||||
void handleFileRenamed(const QString ¬ebook,
|
||||
const QString &oldRelativePath, const QString &newRelativePath);
|
||||
|
||||
private slots:
|
||||
void handleSplitWindowRequest(VEditWindow *curWindow);
|
||||
|
@ -21,7 +21,7 @@ extern VConfigManager vconfig;
|
||||
VEditTab::VEditTab(const QString &path, bool modifiable, QWidget *parent)
|
||||
: QStackedWidget(parent), mdConverterType(vconfig.getMdConverterType())
|
||||
{
|
||||
DocType docType = isMarkdown(path) ? DocType::Markdown : DocType::Html;
|
||||
DocType docType = VUtils::isMarkdown(path) ? DocType::Markdown : DocType::Html;
|
||||
QString basePath = QFileInfo(path).path();
|
||||
QString fileName = QFileInfo(path).fileName();
|
||||
qDebug() << "VEditTab basePath" << basePath << "file" << fileName;
|
||||
@ -75,23 +75,6 @@ void VEditTab::setupUI()
|
||||
}
|
||||
}
|
||||
|
||||
bool VEditTab::isMarkdown(const QString &name)
|
||||
{
|
||||
const QVector<QString> mdPostfix({"md", "markdown", "mkd"});
|
||||
|
||||
QStringList list = name.split('.', QString::SkipEmptyParts);
|
||||
if (list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
const QString &postfix = list.last();
|
||||
for (int i = 0; i < mdPostfix.size(); ++i) {
|
||||
if (postfix == mdPostfix[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VEditTab::showFileReadMode()
|
||||
{
|
||||
isEditMode = false;
|
||||
@ -402,3 +385,10 @@ void VEditTab::updateCurHeader(int lineNumber)
|
||||
emit curHeaderChanged(curHeader);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditTab::updatePath(const QString &newPath)
|
||||
{
|
||||
QFileInfo info(newPath);
|
||||
noteFile->basePath = info.path();
|
||||
noteFile->fileName = info.fileName();
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
void requestUpdateOutline();
|
||||
void requestUpdateCurHeader();
|
||||
void scrollToAnchor(const VAnchor& anchor);
|
||||
void updatePath(const QString &newPath);
|
||||
|
||||
signals:
|
||||
void getFocused();
|
||||
@ -51,7 +52,6 @@ private slots:
|
||||
void updateTocFromHeaders(const QVector<VHeader> &headers);
|
||||
|
||||
private:
|
||||
bool isMarkdown(const QString &name);
|
||||
void setupUI();
|
||||
void showFileReadMode();
|
||||
void showFileEditMode();
|
||||
|
@ -123,21 +123,26 @@ out:
|
||||
return idx;
|
||||
}
|
||||
|
||||
void VEditWindow::closeFile(const QString ¬ebook, const QString &relativePath)
|
||||
bool VEditWindow::closeFile(const QString ¬ebook, const QString &relativePath, bool isForced)
|
||||
{
|
||||
// Find if it has been opened already
|
||||
int idx = findTabByFile(notebook, relativePath);
|
||||
if (idx == -1) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do not check if modified
|
||||
VEditTab *editor = getTab(idx);
|
||||
Q_ASSERT(editor);
|
||||
bool ok = true;
|
||||
if (!isForced) {
|
||||
ok = editor->requestClose();
|
||||
}
|
||||
if (ok) {
|
||||
removeTab(idx);
|
||||
delete editor;
|
||||
|
||||
}
|
||||
updateTabListMenu();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool VEditWindow::closeAllFiles()
|
||||
@ -155,17 +160,8 @@ bool VEditWindow::closeAllFiles()
|
||||
int VEditWindow::openFileInTab(const QString ¬ebook, const QString &relativePath,
|
||||
bool modifiable)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
VEditTab *editor = new VEditTab(QDir::cleanPath(QDir(rootPath).filePath(relativePath)),
|
||||
modifiable);
|
||||
QString path = QDir::cleanPath(QDir(vnote->getNotebookPath(notebook)).filePath(relativePath));
|
||||
VEditTab *editor = new VEditTab(path, modifiable);
|
||||
connect(editor, &VEditTab::getFocused,
|
||||
this, &VEditWindow::getFocused);
|
||||
connect(editor, &VEditTab::outlineChanged,
|
||||
@ -200,7 +196,6 @@ int VEditWindow::findTabByFile(const QString ¬ebook, const QString &relativeP
|
||||
|
||||
bool VEditWindow::handleTabCloseRequest(int index)
|
||||
{
|
||||
qDebug() << "request closing tab" << index;
|
||||
VEditTab *editor = getTab(index);
|
||||
Q_ASSERT(editor);
|
||||
bool ok = editor->requestClose();
|
||||
@ -262,6 +257,51 @@ void VEditWindow::handleNotebookRenamed(const QVector<VNotebook> ¬ebooks,
|
||||
updateTabListMenu();
|
||||
}
|
||||
|
||||
void VEditWindow::handleDirectoryRenamed(const QString ¬ebook, const QString &oldRelativePath,
|
||||
const QString &newRelativePath)
|
||||
{
|
||||
QTabBar *tabs = tabBar();
|
||||
int nrTabs = tabs->count();
|
||||
for (int i = 0; i < nrTabs; ++i) {
|
||||
QJsonObject tabJson = tabs->tabData(i).toJsonObject();
|
||||
if (tabJson["notebook"].toString() == notebook) {
|
||||
QString relativePath = tabJson["relative_path"].toString();
|
||||
if (relativePath.startsWith(oldRelativePath)) {
|
||||
relativePath.replace(0, oldRelativePath.size(), newRelativePath);
|
||||
tabJson["relative_path"] = relativePath;
|
||||
tabs->setTabData(i, tabJson);
|
||||
tabs->setTabToolTip(i, generateTooltip(tabJson));
|
||||
QString path = QDir::cleanPath(QDir(vnote->getNotebookPath(notebook)).filePath(relativePath));
|
||||
getTab(i)->updatePath(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateTabListMenu();
|
||||
}
|
||||
|
||||
void VEditWindow::handleFileRenamed(const QString ¬ebook, const QString &oldRelativePath,
|
||||
const QString &newRelativePath)
|
||||
{
|
||||
QTabBar *tabs = tabBar();
|
||||
int nrTabs = tabs->count();
|
||||
for (int i = 0; i < nrTabs; ++i) {
|
||||
QJsonObject tabJson = tabs->tabData(i).toJsonObject();
|
||||
if (tabJson["notebook"].toString() == notebook) {
|
||||
QString relativePath = tabJson["relative_path"].toString();
|
||||
if (relativePath == oldRelativePath) {
|
||||
relativePath = newRelativePath;
|
||||
tabJson["relative_path"] = relativePath;
|
||||
tabs->setTabData(i, tabJson);
|
||||
tabs->setTabToolTip(i, generateTooltip(tabJson));
|
||||
tabs->setTabText(i, getFileName(relativePath));
|
||||
QString path = QDir::cleanPath(QDir(vnote->getNotebookPath(notebook)).filePath(relativePath));
|
||||
getTab(i)->updatePath(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateTabListMenu();
|
||||
}
|
||||
|
||||
void VEditWindow::noticeTabStatus(int index)
|
||||
{
|
||||
if (index == -1) {
|
||||
|
@ -22,8 +22,7 @@ public:
|
||||
int findTabByFile(const QString ¬ebook, const QString &relativePath) const;
|
||||
int openFile(const QString ¬ebook, const QString &relativePath,
|
||||
int mode);
|
||||
// Close the file forcely
|
||||
void closeFile(const QString ¬ebook, const QString &relativePath);
|
||||
bool closeFile(const QString ¬ebook, const QString &relativePath, bool isForced);
|
||||
void editFile();
|
||||
void saveFile();
|
||||
void readFile();
|
||||
@ -38,6 +37,10 @@ public:
|
||||
// Focus to current tab's editor
|
||||
void focusWindow();
|
||||
void scrollCurTab(const VAnchor &anchor);
|
||||
void handleDirectoryRenamed(const QString ¬ebook,
|
||||
const QString &oldRelativePath, const QString &newRelativePath);
|
||||
void handleFileRenamed(const QString ¬ebook,
|
||||
const QString &oldRelativePath, const QString &newRelativePath);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "dialog/vnewfiledialog.h"
|
||||
#include "dialog/vfileinfodialog.h"
|
||||
#include "vnote.h"
|
||||
#include "veditarea.h"
|
||||
#include "utils/vutils.h"
|
||||
|
||||
VFileList::VFileList(VNote *vnote, QWidget *parent)
|
||||
: QWidget(parent), vnote(vnote)
|
||||
@ -219,6 +221,7 @@ void VFileList::deleteFile()
|
||||
// First close this file forcely
|
||||
curItemJson["notebook"] = notebook;
|
||||
curItemJson["relative_path"] = QDir::cleanPath(QDir(relativePath).filePath(curItemName));
|
||||
curItemJson["is_forced"] = true;
|
||||
emit fileDeleted(curItemJson);
|
||||
|
||||
deleteFileAndUpdateList(curItem);
|
||||
@ -399,13 +402,12 @@ void VFileList::handleNotebookRenamed(const QVector<VNotebook> ¬ebooks,
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: when @oldRelativePath is part of relativePath, we also need to update relativePath partialy
|
||||
void VFileList::handleDirectoryRenamed(const QString ¬ebook,
|
||||
const QString &oldRelativePath, const QString &newRelativePath)
|
||||
{
|
||||
if (notebook == this->notebook
|
||||
&& oldRelativePath == relativePath) {
|
||||
relativePath = newRelativePath;
|
||||
&& relativePath.startsWith(oldRelativePath)) {
|
||||
relativePath.replace(0, oldRelativePath.size(), newRelativePath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,6 +419,32 @@ void VFileList::renameFile(QListWidgetItem *item, const QString &newName)
|
||||
QJsonObject itemJson = item->data(Qt::UserRole).toJsonObject();
|
||||
Q_ASSERT(!itemJson.isEmpty());
|
||||
QString name = itemJson["name"].toString();
|
||||
|
||||
// If change the file type, we need to convert it
|
||||
DocType docType = VUtils::isMarkdown(name) ? DocType::Markdown : DocType::Html;
|
||||
DocType newDocType = VUtils::isMarkdown(newName) ? DocType::Markdown : DocType::Html;
|
||||
if (docType != newDocType) {
|
||||
QString fileRelativePath = QDir::cleanPath(QDir(relativePath).filePath(name));
|
||||
if (editArea->isFileOpened(notebook, fileRelativePath)) {
|
||||
QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Rename will change the note type"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel, this);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setInformativeText(QString("You should close the note %1 before continue").arg(name));
|
||||
if (QMessageBox::Ok == msgBox.exec()) {
|
||||
QJsonObject curItemJson;
|
||||
curItemJson["notebook"] = notebook;
|
||||
curItemJson["relative_path"] = fileRelativePath;
|
||||
curItemJson["is_forced"] = false;
|
||||
if (!editArea->closeFile(curItemJson)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
convertFileType(notebook, fileRelativePath, docType, newDocType);
|
||||
}
|
||||
|
||||
QString path = QDir(rootPath).filePath(relativePath);
|
||||
QFile file(QDir(path).filePath(name));
|
||||
QString newFilePath(QDir(path).filePath(newName));
|
||||
@ -462,3 +490,20 @@ void VFileList::renameFile(QListWidgetItem *item, const QString &newName)
|
||||
qDebug() << "file renamed" << oldPath << "to" << newPath;
|
||||
emit fileRenamed(notebook, oldPath, newPath);
|
||||
}
|
||||
|
||||
void VFileList::convertFileType(const QString ¬ebook, const QString &fileRelativePath,
|
||||
DocType oldType, DocType newType)
|
||||
{
|
||||
Q_ASSERT(oldType != newType);
|
||||
QString filePath = QDir(vnote->getNotebookPath(notebook)).filePath(fileRelativePath);
|
||||
QString fileText = VUtils::readFileFromDisk(filePath);
|
||||
QTextEdit editor;
|
||||
if (oldType == DocType::Markdown) {
|
||||
editor.setPlainText(fileText);
|
||||
fileText = editor.toHtml();
|
||||
} else {
|
||||
editor.setHtml(fileText);
|
||||
fileText = editor.toPlainText();
|
||||
}
|
||||
VUtils::writeFileToDisk(filePath, fileText);
|
||||
}
|
||||
|
@ -6,12 +6,14 @@
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include "vnotebook.h"
|
||||
#include "vconstants.h"
|
||||
|
||||
class QAction;
|
||||
class VNote;
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
class QPushButton;
|
||||
class VEditArea;
|
||||
|
||||
class VFileList : public QWidget
|
||||
{
|
||||
@ -19,6 +21,7 @@ class VFileList : public QWidget
|
||||
public:
|
||||
explicit VFileList(VNote *vnote, QWidget *parent = 0);
|
||||
bool importFile(const QString &name);
|
||||
inline void setEditArea(VEditArea *editArea);
|
||||
|
||||
signals:
|
||||
void fileClicked(QJsonObject fileJson);
|
||||
@ -54,6 +57,8 @@ private:
|
||||
void clearDirectoryInfo();
|
||||
inline QString getDirectoryName();
|
||||
void renameFile(QListWidgetItem *item, const QString &newName);
|
||||
void convertFileType(const QString ¬ebook, const QString &fileRelativePath,
|
||||
DocType oldType, DocType newType);
|
||||
|
||||
VNote *vnote;
|
||||
QString notebook;
|
||||
@ -62,6 +67,8 @@ private:
|
||||
// Used for cache
|
||||
QString rootPath;
|
||||
|
||||
VEditArea *editArea;
|
||||
|
||||
QListWidget *fileList;
|
||||
|
||||
// Actions
|
||||
@ -78,4 +85,9 @@ inline QString VFileList::getDirectoryName()
|
||||
return QFileInfo(QDir::cleanPath(relativePath)).fileName();
|
||||
}
|
||||
|
||||
inline void VFileList::setEditArea(VEditArea *editArea)
|
||||
{
|
||||
this->editArea = editArea;
|
||||
}
|
||||
|
||||
#endif // VFILELIST_H
|
||||
|
@ -76,6 +76,7 @@ void VMainWindow::setupUI()
|
||||
|
||||
editArea = new VEditArea(vnote);
|
||||
editArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
fileList->setEditArea(editArea);
|
||||
|
||||
// Main Splitter
|
||||
mainSplitter = new QSplitter();
|
||||
@ -109,6 +110,10 @@ void VMainWindow::setupUI()
|
||||
editArea, &VEditArea::handleNotebookRenamed);
|
||||
connect(editArea, &VEditArea::curTabStatusChanged,
|
||||
this, &VMainWindow::handleCurTabStatusChanged);
|
||||
connect(directoryTree, &VDirectoryTree::directoryRenamed,
|
||||
editArea, &VEditArea::handleDirectoryRenamed);
|
||||
connect(fileList, &VFileList::fileRenamed,
|
||||
editArea, &VEditArea::handleFileRenamed);
|
||||
|
||||
connect(newNotebookBtn, &QPushButton::clicked,
|
||||
this, &VMainWindow::onNewNotebookBtnClicked);
|
||||
|
Loading…
x
Reference in New Issue
Block a user