Browse Source

VAttachmentList: check missing attachments when showing the list

Le Tan 8 years ago
parent
commit
18ed9b761a

+ 2 - 0
src/resources/docs/shortcuts_en.md

@@ -124,6 +124,8 @@ Toggle single panel or two panels mode.
 Toggle the Tools panel.
 - `F`   
 Popup the opened notes list of current split window. Within this list, pressing the sequence number in front of each note could jump to that note.
+- `A`   
+Popup the attachments list of current note.
 - `X`   
 Close current tab.
 - `J`   

+ 2 - 0
src/resources/docs/shortcuts_zh.md

@@ -125,6 +125,8 @@ size=8
 打开或关闭工具面板。
 - `F`   
 打开当前分割窗口的笔记列表。在该列表中,可以直接按笔记对应的序号实现跳转。
+- `A`   
+打开当前笔记的附件列表。
 - `X`   
 关闭当前标签页。
 - `J`   

+ 68 - 2
src/vattachmentlist.cpp

@@ -62,7 +62,8 @@ void VAttachmentList::setupUI()
                                                 tr("Fail to clear attachments of note <span style=\"%1\">%2</span>.")
                                                   .arg(g_config->c_dataTextStyle)
                                                   .arg(m_file->getName()),
-                                                tr("Please maintain the configureation file manually."),
+                                                tr("Please check the attachments folder and "
+                                                   "maintain the configuration file manually."),
                                                 QMessageBox::Ok,
                                                 QMessageBox::Ok,
                                                 g_vnote->getMainWindow());
@@ -344,7 +345,8 @@ void VAttachmentList::deleteSelectedItems()
                                 tr("Fail to delete attachments of note <span style=\"%1\">%2</span>.")
                                   .arg(g_config->c_dataTextStyle)
                                   .arg(m_file->getName()),
-                                tr("Please maintain the configureation file manually."),
+                                tr("Please check the attachments folder and "
+                                   "maintain the configuration file manually."),
                                 QMessageBox::Ok,
                                 QMessageBox::Ok,
                                 g_vnote->getMainWindow());
@@ -566,6 +568,8 @@ bool VAttachmentList::handleDropEvent(QDropEvent *p_event)
 void VAttachmentList::handleAboutToShow()
 {
     updateContent();
+
+    checkAttachments();
 }
 
 void VAttachmentList::updateButtonState() const
@@ -586,3 +590,65 @@ void VAttachmentList::updateButtonState() const
 
     btn->setBubbleNumber(numOfAttachments);
 }
+
+void VAttachmentList::checkAttachments()
+{
+    if (!m_file) {
+        return;
+    }
+
+    QVector<QString> missingAttas = m_file->checkAttachments();
+    if (missingAttas.isEmpty()) {
+        return;
+    }
+
+    QVector<ConfirmItemInfo> items;
+    for (auto const & atta : missingAttas) {
+        items.push_back(ConfirmItemInfo(atta,
+                                        atta,
+                                        "",
+                                        NULL));
+    }
+
+    QString text = tr("VNote detects that these attachments of note "
+                      "<span style=\"%1\">%2</span> are missing in disk. "
+                      "Would you like to remove them from the note?")
+                     .arg(g_config->c_dataTextStyle)
+                     .arg(m_file->getName());
+
+    QString info = tr("Click \"Cancel\" to leave them untouched.");
+
+    VConfirmDeletionDialog dialog(tr("Confirm Deleting Attachments"),
+                                  text,
+                                  info,
+                                  items,
+                                  false,
+                                  false,
+                                  false,
+                                  g_vnote->getMainWindow());
+    if (dialog.exec()) {
+        items = dialog.getConfirmedItems();
+
+        QVector<QString> names;
+        for (auto const & item : items) {
+            names.push_back(item.m_name);
+        }
+
+        if (!m_file->deleteAttachments(names, true)) {
+            VUtils::showMessage(QMessageBox::Warning,
+                                tr("Warning"),
+                                tr("Fail to delete attachments of note <span style=\"%1\">%2</span>.")
+                                  .arg(g_config->c_dataTextStyle)
+                                  .arg(m_file->getName()),
+                                tr("Please check the attachments folder and "
+                                   "maintain the configuration file manually."),
+                                QMessageBox::Ok,
+                                QMessageBox::Ok,
+                                g_vnote->getMainWindow());
+        }
+
+        updateButtonState();
+
+        updateContent();
+    }
+}

+ 3 - 0
src/vattachmentlist.h

@@ -62,6 +62,9 @@ private:
     // Update the state of VButtonWithWidget.
     void updateButtonState() const;
 
+    // Check if there are attachments that do not exist in disk.
+    void checkAttachments();
+
     QPushButton *m_addBtn;
     QPushButton *m_clearBtn;
     QPushButton *m_locateBtn;

+ 28 - 4
src/vnotefile.cpp

@@ -268,7 +268,7 @@ QString VNoteFile::fetchAttachmentFolderPath()
     return folderPath;
 }
 
-bool VNoteFile::deleteAttachments()
+bool VNoteFile::deleteAttachments(bool p_omitMissing)
 {
     if (m_attachments.isEmpty()) {
         return true;
@@ -279,10 +279,11 @@ bool VNoteFile::deleteAttachments()
         attas.push_back(m_attachments[i].m_name);
     }
 
-    return deleteAttachments(attas);
+    return deleteAttachments(attas, p_omitMissing);
 }
 
-bool VNoteFile::deleteAttachments(const QVector<QString> &p_names)
+bool VNoteFile::deleteAttachments(const QVector<QString> &p_names,
+                                  bool p_omitMissing)
 {
     if (p_names.isEmpty()) {
         return true;
@@ -298,7 +299,15 @@ bool VNoteFile::deleteAttachments(const QVector<QString> &p_names)
         }
 
         m_attachments.remove(idx);
-        if (!VUtils::deleteFile(getNotebook(), dir.filePath(p_names[i]), false)) {
+
+        QString filePath = dir.filePath(p_names[i]);
+        if (p_omitMissing
+            && !QFileInfo::exists(filePath)) {
+            // The attachment file does not exist. We skip it to avoid error.
+            continue;
+        }
+
+        if (!VUtils::deleteFile(getNotebook(), filePath, false)) {
             ret = false;
             qWarning() << "fail to delete attachment" << p_names[i]
                        << "for note" << m_name;
@@ -386,6 +395,21 @@ bool VNoteFile::renameAttachment(const QString &p_oldName, const QString &p_newN
     return true;
 }
 
+QVector<QString> VNoteFile::checkAttachments()
+{
+    QVector<QString> missing;
+
+    QDir dir(fetchAttachmentFolderPath());
+    for (auto const & atta : m_attachments) {
+        QString file = dir.filePath(atta.m_name);
+        if (!QFileInfo::exists(file)) {
+            missing.push_back(atta.m_name);
+        }
+    }
+
+    return missing;
+}
+
 bool VNoteFile::deleteFile(VNoteFile *p_file, QString *p_errMsg)
 {
     Q_ASSERT(!p_file->isOpened());

+ 9 - 2
src/vnotefile.h

@@ -86,10 +86,13 @@ public:
     QString fetchAttachmentFolderPath();
 
     // Delete all the attachments.
-    bool deleteAttachments();
+    // @p_omitMissing: omit the error if the attachment file does not exist.
+    bool deleteAttachments(bool p_omitMissing = false);
 
     // Delete attachments specified by @p_names.
-    bool deleteAttachments(const QVector<QString> &p_names);
+    // @p_omitMissing: omit the error if the attachment file does not exist.
+    bool deleteAttachments(const QVector<QString> &p_names,
+                           bool p_omitMissing = false);
 
     // Reorder attachments in m_attachments by index.
     bool sortAttachments(const QVector<int> &p_sortedIdx);
@@ -101,6 +104,10 @@ public:
     // Rename attachment @p_oldName to @p_newName.
     bool renameAttachment(const QString &p_oldName, const QString &p_newName);
 
+    // Check if all the attachment files still exist.
+    // Return the missing attachments' names.
+    QVector<QString> checkAttachments();
+
     // Create a VNoteFile from @p_json Json object.
     static VNoteFile *fromJson(VDirectory *p_directory,
                                const QJsonObject &p_json,