From: APTX Date: Sun, 31 Mar 2013 19:26:16 +0000 (+0200) Subject: MyListModel now handles additions to the database. X-Git-Url: https://gitweb.aptx.org/?a=commitdiff_plain;h=1ab3c17f73676efd24e9ed04e42ffcde07a2e362;p=localmylist.git MyListModel now handles additions to the database. It also reorders rows caused by data updates. --- diff --git a/localmylist/database.cpp b/localmylist/database.cpp index dee3533..eac20af 100644 --- a/localmylist/database.cpp +++ b/localmylist/database.cpp @@ -1476,6 +1476,10 @@ void Database::subscribeToNotifications() d->db.driver()->subscribeToNotification("episode_update"); d->db.driver()->subscribeToNotification("file_update"); d->db.driver()->subscribeToNotification("file_location_update"); + d->db.driver()->subscribeToNotification("anime_insert"); + d->db.driver()->subscribeToNotification("episode_insert"); + d->db.driver()->subscribeToNotification("file_insert"); + d->db.driver()->subscribeToNotification("file_location_insert"); } OpenFileData Database::readOpenFileData(QSqlQuery &q) @@ -1786,6 +1790,48 @@ void Database::handleNotification(const QString &name, QSqlDriver::NotificationS if (id) emit fileLocationUpdate(id); } + else if (name == "anime_insert") + { + int id = payload.toInt(); + if (id) + emit animeInsert(id); + } + else if (name == "episode_insert") + { + QStringList ids = payload.toString().split(QChar(','), QString::SkipEmptyParts); + int eid = 0; + int aid = 0; + if (ids.count()) + eid = ids.takeFirst().toInt(); + if (ids.count()) + aid = ids.takeFirst().toInt(); + + if (eid) + emit episodeInsert(eid, aid); + } + else if (name == "file_insert") + { + QStringList ids = payload.toString().split(QChar(','), QString::SkipEmptyParts); + int fid = 0; + int eid = 0; + int aid = 0; + + if (ids.count()) + fid = ids.takeFirst().toInt(); + if (ids.count()) + eid = ids.takeFirst().toInt(); + if (ids.count()) + aid = ids.takeFirst().toInt(); + + if (fid) + emit fileUpdate(fid, eid, aid); + } + else if (name == "file_location_insert") + { + int id = payload.toInt(); + if (id) + emit fileLocationInsert(id); + } } diff --git a/localmylist/database.h b/localmylist/database.h index d569522..8493437 100644 --- a/localmylist/database.h +++ b/localmylist/database.h @@ -158,6 +158,11 @@ signals: void fileUpdate(int fid, int eid, int aid); void fileLocationUpdate(int id); + void animeInsert(int aid); + void episodeInsert(int eid, int aid); + void fileInsert(int fid, int eid, int aid); + void fileLocationInsert(int id); + private slots: void handleNotification(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload); diff --git a/localmylist/mylistmodel.cpp b/localmylist/mylistmodel.cpp index 4ac83e2..d3aa66a 100644 --- a/localmylist/mylistmodel.cpp +++ b/localmylist/mylistmodel.cpp @@ -18,6 +18,11 @@ MyListModel::MyListModel(QObject *parent) : connect(MyList::instance()->database(), SIGNAL(episodeUpdate(int,int)), this, SLOT(episodeUpdate(int,int))); connect(MyList::instance()->database(), SIGNAL(fileUpdate(int,int,int)), this, SLOT(fileUpdate(int,int,int))); connect(MyList::instance()->database(), SIGNAL(fileLocationUpdate(int)), this, SLOT(fileLocationUpdate(int))); + + connect(MyList::instance()->database(), SIGNAL(animeInsert(int)), this, SLOT(animeInsert(int))); + connect(MyList::instance()->database(), SIGNAL(episodeInsert(int,int)), this, SLOT(episodeInsert(int,int))); + connect(MyList::instance()->database(), SIGNAL(fileInsert(int,int,int)), this, SLOT(fileInsert(int,int,int))); + connect(MyList::instance()->database(), SIGNAL(fileLocationInsert(int)), this, SLOT(fileLocationInsert(int))); } MyListModel::~MyListModel() @@ -308,7 +313,8 @@ void MyListModel::animeUpdate(int aid) if (!updatedNode) return; - updatedNode->updated(); + if (updatedNode->updated(MyListNode::UpdateOperation)) + updatedNode->parent()->moveChild(updatedNode, MyListNode::UpdateOperation); } void MyListModel::episodeUpdate(int eid, int aid) @@ -320,7 +326,8 @@ void MyListModel::episodeUpdate(int eid, int aid) return; } - updatedNode->updated(); + if (updatedNode->updated(MyListNode::UpdateOperation)) + updatedNode->parent()->moveChild(updatedNode, MyListNode::UpdateOperation); } void MyListModel::fileUpdate(int fid, int eid, int aid) @@ -332,7 +339,8 @@ void MyListModel::fileUpdate(int fid, int eid, int aid) return; } - updatedNode->updated(); + if (updatedNode->updated(MyListNode::UpdateOperation)) + updatedNode->parent()->moveChild(updatedNode, MyListNode::UpdateOperation); } void MyListModel::fileLocationUpdate(int id) @@ -341,7 +349,55 @@ void MyListModel::fileLocationUpdate(int id) if (!updatedNode) return; - updatedNode->updated(); + if (updatedNode->updated(MyListNode::UpdateOperation)) + updatedNode->parent()->moveChild(updatedNode, MyListNode::UpdateOperation); +} + +void MyListModel::animeInsert(int aid) +{ + if (animeIndex(aid).isValid()) + return; + rootItem->childAdded(aid); +} + +void MyListModel::episodeInsert(int eid, int aid) +{ + if (episodeIndex(eid).isValid()) + return; + + MyListNode *parentNode = node(animeIndex(aid)); + + if (!parentNode) + return; + + parentNode->childAdded(eid); +} + +void MyListModel::fileInsert(int fid, int eid, int aid) +{ + if (fileIndex(fid).isValid()) + return; + + MyListNode *parentNode = node(episodeIndex(eid)); + + if (!parentNode) + { + parentNode = node(animeIndex(aid)); + if (!parentNode) + return; + parentNode->updated(MyListNode::UpdateOperation); + return; + } + + parentNode->childAdded(eid); +} + +void MyListModel::fileLocationInsert(int id) +{ + if (fileLocationIndex(id).isValid()) + return; + + } QModelIndex MyListModel::index(MyListNode *node) const diff --git a/localmylist/mylistmodel.h b/localmylist/mylistmodel.h index 0ccba04..e92e4a4 100644 --- a/localmylist/mylistmodel.h +++ b/localmylist/mylistmodel.h @@ -80,6 +80,11 @@ private slots: void fileUpdate(int fid, int eid, int aid); void fileLocationUpdate(int id); + void animeInsert(int aid); + void episodeInsert(int eid, int aid); + void fileInsert(int fid, int eid, int aid); + void fileLocationInsert(int id); + protected: QModelIndex index(MyListNode *node) const; void fetchFinished(MyListNode *node, int newrows); diff --git a/localmylist/mylistnode.cpp b/localmylist/mylistnode.cpp index 811d03c..ddf355c 100644 --- a/localmylist/mylistnode.cpp +++ b/localmylist/mylistnode.cpp @@ -5,6 +5,7 @@ #include "database.h" #include #include "sqlasyncquery.h" +#include #include namespace LocalMyList { @@ -154,21 +155,119 @@ QString MyListNode::totalRowCountSql() const return "SELECT COUNT(aid) FROM anime"; } -void MyListNode::childUpdate(const EpisodeData &oldData, const EpisodeData &newData) +void MyListNode::childUpdate(const EpisodeData &oldData, const EpisodeData &newData, Operation type) { Q_UNUSED(oldData) Q_UNUSED(newData) + Q_UNUSED(type) } -void MyListNode::childUpdate(const FileData &oldData, const FileData &newData) +void MyListNode::childUpdate(const FileData &oldData, const FileData &newData, Operation type) { Q_UNUSED(oldData) - Q_UNUSED(newData)} + Q_UNUSED(newData) + Q_UNUSED(type) +} -void MyListNode::childUpdate(const FileLocationData &oldData, const FileLocationData &newData) +void MyListNode::childUpdate(const FileLocationData &oldData, const FileLocationData &newData, Operation type) { Q_UNUSED(oldData) Q_UNUSED(newData) + Q_UNUSED(type) +} + +MyListNodeCompare MyListNode::compareFunction() const +{ + return [](MyListNode *a, MyListNode *b) -> bool + { + const MyListAnimeNode *aa = static_cast(a); + const MyListAnimeNode *ab = static_cast(b); + return aa->internalData().data.titleRomaji < ab->internalData().data.titleRomaji; + }; +} + +MyListNode::MoveType MyListNode::moveChild(MyListNode *child, Operation type) +{ + const QModelIndex idx = model->index(this); + + if (type == InsertOperation) + { + auto it = std::upper_bound(childItems.begin(), childItems.end(), child, compareFunction()); + + if (it == childItems.end() && canFetchMore()) + { + delete child; + return OutOfBoundsMove; + } + + const int newRow = qMax(0, (it - childItems.begin()) - 1); + + model->beginInsertRows(idx, newRow, newRow); + it = childItems.insert(it, child); + model->endInsertRows(); + return SuccessfulMove; + } + + const auto oldPos = std::find(childItems.begin(), childItems.end(), child); + const int oldRow = oldPos == childItems.end() ? -1 : oldPos - childItems.begin(); + + if (type == DeleteOperation) + { + if (oldRow != -1) + { + model->beginRemoveRows(idx, oldRow, oldRow); + childItems.removeAt(oldRow); + model->endRemoveRows(); + } + delete child; + return SuccessfulMove; + } + + auto lower = std::upper_bound(childItems.begin(), oldPos, child, compareFunction()); + auto upper = std::lower_bound(oldPos, childItems.end(), child, compareFunction()); + + // No move needed + if (lower == upper) + { + return NoMove; + } + + decltype(childItems.begin()) it; + + // New pos in upper part + if (lower == oldPos) + it = upper; + else + it = lower; + + // Added item is not in the currently loaded data + if (it == childItems.end() && canFetchMore()) + { + model->beginRemoveRows(idx, oldRow, oldRow); + childItems.removeAt(oldRow); + model->endRemoveRows(); + delete child; + + return OutOfBoundsMove; + } + + const int nextRow = it - childItems.begin(); + const int newRow = qMax(0, nextRow - 1); + + if (oldRow < newRow) + { + model->beginMoveRows(idx, oldRow, oldRow, idx, nextRow); + childItems.move(oldRow, newRow); + model->endMoveRows(); + } + else + { + model->beginMoveRows(idx, oldRow, oldRow, idx, newRow); + childItems.move(oldRow, nextRow); + model->endMoveRows(); + } + + return SuccessfulMove; } MyListNode::NodeType MyListNode::type() const @@ -181,8 +280,25 @@ int MyListNode::id() const return 0; } -void MyListNode::updated() +void MyListNode::childAdded(int id) +{ + qDebug() << "childAdded" << id; + if (m_totalRowCount == -1) + return; + + MyListAnimeNode *newChild = new MyListAnimeNode(model, AnimeData(id), this); + newChild->updated(InsertOperation); + + MoveType result = moveChild(newChild, InsertOperation); + + if (result == SuccessfulMove) + ++m_totalRowCount; +} + +bool MyListNode::updated(Operation type) { + Q_UNUSED(type) + return false; } // ------ @@ -270,42 +386,80 @@ int MyListAnimeNode::id() const return animeData.data.aid; } -void MyListAnimeNode::updated() +void MyListAnimeNode::childAdded(int id) +{ + qDebug() << "MyListAnimeNode::childAdded" << id << m_totalRowCount; + if (m_totalRowCount == -1) + return; + + MyListEpisodeNode *newChild = new MyListEpisodeNode(model, EpisodeData(id), this); + newChild->updated(InsertOperation); + + MoveType result = moveChild(newChild, InsertOperation); + + if (result == SuccessfulMove) + ++m_totalRowCount; +} + +bool MyListAnimeNode::updated(Operation type) { + Q_UNUSED(type) QSqlQuery q = MyList::instance()->database()->prepareOneShot(QString( " %1 " "WHERE a.aid = :aid").arg(baseQuery())); q.bindValue(":aid", id()); if(!MyList::instance()->database()->exec(q)) - return; + return false; if (!q.next()) - return; + return false; AnimeData newData; fillAnimeData(newData, QSqlResultIterator(q)); + + bool orderingChange = animeData.data.titleRomaji != newData.data.titleKanji; + animeData = newData; animeData.node = this; model->nodeChanged(this); + + return orderingChange; } -void MyListAnimeNode::childUpdate(const EpisodeData &oldData, const EpisodeData &newData) +void MyListAnimeNode::childUpdate(const EpisodeData &oldData, const EpisodeData &newData, Operation type) { // Episode got watched - if (!oldData.watchedDate.isValid() && newData.watchedDate.isValid()) + if ((type == InsertOperation || !oldData.watchedDate.isValid()) && newData.watchedDate.isValid()) { ++animeData.watchedEpisodes; model->nodeChanged(this); } // Episode got unwatched - else if (oldData.watchedDate.isValid() && !newData.watchedDate.isValid()) + else if ((type == DeleteOperation || !newData.watchedDate.isValid()) && oldData.watchedDate.isValid()) { --animeData.watchedEpisodes; model->nodeChanged(this); } } +MyListNodeCompare MyListAnimeNode::compareFunction() const +{ + return [](MyListNode *a, MyListNode *b) -> bool + { + const MyListEpisodeNode *aa = static_cast(a); + const MyListEpisodeNode *ab = static_cast(b); + if (aa->internalData().episodeTypeOrdering == ab->internalData().episodeTypeOrdering) + return aa->internalData().data.epno < ab->internalData().data.epno; + return aa->internalData().episodeTypeOrdering < ab->internalData().episodeTypeOrdering; + }; +} + +const AnimeData &MyListAnimeNode::internalData() const +{ + return animeData; +} + QString MyListAnimeNode::baseQuery() { return QString( @@ -422,33 +576,52 @@ int MyListEpisodeNode::id() const return episodeData.data.eid; } -void MyListEpisodeNode::updated() +void MyListEpisodeNode::childAdded(int id) +{ + if (m_totalRowCount == -1) + return; + + MyListFileNode *newChild = new MyListFileNode(model, FileData(id), this); + newChild->updated(InsertOperation); + + MoveType result = moveChild(newChild, InsertOperation); + + if (result == SuccessfulMove) + ++m_totalRowCount; +} + +bool MyListEpisodeNode::updated(Operation type) { + Q_UNUSED(type) QSqlQuery q = MyList::instance()->database()->prepareOneShot(QString( " %1 " "WHERE e.eid = :eid").arg(baseQuery())); q.bindValue(":eid", id()); if(!MyList::instance()->database()->exec(q)) - return; + return false; if (!q.next()) - return; + return false; EpisodeData newData; fillEpisodeData(newData, QSqlResultIterator(q)); - parent()->childUpdate(episodeData, newData); + parent()->childUpdate(episodeData, newData, type); + bool orderingChanged = episodeData.episodeTypeOrdering != newData.episodeTypeOrdering + || episodeData.data.epno != newData.data.epno; episodeData = newData; episodeData.node = this; model->nodeChanged(this); + + return orderingChanged; } -void MyListEpisodeNode::childUpdate(const FileData &oldData, const FileData &newData) +void MyListEpisodeNode::childUpdate(const FileData &oldData, const FileData &newData, Operation type) { // File from episode got watched - if (!oldData.data.myWatched.isValid() && newData.data.myWatched.isValid()) + if ((type == InsertOperation || !oldData.data.myWatched.isValid()) && newData.data.myWatched.isValid()) { if (!episodeData.watchedDate.isValid() || (episodeData.watchedDate.isValid() @@ -459,11 +632,11 @@ void MyListEpisodeNode::childUpdate(const FileData &oldData, const FileData &new episodeData.watchedDate = newData.data.myWatched; model->nodeChanged(this); - parent()->childUpdate(oldData, episodeData); + parent()->childUpdate(oldData, episodeData, UpdateOperation); } } // Watched date changed - else if (oldData.data.myWatched.isValid() && newData.data.myWatched.isValid()) + else if ((type == UpdateOperation && oldData.data.myWatched.isValid()) && newData.data.myWatched.isValid()) { if (episodeData.watchedDate.isValid() && newData.data.myWatched < episodeData.watchedDate) { @@ -472,18 +645,33 @@ void MyListEpisodeNode::childUpdate(const FileData &oldData, const FileData &new episodeData.watchedDate = newData.data.myWatched; model->nodeChanged(this); - parent()->childUpdate(oldData, episodeData); + parent()->childUpdate(oldData, episodeData, UpdateOperation); } } // File got unwatched - else if (oldData.data.myWatched.isValid() && !newData.data.myWatched.isValid()) + else if ((type == DeleteOperation || !newData.data.myWatched.isValid()) && oldData.data.myWatched.isValid()) { // No real way to get the proper watched date without // looking at other children. - updated(); + updated(UpdateOperation); } } +MyListNodeCompare MyListEpisodeNode::compareFunction() const +{ + return [](MyListNode *a, MyListNode *b) -> bool + { + const MyListFileNode *aa = static_cast(a); + const MyListFileNode *ab = static_cast(b); + return aa->internalData().data.fid < ab->internalData().data.fid; + }; +} + +const EpisodeData &MyListEpisodeNode::internalData() const +{ + return episodeData; +} + QString MyListEpisodeNode::baseQuery() { return QString( @@ -500,7 +688,7 @@ QString MyListEpisodeNode::baseQuery() " JOIN file_episode_rel fer ON (fer.fid = f.fid) " " WHERE fer.eid = e.eid " " AND my_watched IS NOT NULL) AS sq) AS my_watched, " - " %1 " + " et.ordering, %1 " " FROM episode e " " JOIN episode_type et ON (et.type = e.type)") .arg(Database::episodeFields()); @@ -509,7 +697,8 @@ QString MyListEpisodeNode::baseQuery() void MyListEpisodeNode::fillEpisodeData(EpisodeData &data, SqlResultIteratorInterface &query) { data.watchedDate = query.value(0).toDateTime(); - Database::readEpisodeData(query, data.data, 1); + data.episodeTypeOrdering = query.value(1).toInt(); + Database::readEpisodeData(query, data.data, 2); } // --------------- @@ -579,7 +768,12 @@ int MyListFileNode::id() const return fileData.data.fid; } -void MyListFileNode::updated() +void MyListFileNode::childAdded(int id) +{ + Q_UNUSED(id) +} + +bool MyListFileNode::updated(Operation type) { QSqlQuery q = MyList::instance()->database()->prepareOneShot(QString( "SELECT %1 " @@ -589,19 +783,36 @@ void MyListFileNode::updated() q.bindValue(":fid", id()); if(!MyList::instance()->database()->exec(q)) - return; + return false; if (!q.next()) - return; + return false; FileData newData; fillFileData(newData, QSqlResultIterator(q)); - parent()->childUpdate(fileData, newData); + parent()->childUpdate(fileData, newData, type); fileData = newData; fileData.node = this; model->nodeChanged(this); + + return false; +} + +MyListNodeCompare MyListFileNode::compareFunction() const +{ + return [](MyListNode *a, MyListNode *b) -> bool + { + const MyListFileLocationNode *aa = static_cast(a); + const MyListFileLocationNode *ab = static_cast(b); + return aa->internalData().data.locationId < ab->internalData().data.locationId; + }; +} + +const FileData &MyListFileNode::internalData() const +{ + return fileData; } QString MyListFileNode::baseQuery() @@ -669,7 +880,7 @@ int MyListFileLocationNode::id() const return fileLocationData.data.locationId; } -void MyListFileLocationNode::updated() +bool MyListFileLocationNode::updated(Operation type) { QSqlQuery q = MyList::instance()->database()->prepareOneShot(QString( " %1 " @@ -678,20 +889,26 @@ void MyListFileLocationNode::updated() q.bindValue(":locationId", id()); if(!MyList::instance()->database()->exec(q)) - return; + return false; if (!q.next()) - return; + return false; FileLocationData newData; fillFileLocationData(newData, QSqlResultIterator(q)); - parent()->childUpdate(fileLocationData, newData); + parent()->childUpdate(fileLocationData, newData, type); fileLocationData = newData; fileLocationData.node = this; model->nodeChanged(this); + return false; +} + +const FileLocationData &MyListFileLocationNode::internalData() const +{ + return fileLocationData; } QString MyListFileLocationNode::baseQuery() diff --git a/localmylist/mylistnode.h b/localmylist/mylistnode.h index fa429a9..ccc7226 100644 --- a/localmylist/mylistnode.h +++ b/localmylist/mylistnode.h @@ -12,6 +12,8 @@ class MyListModel; class SqlAsyncQuery; class SqlResultIteratorInterface; +typedef bool (*MyListNodeCompare)(MyListNode *a, MyListNode *b); + class LOCALMYLISTSHARED_EXPORT MyListNode { public: @@ -23,6 +25,18 @@ public: FileLocationNode }; + enum Operation { + UpdateOperation, + InsertOperation, + DeleteOperation + }; + + enum MoveType { + NoMove, + SuccessfulMove, + OutOfBoundsMove + }; + MyListNode(MyListModel *model, NodeType type = RootNode, MyListNode *parent = 0); virtual ~MyListNode(); @@ -47,10 +61,15 @@ public: NodeType type() const; virtual int id() const; - virtual void updated(); - virtual void childUpdate(const EpisodeData &oldData, const EpisodeData &newData); - virtual void childUpdate(const FileData &oldData, const FileData &newData); - virtual void childUpdate(const FileLocationData &oldData, const FileLocationData &newData); + virtual void childAdded(int id); + virtual bool updated(Operation type); + virtual void childUpdate(const EpisodeData &oldData, const EpisodeData &newData, Operation type); + virtual void childUpdate(const FileData &oldData, const FileData &newData, Operation type); + virtual void childUpdate(const FileLocationData &oldData, const FileLocationData &newData, Operation type); + + virtual MyListNodeCompare compareFunction() const; + + MoveType moveChild(MyListNode *child, Operation type); protected: virtual QString totalRowCountSql() const; @@ -82,8 +101,13 @@ public: void fetchMore(); void fetchComplete(); int id() const; - void updated(); - void childUpdate(const EpisodeData &oldData, const EpisodeData &newData); + void childAdded(int id); + bool updated(Operation type); + void childUpdate(const EpisodeData &oldData, const EpisodeData &newData, Operation type); + + MyListNodeCompare compareFunction() const; + + const AnimeData &internalData() const; static QString baseQuery(); static void fillAnimeData(AnimeData &data, SqlResultIteratorInterface &q); @@ -106,8 +130,13 @@ public: void fetchMore(); void fetchComplete(); int id() const; - void updated(); - void childUpdate(const FileData &oldData, const FileData &newData); + void childAdded(int id); + bool updated(Operation type); + void childUpdate(const FileData &oldData, const FileData &newData, Operation type); + + MyListNodeCompare compareFunction() const; + + const EpisodeData &internalData() const; static QString baseQuery(); static void fillEpisodeData(EpisodeData &data, SqlResultIteratorInterface &query); @@ -129,7 +158,12 @@ public: void fetchMore(); void fetchComplete(); int id() const; - void updated(); + void childAdded(int id); + bool updated(Operation type); + + MyListNodeCompare compareFunction() const; + + const FileData &internalData() const; static QString baseQuery(); static void fillFileData(FileData &data, SqlResultIteratorInterface &query); @@ -151,7 +185,9 @@ public: void fetchMore(); void fetchComplete(); int id() const; - void updated(); + bool updated(Operation type); + + const FileLocationData &internalData() const; static QString baseQuery(); static void fillFileLocationData(FileLocationData &data, SqlResultIteratorInterface &query); diff --git a/localmylist/mylistnodedata.h b/localmylist/mylistnodedata.h index 046f5ae..09e6efe 100644 --- a/localmylist/mylistnodedata.h +++ b/localmylist/mylistnodedata.h @@ -24,10 +24,6 @@ struct AnimeData : public boost::intrusive::set_base_hook< > AnimeData(int aid = 0) { data.aid = aid; } - - AnimeData(const Anime &animeData, int epsInML, int watchedEps) : data(animeData), node(0), - episodesInMyList(epsInML), watchedEpisodes(watchedEps) - {} }; struct EpisodeData : public boost::intrusive::set_base_hook< > @@ -36,16 +32,13 @@ struct EpisodeData : public boost::intrusive::set_base_hook< > MyListEpisodeNode *node; QDateTime watchedDate; + int episodeTypeOrdering; friend bool operator<(const EpisodeData &a, const EpisodeData &b) { return a.data.eid < b.data.eid; } EpisodeData(int eid = 0) { data.eid = eid; } - - EpisodeData(const Episode &episodeData, const QDateTime &watchedDate_) - : data(episodeData), node(0), watchedDate(watchedDate_) - {} }; struct FileData : public boost::intrusive::set_base_hook< > @@ -58,10 +51,6 @@ struct FileData : public boost::intrusive::set_base_hook< > FileData(int fid = 0) { data.fid = fid; } - - FileData(const File &fileData) - : data(fileData), node(0) - {} }; struct FileLocationData : public boost::intrusive::set_base_hook< > @@ -76,10 +65,6 @@ struct FileLocationData : public boost::intrusive::set_base_hook< > FileLocationData(int locationId = 0) { data.locationId = locationId; } - - FileLocationData(const FileLocation &fileLocationData, const QString &hostName_) - : data(fileLocationData), node(0), hostName(hostName_) - {} }; } // namespace LocalMyList diff --git a/localmylist/share/schema/schema.sql b/localmylist/share/schema/schema.sql index fe3c07e..782f8ee 100644 --- a/localmylist/share/schema/schema.sql +++ b/localmylist/share/schema/schema.sql @@ -237,10 +237,6 @@ CREATE VIEW rename_data AS JOIN episode e ON e.eid = f.eid JOIN file_location fl ON fl.fid = f.fid; -CREATE RULE new_anime_rule AS ON INSERT TO anime DO NOTIFY rename_data_changed; -CREATE RULE new_episode_rule AS ON INSERT TO episode DO NOTIFY rename_data_changed; -CREATE RULE new_file_rule AS ON INSERT TO file DO NOTIFY rename_data_changed; - -- WHEN (OLD.* IS DISTINCT FROM NEW.*) <- means if anything changed CREATE RULE update_anime_rule AS ON UPDATE TO anime @@ -292,6 +288,22 @@ COMMENT ON RULE unknown_file_ignore_duplicate ON unknown_file IS 'Adding the sam CREATE RULE new_pending_mylist_update_rule AS ON INSERT TO pending_mylist_update DO NOTIFY new_pending_mylist_update; +-- Add rules +CREATE OR REPLACE RULE anime_insert_rule AS + ON INSERT TO anime DO SELECT pg_notify('rename_data_changed', ''), + pg_notify('anime_insert', new.aid::text); + +CREATE OR REPLACE RULE episode_insert_rule AS + ON INSERT TO episode DO SELECT pg_notify('rename_data_changed', ''), + pg_notify('episode_insert', new.eid::text || ',' || new.aid::text); + +CREATE OR REPLACE RULE file_insert_rule AS + ON INSERT TO file DO SELECT pg_notify('rename_data_changed', ''), + pg_notify('file_insert', new.fid::text || ',' || new.eid::text || ',' || new.aid::text); + +CREATE OR REPLACE RULE file_location_insert_rule AS + ON INSERT TO file_location DO SELECT + pg_notify('file_location_insert', new.location_id::text); -- Update rules CREATE OR REPLACE RULE anime_update_rule AS