Browse Source

complete rename logics

1. Handle directory rename correctly;
2. Handle file rename correctly;

Signed-off-by: Le Tan <[email protected]>
Le Tan 9 years ago
parent
commit
62c75427e7
11 changed files with 195 additions and 47 deletions
  1. 17 0
      src/utils/vutils.cpp
  2. 1 0
      src/utils/vutils.h
  3. 34 3
      src/veditarea.cpp
  4. 6 2
      src/veditarea.h
  5. 8 18
      src/vedittab.cpp
  6. 1 1
      src/vedittab.h
  7. 58 18
      src/veditwindow.cpp
  8. 5 2
      src/veditwindow.h
  9. 48 3
      src/vfilelist.cpp
  10. 12 0
      src/vfilelist.h
  11. 5 0
      src/vmainwindow.cpp

+ 17 - 0
src/utils/vutils.cpp

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

+ 1 - 0
src/utils/vutils.h

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

+ 34 - 3
src/veditarea.cpp

@@ -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> &notebooks,
         VEditWindow *win = getWindow(i);
         win->handleNotebookRenamed(notebooks, oldName, newName);
     }
+    updateWindowStatus();
+}
+
+void VEditArea::handleDirectoryRenamed(const QString &notebook, 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 &notebook,
+                                  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 &notebook, const QString &relativePath)
+{
+    return !findTabsByFile(notebook, relativePath).isEmpty();
+}

+ 6 - 2
src/veditarea.h

@@ -21,6 +21,7 @@ class VEditArea : public QWidget
     Q_OBJECT
 public:
     explicit VEditArea(VNote *vnote, QWidget *parent = 0);
+    bool isFileOpened(const QString &notebook, const QString &relativePath);
 
 signals:
     void curTabStatusChanged(const QString &notebook, 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> &notebooks, const QString &oldName,
                                const QString &newName);
     void handleOutlineItemActivated(const VAnchor &anchor);
+    void handleDirectoryRenamed(const QString &notebook,
+                                const QString &oldRelativePath, const QString &newRelativePath);
+    void handleFileRenamed(const QString &notebook,
+                           const QString &oldRelativePath, const QString &newRelativePath);
 
 private slots:
     void handleSplitWindowRequest(VEditWindow *curWindow);

+ 8 - 18
src/vedittab.cpp

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

+ 1 - 1
src/vedittab.h

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

+ 58 - 18
src/veditwindow.cpp

@@ -123,21 +123,26 @@ out:
     return idx;
 }
 
-void VEditWindow::closeFile(const QString &notebook, const QString &relativePath)
+bool VEditWindow::closeFile(const QString &notebook, 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);
-    removeTab(idx);
-    delete 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 &notebook, const QString &relativePath,
                               bool modifiable)
 {
-    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;
-        }
-    }
-
-    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 &notebook, 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> &notebooks,
     updateTabListMenu();
 }
 
+void VEditWindow::handleDirectoryRenamed(const QString &notebook, 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 &notebook, 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) {

+ 5 - 2
src/veditwindow.h

@@ -22,8 +22,7 @@ public:
     int findTabByFile(const QString &notebook, const QString &relativePath) const;
     int openFile(const QString &notebook, const QString &relativePath,
                  int mode);
-    // Close the file forcely
-    void closeFile(const QString &notebook, const QString &relativePath);
+    bool closeFile(const QString &notebook, 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 &notebook,
+                                const QString &oldRelativePath, const QString &newRelativePath);
+    void handleFileRenamed(const QString &notebook,
+                           const QString &oldRelativePath, const QString &newRelativePath);
 
 protected:
     void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

+ 48 - 3
src/vfilelist.cpp

@@ -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> &notebooks,
     }
 }
 
-// FIXME: when @oldRelativePath is part of relativePath, we also need to update relativePath partialy
 void VFileList::handleDirectoryRenamed(const QString &notebook,
                                        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 &notebook, 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);
+}

+ 12 - 0
src/vfilelist.h

@@ -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 &notebook, 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

+ 5 - 0
src/vmainwindow.cpp

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