← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~mzanetti/reminders-app/enable-deleting-notebooks-and-tags into lp:reminders-app

 

Michael Zanetti has proposed merging lp:~mzanetti/reminders-app/enable-deleting-notebooks-and-tags into lp:reminders-app.

Commit message:
Enable deleting notebooks and tags on Evernote

Requested reviews:
  Ubuntu Reminders app developers (reminders-app-dev)

For more details, see:
https://code.launchpad.net/~mzanetti/reminders-app/enable-deleting-notebooks-and-tags/+merge/261774
-- 
Your team Ubuntu Reminders app developers is requested to review the proposed merge of lp:~mzanetti/reminders-app/enable-deleting-notebooks-and-tags into lp:reminders-app.
=== modified file 'src/app/qml/components/NotebooksDelegate.qml'
--- src/app/qml/components/NotebooksDelegate.qml	2015-03-15 20:00:21 +0000
+++ src/app/qml/components/NotebooksDelegate.qml	2015-06-11 18:56:43 +0000
@@ -89,6 +89,7 @@
                 color: root.notebookColor
                 fontSize: "large"
                 Layout.fillWidth: true
+                font.strikeout: model.deleted
             }
 
             Label {

=== modified file 'src/app/qml/components/TagsDelegate.qml'
--- src/app/qml/components/TagsDelegate.qml	2015-03-15 20:00:21 +0000
+++ src/app/qml/components/TagsDelegate.qml	2015-06-11 18:56:43 +0000
@@ -80,6 +80,7 @@
                 text: model.name
                 fontSize: "large"
                 Layout.fillWidth: true
+                font.strikeout: model.deleted
             }
         }
 

=== modified file 'src/app/qml/reminders.qml'
--- src/app/qml/reminders.qml	2015-06-01 09:56:30 +0000
+++ src/app/qml/reminders.qml	2015-06-11 18:56:43 +0000
@@ -383,6 +383,7 @@
         onAuthenticated: {
             EvernoteConnection.token = reply.AccessToken;
             print("token is:", EvernoteConnection.token)
+            print("NetworkingStatus.online:", NetworkingStatus.online)
             if (NetworkingStatus.online) {
                 EvernoteConnection.connectToEvernote();
             }

=== modified file 'src/libqtevernote/CMakeLists.txt'
--- src/libqtevernote/CMakeLists.txt	2015-03-06 00:42:42 +0000
+++ src/libqtevernote/CMakeLists.txt	2015-06-11 18:56:43 +0000
@@ -32,6 +32,7 @@
     jobs/fetchtagsjob.cpp
     jobs/createtagjob.cpp
     jobs/savetagjob.cpp
+    jobs/expungetagjob.cpp
     resourceimageprovider.cpp
     utils/enmldocument.cpp
     utils/organizeradapter.cpp

=== added file 'src/libqtevernote/jobs/expungetagjob.cpp'
--- src/libqtevernote/jobs/expungetagjob.cpp	1970-01-01 00:00:00 +0000
+++ src/libqtevernote/jobs/expungetagjob.cpp	2015-06-11 18:56:43 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright: 2015 Canonical, Ltd
+ *
+ * This file is part of reminders
+ *
+ * reminders is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * reminders is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Michael Zanetti <michael.zanetti@xxxxxxxxxxxxx>
+ */
+
+#include "expungetagjob.h"
+
+ExpungeTagJob::ExpungeTagJob(const QString &guid, QObject *parent) :
+    NotesStoreJob(parent),
+    m_guid(guid)
+{
+}
+
+bool ExpungeTagJob::operator==(const EvernoteJob *other) const
+{
+    const ExpungeTagJob *otherJob = qobject_cast<const ExpungeTagJob*>(other);
+    if (!otherJob) {
+        return false;
+    }
+    return this->m_guid == otherJob->m_guid;
+}
+
+void ExpungeTagJob::attachToDuplicate(const EvernoteJob *other)
+{
+    const ExpungeTagJob *otherJob = static_cast<const ExpungeTagJob*>(other);
+    connect(otherJob, &ExpungeTagJob::jobDone, this, &ExpungeTagJob::jobDone);
+}
+
+void ExpungeTagJob::startJob()
+{
+    client()->expungeTag(token().toStdString(), m_guid.toStdString());
+}
+
+void ExpungeTagJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
+{
+    emit jobDone(errorCode, errorMessage, m_guid);
+}

=== added file 'src/libqtevernote/jobs/expungetagjob.h'
--- src/libqtevernote/jobs/expungetagjob.h	1970-01-01 00:00:00 +0000
+++ src/libqtevernote/jobs/expungetagjob.h	2015-06-11 18:56:43 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright: 2015 Canonical, Ltd
+ *
+ * This file is part of reminders
+ *
+ * reminders is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * reminders is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Michael Zanetti <michael.zanetti@xxxxxxxxxxxxx>
+ */
+
+#ifndef EXPUNGETAGJOB_H
+#define EXPUNGETAGJOB_H
+
+#include "notesstorejob.h"
+
+class ExpungeTagJob : public NotesStoreJob
+{
+    Q_OBJECT
+public:
+    explicit ExpungeTagJob(const QString &guid, QObject *parent = 0);
+
+    virtual bool operator==(const EvernoteJob *other) const override;
+    virtual void attachToDuplicate(const EvernoteJob *other) override;
+
+signals:
+    void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid);
+
+private slots:
+    void startJob();
+    void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
+
+private:
+    QString m_guid;
+};
+
+#endif // EXPUNGETAGJOB_H

=== modified file 'src/libqtevernote/notebook.cpp'
--- src/libqtevernote/notebook.cpp	2015-03-06 00:47:45 +0000
+++ src/libqtevernote/notebook.cpp	2015-06-11 18:56:43 +0000
@@ -34,7 +34,8 @@
     m_published(false),
     m_isDefaultNotebook(false),
     m_loading(false),
-    m_syncError(false)
+    m_syncError(false),
+    m_deleted(false)
 {
     setGuid(guid);
     QSettings infoFile(m_infoFile, QSettings::IniFormat);
@@ -44,6 +45,7 @@
     m_lastSyncedSequenceNumber = infoFile.value("lastSyncedSequenceNumber", 0).toUInt();
     m_isDefaultNotebook = infoFile.value("isDefaultNotebook", false).toBool();
     m_synced = m_lastSyncedSequenceNumber == m_updateSequenceNumber;
+    m_deleted = infoFile.value("deleted", false).toBool();
 
     foreach (Note *note, NotesStore::instance()->notes()) {
         if (note->notebookGuid() == m_guid) {
@@ -155,6 +157,7 @@
     notebook->setName(m_name);
     notebook->setLastUpdated(m_lastUpdated);
     notebook->setPublished(m_published);
+    notebook->setDeleted(m_deleted);
 
     return notebook;
 }
@@ -232,6 +235,7 @@
     infoFile.value("lastUpdated", m_lastUpdated);
     infoFile.setValue("lastSyncedSequenceNumber", m_lastSyncedSequenceNumber);
     infoFile.setValue("isDefaultNotebook", m_isDefaultNotebook);
+    infoFile.setValue("deleted", m_deleted);
 }
 
 void Notebook::deleteInfoFile()
@@ -257,6 +261,11 @@
     return m_syncError;
 }
 
+bool Notebook::deleted() const
+{
+    return m_deleted;
+}
+
 qint32 Notebook::updateSequenceNumber() const
 {
     return m_updateSequenceNumber;
@@ -287,6 +296,14 @@
     }
 }
 
+void Notebook::setDeleted(bool deleted)
+{
+    if (m_deleted != deleted) {
+        m_deleted = deleted;
+        emit deletedChanged();
+    }
+}
+
 void Notebook::setLoading(bool loading)
 {
     if (m_loading != loading) {

=== modified file 'src/libqtevernote/notebook.h'
--- src/libqtevernote/notebook.h	2015-03-04 20:30:55 +0000
+++ src/libqtevernote/notebook.h	2015-06-11 18:56:43 +0000
@@ -37,6 +37,7 @@
     Q_PROPERTY(QDateTime lastUpdated READ lastUpdated NOTIFY lastUpdatedChanged)
     Q_PROPERTY(QString lastUpdatedString READ lastUpdatedString NOTIFY lastUpdatedChanged)
     Q_PROPERTY(bool isDefaultNotebook READ isDefaultNotebook WRITE setIsDefaultNotebook NOTIFY isDefaultNotebookChanged)
+    Q_PROPERTY(bool deleted READ deleted NOTIFY deletedChanged)
     // Don't forget to update clone() if you add new properties
 
     Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
@@ -71,6 +72,7 @@
     bool loading() const;
     bool synced() const;
     bool syncError() const;
+    bool deleted() const;
 
     Notebook *clone();
 
@@ -87,6 +89,7 @@
     void syncedChanged();
     void syncErrorChanged();
     void isDefaultNotebookChanged();
+    void deletedChanged();
 
 private slots:
     void noteAdded(const QString &noteGuid, const QString &notebookGuid);
@@ -101,6 +104,7 @@
     void setSyncError(bool syncError);
     void setUpdateSequenceNumber(qint32 updateSequenceNumber);
     void setLastSyncedSequenceNumber(qint32 lastSyncedSequenceNumber);
+    void setDeleted(bool deleted);
 
     void syncToInfoFile();
     void deleteInfoFile();
@@ -114,6 +118,7 @@
     QDateTime m_lastUpdated;
     bool m_isDefaultNotebook;
     QList<QString> m_notesList;
+    bool m_deleted;
 
     QString m_infoFile;
 

=== modified file 'src/libqtevernote/notebooks.cpp'
--- src/libqtevernote/notebooks.cpp	2015-03-06 00:47:45 +0000
+++ src/libqtevernote/notebooks.cpp	2015-06-11 18:56:43 +0000
@@ -70,6 +70,8 @@
         return notebook->syncError();
     case RoleIsDefaultNotebook:
         return notebook->isDefaultNotebook();
+    case RoleDeleted:
+        return notebook->deleted();
     }
     return QVariant();
 }
@@ -94,6 +96,7 @@
     roles.insert(RoleSynced, "synced");
     roles.insert(RoleSyncError, "syncError");
     roles.insert(RoleIsDefaultNotebook, "isDefaultNotebook");
+    roles.insert(RoleDeleted, "deleted");
     return roles;
 }
 
@@ -121,6 +124,7 @@
     connect(notebook, &Notebook::loadingChanged, this, &Notebooks::notebookLoadingChanged);
     connect(notebook, &Notebook::syncErrorChanged, this, &Notebooks::syncErrorChanged);
     connect(notebook, &Notebook::isDefaultNotebookChanged, this, &Notebooks::isDefaultNotebookChanged);
+    connect(notebook, &Notebook::deletedChanged, this, &Notebooks::deletedChanged);
 
     beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
     m_list.append(guid);
@@ -150,6 +154,13 @@
     emit dataChanged(idx, idx, QVector<int>() << RoleIsDefaultNotebook);
 }
 
+void Notebooks::deletedChanged()
+{
+    Notebook *notebook = static_cast<Notebook*>(sender());
+    QModelIndex idx = index(m_list.indexOf(notebook->guid()));
+    emit dataChanged(idx, idx, QVector<int>() << RoleDeleted);
+}
+
 void Notebooks::nameChanged()
 {
     Notebook *notebook = static_cast<Notebook*>(sender());

=== modified file 'src/libqtevernote/notebooks.h'
--- src/libqtevernote/notebooks.h	2015-03-04 00:23:45 +0000
+++ src/libqtevernote/notebooks.h	2015-06-11 18:56:43 +0000
@@ -42,7 +42,8 @@
         RoleLoading,
         RoleSynced,
         RoleSyncError,
-        RoleIsDefaultNotebook
+        RoleIsDefaultNotebook,
+        RoleDeleted
     };
     explicit Notebooks(QObject *parent = 0);
 
@@ -76,6 +77,7 @@
     void notebookLoadingChanged();
     void syncErrorChanged();
     void isDefaultNotebookChanged();
+    void deletedChanged();
 
 private:
     QList<QString> m_list;

=== modified file 'src/libqtevernote/notesstore.cpp'
--- src/libqtevernote/notesstore.cpp	2015-03-30 19:01:49 +0000
+++ src/libqtevernote/notesstore.cpp	2015-06-11 18:56:43 +0000
@@ -41,6 +41,7 @@
 #include "jobs/fetchtagsjob.h"
 #include "jobs/createtagjob.h"
 #include "jobs/savetagjob.h"
+#include "jobs/expungetagjob.h"
 
 #include "libintl.h"
 
@@ -404,12 +405,17 @@
 
 void NotesStore::expungeNotebook(const QString &guid)
 {
+#ifdef NO_EXPUNGE_NOTEBOOKS
+    // This snipped can be used if the app is compiled with a restricted api key
+    // that can't expunge notebooks on Evernote. Compile with
+    // cmake -DNO_EXPUNGE_NOTEBOOKS=1
     if (m_username != "@local") {
         qCWarning(dcNotesStore) << "Account managed by Evernote. Cannot delete notebooks.";
         m_errorQueue.append(QString(gettext("This account is managed by Evernote. Use the Evernote website to delete notebooks.")));
         emit errorChanged();
         return;
     }
+#endif
 
     Notebook* notebook = m_notebooksHash.value(guid);
     if (!notebook) {
@@ -453,17 +459,33 @@
         }
     }
 
-    m_notebooks.removeAll(notebook);
-    m_notebooksHash.remove(notebook->guid());
-    emit notebookRemoved(notebook->guid());
-
-    QSettings settings(m_cacheFile, QSettings::IniFormat);
-    settings.beginGroup("notebooks");
-    settings.remove(notebook->guid());
-    settings.endGroup();
-
-    notebook->deleteInfoFile();
-    notebook->deleteLater();
+    if (notebook->lastSyncedSequenceNumber() == 0) {
+        emit notebookRemoved(notebook->guid());
+        m_notebooks.removeAll(notebook);
+        m_notebooksHash.remove(notebook->guid());
+        emit notebookRemoved(notebook->guid());
+
+        QSettings settings(m_cacheFile, QSettings::IniFormat);
+        settings.beginGroup("notebooks");
+        settings.remove(notebook->guid());
+        settings.endGroup();
+
+        notebook->deleteInfoFile();
+        notebook->deleteLater();
+    } else {
+        qCDebug(dcNotesStore) << "Setting notebook to deleted:" << notebook->guid();
+        notebook->setDeleted(true);
+        notebook->setUpdateSequenceNumber(notebook->updateSequenceNumber()+1);
+        emit notebookChanged(notebook->guid());
+        syncToCacheFile(notebook);
+        saveNotebook(notebook->guid());
+
+        if (EvernoteConnection::instance()->isConnected()) {
+            ExpungeNotebookJob *job = new ExpungeNotebookJob(guid, this);
+            connect(job, &ExpungeNotebookJob::jobDone, this, &NotesStore::expungeNotebookJobDone);
+            EvernoteConnection::instance()->enqueue(job);
+        }
+    }
 }
 
 QList<Tag *> NotesStore::tags() const
@@ -560,6 +582,33 @@
     syncToCacheFile(tag);
 }
 
+void NotesStore::expungeTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid)
+{
+    handleUserError(errorCode);
+    if (errorCode != EvernoteConnection::ErrorCodeNoError) {
+        qCWarning(dcSync) << "Error expunging tag:" << errorMessage;
+        return;
+    }
+
+    if (!m_tagsHash.contains(guid)) {
+        qCWarning(dcSync) << "Received a response for a expungeTag call, but can't find tag around any more.";
+        return;
+    }
+
+    emit tagRemoved(guid);
+    Tag *tag = m_tagsHash.take(guid);
+    m_tags.removeAll(tag);
+
+    QSettings cacheFile(m_cacheFile, QSettings::IniFormat);
+    cacheFile.beginGroup("tags");
+    cacheFile.remove(guid);
+    cacheFile.endGroup();
+    tag->syncToInfoFile();
+
+    tag->deleteInfoFile();
+    tag->deleteLater();
+}
+
 void NotesStore::tagNote(const QString &noteGuid, const QString &tagGuid)
 {
     Note *note = m_notesHash.value(noteGuid);
@@ -1030,14 +1079,19 @@
                 syncToCacheFile(notebook);
             }
         } else {
-            // Local notebook changed. See if we can push our changes
             if (result.updateSequenceNum == notebook->lastSyncedSequenceNumber()) {
-                qCDebug(dcNotesStore) << "Local Notebook changed. Uploading changes to Evernote:" << notebook->guid();
-                SaveNotebookJob *job = new SaveNotebookJob(notebook);
-                connect(job, &SaveNotebookJob::jobDone, this, &NotesStore::saveNotebookJobDone);
-                EvernoteConnection::instance()->enqueue(job);
-                notebook->setLoading(true);
-                emit notebookChanged(notebook->guid());
+                // Local notebook changed. See if we can push our changes
+                if (notebook->deleted()) {
+                    qCDebug(dcNotesStore) << "Local notebook has been deleted. Deleting from server";
+                    expungeNotebook(notebook->guid());
+                } else {
+                    qCDebug(dcNotesStore) << "Local Notebook changed. Uploading changes to Evernote:" << notebook->guid();
+                    SaveNotebookJob *job = new SaveNotebookJob(notebook);
+                    connect(job, &SaveNotebookJob::jobDone, this, &NotesStore::saveNotebookJobDone);
+                    EvernoteConnection::instance()->enqueue(job);
+                    notebook->setLoading(true);
+                    emit notebookChanged(notebook->guid());
+                }
             } else {
                 qCWarning(dcNotesStore) << "Sync conflict in notebook:" << notebook->name();
                 qCWarning(dcNotesStore) << "Resolving of sync conflicts is not implemented yet.";
@@ -1134,11 +1188,16 @@
         } else {
             // local tag changed. See if we can sync it to the server
             if (result.updateSequenceNum == tag->lastSyncedSequenceNumber()) {
-                SaveTagJob *job = new SaveTagJob(tag);
-                connect(job, &SaveTagJob::jobDone, this, &NotesStore::saveTagJobDone);
-                EvernoteConnection::instance()->enqueue(job);
-                tag->setLoading(true);
-                emit tagChanged(tag->guid());
+                if (tag->deleted()) {
+                    qCDebug(dcNotesStore) << "Tag has been deleted locally";
+                    expungeTag(tag->guid());
+                } else {
+                    SaveTagJob *job = new SaveTagJob(tag);
+                    connect(job, &SaveTagJob::jobDone, this, &NotesStore::saveTagJobDone);
+                    EvernoteConnection::instance()->enqueue(job);
+                    tag->setLoading(true);
+                    emit tagChanged(tag->guid());
+                }
             } else {
                 qCWarning(dcSync) << "CONFLICT in tag" << tag->name();
                 tag->setSyncError(true);
@@ -1473,9 +1532,22 @@
         qCWarning(dcSync) << "Error expunging notebook:" << errorMessage;
         return;
     }
+
+    if (!m_notebooksHash.contains(guid)) {
+        qCWarning(dcSync) << "Received a response for a expungeNotebook call, but can't find notebook around any more.";
+        return;
+    }
+
     emit notebookRemoved(guid);
     Notebook *notebook = m_notebooksHash.take(guid);
     m_notebooks.removeAll(notebook);
+
+    QSettings settings(m_cacheFile, QSettings::IniFormat);
+    settings.beginGroup("notebooks");
+    settings.remove(notebook->guid());
+    settings.endGroup();
+
+    notebook->deleteInfoFile();
     notebook->deleteLater();
 }
 
@@ -1712,12 +1784,18 @@
 
 void NotesStore::expungeTag(const QString &guid)
 {
+#ifdef NO_EXPUNGE_TAGS
+    // This snipped can be used if the app is compiled with a restricted api key
+    // that can't expunge tags on Evernote. Compile with
+    // cmake -DNO_EXPUNGE_TAGS=1
+
     if (m_username != "@local") {
         qCWarning(dcNotesStore) << "This account is managed by Evernote. Cannot delete tags.";
         m_errorQueue.append(gettext("This account is managed by Evernote. Please use the Evernote website to delete tags."));
         emit errorChanged();
         return;
     }
+#endif
 
     Tag *tag = m_tagsHash.value(guid);
     if (!tag) {
@@ -1730,23 +1808,39 @@
         Note *note = m_notesHash.value(noteGuid);
         if (!note) {
             qCWarning(dcNotesStore) << "Tag holds note" << noteGuid << "which hasn't been found in Notes Store";
+            Q_ASSERT(false);
             continue;
         }
         untagNote(noteGuid, guid);
     }
 
-    emit tagRemoved(guid);
-    m_tagsHash.remove(guid);
-    m_tags.removeAll(tag);
-
-    QSettings cacheFile(m_cacheFile, QSettings::IniFormat);
-    cacheFile.beginGroup("tags");
-    cacheFile.remove(guid);
-    cacheFile.endGroup();
-    tag->syncToInfoFile();
-
-    tag->deleteInfoFile();
-    tag->deleteLater();
+    if (tag->lastSyncedSequenceNumber() == 0) {
+        emit tagRemoved(guid);
+        m_tagsHash.remove(guid);
+        m_tags.removeAll(tag);
+
+        QSettings cacheFile(m_cacheFile, QSettings::IniFormat);
+        cacheFile.beginGroup("tags");
+        cacheFile.remove(guid);
+        cacheFile.endGroup();
+        tag->syncToInfoFile();
+
+        tag->deleteInfoFile();
+        tag->deleteLater();
+    } else {
+        qCDebug(dcNotesStore) << "Setting tag to deleted:" << tag->guid();
+        tag->setDeleted(true);
+        tag->setUpdateSequenceNumber(tag->updateSequenceNumber()+1);
+        emit tagChanged(tag->guid());
+        syncToCacheFile(tag);
+        saveTag(tag->guid());
+
+        if (EvernoteConnection::instance()->isConnected()) {
+            ExpungeTagJob *job = new ExpungeTagJob(guid, this);
+            connect(job, &ExpungeTagJob::jobDone, this, &NotesStore::expungeTagJobDone);
+            EvernoteConnection::instance()->enqueue(job);
+        }
+    }
 }
 
 void NotesStore::resolveConflict(const QString &noteGuid, NotesStore::ConflictResolveMode mode)

=== modified file 'src/libqtevernote/notesstore.h'
--- src/libqtevernote/notesstore.h	2015-03-15 20:00:21 +0000
+++ src/libqtevernote/notesstore.h	2015-06-11 18:56:43 +0000
@@ -197,6 +197,7 @@
     void fetchTagsJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Tag> &results);
     void createTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &tmpGuid, const evernote::edam::Tag &result);
     void saveTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Tag &result);
+    void expungeTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid);
 
     void syncToCacheFile(Note *note);
     void deleteFromCacheFile(Note* note);

=== modified file 'src/libqtevernote/tag.cpp'
--- src/libqtevernote/tag.cpp	2015-03-04 20:30:55 +0000
+++ src/libqtevernote/tag.cpp	2015-06-11 18:56:43 +0000
@@ -30,11 +30,13 @@
     m_updateSequenceNumber(updateSequenceNumber),
     m_guid(guid),
     m_loading(false),
-    m_syncError(false)
+    m_syncError(false),
+    m_deleted(false)
 {
     setGuid(guid);
     QSettings infoFile(m_infoFile, QSettings::IniFormat);
     m_name = infoFile.value("name").toString();
+    m_deleted = infoFile.value("deleted").toBool();
     m_lastSyncedSequenceNumber = infoFile.value("lastSyncedSequenceNumber", 0).toUInt();
     m_synced = m_lastSyncedSequenceNumber == m_updateSequenceNumber;
 
@@ -129,6 +131,7 @@
 {
     Tag *tag = new Tag(m_guid, m_updateSequenceNumber);
     tag->setName(m_name);
+    tag->setDeleted(m_deleted);
     return tag;
 }
 
@@ -178,6 +181,7 @@
 {
     QSettings infoFile(m_infoFile, QSettings::IniFormat);
     infoFile.setValue("name", m_name);
+    infoFile.setValue("deleted", m_deleted);
     infoFile.setValue("lastSyncedSequenceNumber", m_lastSyncedSequenceNumber);
 }
 
@@ -212,6 +216,11 @@
     return m_syncError;
 }
 
+bool Tag::deleted() const
+{
+    return m_deleted;
+}
+
 void Tag::setSyncError(bool syncError)
 {
     if (m_syncError != syncError) {
@@ -220,6 +229,14 @@
     }
 }
 
+void Tag::setDeleted(bool deleted)
+{
+    if (m_deleted != deleted) {
+        m_deleted = deleted;
+        emit deletedChanged();
+    }
+}
+
 
 QString Tag::noteAt(int index) const
 {

=== modified file 'src/libqtevernote/tag.h'
--- src/libqtevernote/tag.h	2015-03-06 00:42:42 +0000
+++ src/libqtevernote/tag.h	2015-06-11 18:56:43 +0000
@@ -38,6 +38,7 @@
     Q_PROPERTY(QString guid READ guid NOTIFY guidChanged)
     Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
     Q_PROPERTY(int noteCount READ noteCount NOTIFY noteCountChanged)
+    Q_PROPERTY(bool deleted READ deleted NOTIFY deletedChanged)
     // Don't forget to update clone() if you add new properties
 
     Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
@@ -65,6 +66,7 @@
     bool loading() const;
     bool synced() const;
     bool syncError() const;
+    bool deleted() const;
 
     Tag *clone();
 
@@ -75,6 +77,7 @@
     void loadingChanged();
     void syncedChanged();
     void syncErrorChanged();
+    void deletedChanged();
 
 private slots:
     void noteAdded(const QString &noteGuid, const QString &notebookGuid);
@@ -88,12 +91,14 @@
     void setLastSyncedSequenceNumber(qint32 lastSyncedSequenceNumber);
     void setLoading(bool loading);
     void setSyncError(bool syncError);
+    void setDeleted(bool deleted);
 
 private:
     qint32 m_updateSequenceNumber;
     qint32 m_lastSyncedSequenceNumber;
     QString m_guid;
     QString m_name;
+    bool m_deleted;
 
     QList<QString> m_notesList;
 

=== modified file 'src/libqtevernote/tags.cpp'
--- src/libqtevernote/tags.cpp	2015-03-06 00:47:45 +0000
+++ src/libqtevernote/tags.cpp	2015-06-11 18:56:43 +0000
@@ -61,6 +61,8 @@
         return tag->synced();
     case RoleSyncError:
         return tag->syncError();
+    case RoleDeleted:
+        return tag->deleted();
     }
     return QVariant();
 }
@@ -80,6 +82,7 @@
     roles.insert(RoleLoading, "loading");
     roles.insert(RoleSynced, "synced");
     roles.insert(RoleSyncError, "syncError");
+    roles.insert(RoleDeleted, "deleted");
     return roles;
 }
 
@@ -104,6 +107,7 @@
     connect(tag, &Tag::loadingChanged, this, &Tags::tagLoadingChanged);
     connect(tag, &Tag::syncedChanged, this, &Tags::syncedChanged);
     connect(tag, &Tag::syncErrorChanged, this, &Tags::syncErrorChanged);
+    connect(tag, &Tag::deletedChanged, this, &Tags::deletedChanged);
 
     beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
     m_list.append(guid);
@@ -128,6 +132,13 @@
     }
 }
 
+void Tags::deletedChanged()
+{
+    Tag *tag = static_cast<Tag*>(sender());
+    int idx = m_list.indexOf(tag->guid());
+    emit dataChanged(index(idx), index(idx), QVector<int>() << RoleDeleted);
+}
+
 void Tags::nameChanged()
 {
     Tag *tag = static_cast<Tag*>(sender());

=== modified file 'src/libqtevernote/tags.h'
--- src/libqtevernote/tags.h	2015-03-04 00:23:45 +0000
+++ src/libqtevernote/tags.h	2015-06-11 18:56:43 +0000
@@ -38,7 +38,8 @@
         RoleNoteCount,
         RoleLoading,
         RoleSynced,
-        RoleSyncError
+        RoleSyncError,
+        RoleDeleted
     };
     explicit Tags(QObject *parent = 0);
 
@@ -62,6 +63,7 @@
     void tagAdded(const QString &guid);
     void tagRemoved(const QString &guid);
     void tagGuidChanged(const QString &oldGuid, const QString &newGuid);
+    void deletedChanged();
 
     void nameChanged();
     void noteCountChanged();


Follow ups