Browse Source

open an external file as internal note if it is a note within VNote

Le Tan 8 years ago
parent
commit
c2fe857e3a
10 changed files with 174 additions and 18 deletions
  1. 34 0
      src/utils/vutils.cpp
  2. 9 0
      src/utils/vutils.h
  3. 33 0
      src/vdirectory.cpp
  4. 16 13
      src/vdirectory.h
  5. 10 2
      src/vmainwindow.cpp
  6. 3 1
      src/vmainwindow.h
  7. 14 0
      src/vnote.cpp
  8. 5 0
      src/vnote.h
  9. 36 0
      src/vnotebook.cpp
  10. 14 2
      src/vnotebook.h

+ 34 - 0
src/utils/vutils.cpp

@@ -650,3 +650,37 @@ bool VUtils::equalPath(const QString &p_patha, const QString &p_pathb)
 
     return a == b;
 }
+
+bool VUtils::splitPathInBasePath(const QString &p_base,
+                                 const QString &p_path,
+                                 QStringList &p_parts)
+{
+    p_parts.clear();
+    QString a = QDir::cleanPath(p_base);
+    QString b = QDir::cleanPath(p_path);
+
+#if defined(Q_OS_WIN)
+    if (!b.toLower().startsWith(a.toLower())) {
+        return false;
+    }
+#else
+    if (!b.startsWith(a)) {
+        return false;
+    }
+#endif
+
+    if (a.size() == b.size()) {
+        return true;
+    }
+
+    Q_ASSERT(a.size() < b.size());
+
+    if (b.at(a.size()) != '/') {
+        return false;
+    }
+
+    p_parts = b.right(b.size() - a.size() - 1).split("/", QString::SkipEmptyParts);
+
+    qDebug() << QString("split path %1 based on %2 to %3 parts").arg(p_path).arg(p_base).arg(p_parts.size());
+    return true;
+}

+ 9 - 0
src/utils/vutils.h

@@ -109,6 +109,15 @@ public:
     // Returns true if @p_patha and @p_pathb points to the same file/directory.
     static bool equalPath(const QString &p_patha, const QString &p_pathb);
 
+    // Try to split @p_path into multiple parts based on @p_base.
+    // Returns false if @p_path is not under @p_base directory.
+    // @p_parts will be empty if @p_path is right @p_base.
+    // Example: "/home/tamlok/study", "/home/tamlok/study/a/b/c/vnote.md"
+    // returns true and @p_parts is {a, b, c, vnote.md}.
+    static bool splitPathInBasePath(const QString &p_base,
+                                    const QString &p_path,
+                                    QStringList &p_parts);
+
     // Regular expression for image link.
     // ![image title]( http://github.com/tamlok/vnote.jpg "alt \" text" )
     // Captured texts (need to be trimmed):

+ 33 - 0
src/vdirectory.cpp

@@ -678,3 +678,36 @@ void VDirectory::reorderFiles(int p_first, int p_last, int p_destStart)
         m_files = oriFiles;
     }
 }
+
+VFile *VDirectory::tryLoadFile(QStringList &p_filePath)
+{
+    qDebug() << "directory" << m_name << "tryLoadFile()" << p_filePath.join("/");
+    if (p_filePath.isEmpty()) {
+        return NULL;
+    }
+
+    bool opened = isOpened();
+    if (!open()) {
+        return NULL;
+    }
+
+    VFile *file = NULL;
+
+    if (p_filePath.size() == 1) {
+        // File.
+        file = findFile(p_filePath.at(0));
+    } else {
+        // Directory.
+        VDirectory *dir = findSubDirectory(p_filePath.at(0));
+        if (dir) {
+            p_filePath.removeFirst();
+            file = dir->tryLoadFile(p_filePath);
+        }
+    }
+
+    if (!file && !opened) {
+        close();
+    }
+
+    return file;
+}

+ 16 - 13
src/vdirectory.h

@@ -60,20 +60,20 @@ public:
     static VDirectory *copyDirectory(VDirectory *p_destDir, const QString &p_destName,
                                      VDirectory *p_srcDir, bool p_cut);
 
-    inline const QVector<VDirectory *> &getSubDirs() const;
-    inline const QString &getName() const;
-    inline void setName(const QString &p_name);
-    inline bool isOpened() const;
-    inline VDirectory *getParentDirectory();
-    inline const VDirectory *getParentDirectory() const;
-    inline VNotebook *getNotebook();
-    inline const VNotebook *getNotebook() const;
-    inline const QVector<VFile *> &getFiles() const;
-    inline QString retrivePath() const;
+    const QVector<VDirectory *> &getSubDirs() const;
+    const QString &getName() const;
+    void setName(const QString &p_name);
+    bool isOpened() const;
+    VDirectory *getParentDirectory();
+    const VDirectory *getParentDirectory() const;
+    VNotebook *getNotebook();
+    const VNotebook *getNotebook() const;
+    const QVector<VFile *> &getFiles() const;
+    QString retrivePath() const;
     QString retriveBasePath() const;
-    inline QString retriveRelativePath() const;
-    inline QString getNotebookName() const;
-    inline bool isExpanded() const;
+    QString retriveRelativePath() const;
+    QString getNotebookName() const;
+    bool isExpanded() const;
     void setExpanded(bool p_expanded);
     void reorderFiles(int p_first, int p_last, int p_destStart);
 
@@ -90,6 +90,9 @@ public:
     // notebook.
     bool writeToConfig() const;
 
+    // Try to load file given relative path @p_filePath.
+    VFile *tryLoadFile(QStringList &p_filePath);
+
 private:
     // Get the path of @p_dir recursively
     QString retrivePath(const VDirectory *p_dir) const;

+ 10 - 2
src/vmainwindow.cpp

@@ -1890,11 +1890,19 @@ void VMainWindow::handleVimStatusUpdated(const VVim *p_vim)
     }
 }
 
-void VMainWindow::openExternalFiles(const QStringList &p_files)
+void VMainWindow::openExternalFiles(const QStringList &p_files, bool p_forceOrphan)
 {
     qDebug() << "open external files" << p_files;
     for (int i = 0; i < p_files.size(); ++i) {
-        VFile *file = vnote->getOrphanFile(p_files[i], true);
+        VFile *file = NULL;
+        if (!p_forceOrphan) {
+            file = vnote->getInternalFile(p_files[i]);
+        }
+
+        if (!file) {
+            file = vnote->getOrphanFile(p_files[i], true);
+        }
+
         editArea->openFile(file, OpenFileMode::Read);
     }
 }

+ 3 - 1
src/vmainwindow.h

@@ -53,7 +53,9 @@ public:
     void editOrphanFileInfo(VFile *p_file);
 
     // Open external files @p_files as orphan files.
-    void openExternalFiles(const QStringList &p_files);
+    // If @p_forceOrphan is false, for each file, VNote will try to find out if
+    // it is a note inside VNote. If yes, VNote will open it as internal file.
+    void openExternalFiles(const QStringList &p_files, bool p_forceOrphan = false);
 
 private slots:
     void importNoteFromFile();

+ 14 - 0
src/vnote.cpp

@@ -309,3 +309,17 @@ VFile *VNote::getOrphanFile(const QString &p_path, bool p_modifiable, bool p_sys
     m_externalFiles.append(file);
     return file;
 }
+
+VFile *VNote::getInternalFile(const QString &p_path)
+{
+    VFile *file = NULL;
+    for (auto & nb : m_notebooks) {
+        file = nb->tryLoadFile(p_path);
+        if (file) {
+            break;
+        }
+    }
+
+    return file;
+}
+

+ 5 - 0
src/vnote.h

@@ -78,6 +78,11 @@ public:
     VFile *getOrphanFile(const QString &p_path, bool p_modifiable,
                          bool p_systemFile = false);
 
+    // Given the path of a file, try to find it in all notebooks.
+    // Returns a VFile struct if it is a note in one notebook.
+    // Otherwise, returns NULL.
+    VFile *getInternalFile(const QString &p_path);
+
 public slots:
     void updateTemplate();
 

+ 36 - 0
src/vnotebook.cpp

@@ -187,6 +187,37 @@ bool VNotebook::containsFile(const VFile *p_file) const
     return m_rootDir->containsFile(p_file);
 }
 
+VFile *VNotebook::tryLoadFile(const QString &p_path)
+{
+    QFileInfo fi(p_path);
+    Q_ASSERT(fi.isAbsolute());
+    if (!fi.exists()) {
+        return NULL;
+    }
+
+    QStringList filePath;
+    if (VUtils::splitPathInBasePath(m_path, p_path, filePath)) {
+        if (filePath.isEmpty()) {
+            return NULL;
+        }
+
+        bool opened = isOpened();
+        if (!open()) {
+            return NULL;
+        }
+
+        VFile *file = m_rootDir->tryLoadFile(filePath);
+
+        if (!file && !opened) {
+            close();
+        }
+
+        return file;
+    }
+
+    return NULL;
+}
+
 const QString &VNotebook::getImageFolder() const
 {
     if (m_imageFolder.isEmpty()) {
@@ -205,3 +236,8 @@ const QString &VNotebook::getImageFolderConfig() const
 {
     return m_imageFolder;
 }
+
+bool VNotebook::isOpened() const
+{
+    return m_rootDir->isOpened();
+}

+ 14 - 2
src/vnotebook.h

@@ -17,15 +17,27 @@ public:
     // Open the root directory to load contents
     bool open();
 
+    // Whether this notebook is opened.
+    bool isOpened() const;
+
     // Close all the directory and files of this notebook.
     // Please make sure all files belonging to this notebook have been closed in the tab.
     void close();
 
     bool containsFile(const VFile *p_file) const;
 
+    // Try to load the file @p_path.
+    // Returns the corresponding VFile struct if @p_path is a note inside this notebook.
+    // Otherwise, returns NULL.
+    // If notebook is not opened currently, it will open itself and close itself
+    // if @p_path is not inside this notebook.
+    VFile *tryLoadFile(const QString &p_path);
+
     QString getName() const;
     QString getPath() const;
-    inline VDirectory *getRootDir();
+
+    VDirectory *getRootDir() const;
+
     void rename(const QString &p_name);
 
     static VNotebook *createNotebook(const QString &p_name, const QString &p_path,
@@ -76,7 +88,7 @@ private:
     VDirectory *m_rootDir;
 };
 
-inline VDirectory *VNotebook::getRootDir()
+inline VDirectory *VNotebook::getRootDir() const
 {
     return m_rootDir;
 }