[SCM] ktp-text-ui packaging branch, master, updated. debian/15.12.1-1-1918-gdf4b0ec

Maximiliano Curia maxy at moszumanska.debian.org
Sat May 28 00:24:19 UTC 2016


Gitweb-URL: http://git.debian.org/?p=pkg-kde/applications/ktp-text-ui.git;a=commitdiff;h=752dae9

The following commit has been merged in the master branch:
commit 752dae9e50691d0cdc82cbb3f389849445f75092
Author: Dan Vrátil <dvratil at redhat.com>
Date:   Wed Oct 23 14:30:48 2013 +0200

    Rewrite DatesModel to be more failproof
    
    REVIEW: 113331
---
 logviewer/dates-model.cpp | 461 ++++++++++++++++++++++++++--------------------
 logviewer/dates-model.h   |  14 +-
 2 files changed, 263 insertions(+), 212 deletions(-)

diff --git a/logviewer/dates-model.cpp b/logviewer/dates-model.cpp
index db2d058..cb9c8da 100644
--- a/logviewer/dates-model.cpp
+++ b/logviewer/dates-model.cpp
@@ -31,39 +31,177 @@
 
 Q_DECLARE_METATYPE(Tp::AccountPtr)
 
-class DatesModel::Date
+typedef QPair<Tp::AccountPtr, KTp::LogEntity> AccountEntityPair;
+
+class Node
 {
   public:
+    enum Type {
+        Root,
+        Month,
+        Date,
+        Account
+    };
+    Node(Type type, const QDate &date = QDate(), Node *parent = 0);
+    virtual ~Node();
+
+    void addChild(Node *child);
+    Node* prevSibling() const;
+    Node* nextSibling() const;
+
+    Type type;
     QDate date;
-    QList<AccountEntityPair> matches;
+
+    Node* parent;
+    QList<Node*> children;
+};
+
+class DateNode: public Node
+{
+  public:
+    DateNode(const QDate &date, const KTp::LogEntity &entity, Node *parent = 0);
+    virtual ~DateNode();
+
+    KTp::LogEntity entity;
+};
+
+class AccountNode: public DateNode
+{
+  public:
+    AccountNode(const QDate &date, const Tp::AccountPtr &account,
+                const KTp::LogEntity &entity, Node *parent = 0);
+    ~AccountNode();
+
+    Tp::AccountPtr account;
+};
+
+
+class DatesModel::Private
+{
+  public:
+    Private();
+    ~Private();
+
+    Node* nodeForDate(const QDate &date, Node *parent);
+
+    QList<KTp::LogSearchHit> searchHits;
+    int resetInProgress;
+
+    Node *rootNode;
+
+    QList<KTp::PendingLoggerOperation*> pendingDates;
 };
 
-bool sortDatesDescending(const DatesModel::Date* date1, const DatesModel::Date* date2)
+Node::Node(Node::Type type_, const QDate &date_, Node *parent_):
+    type(type_),
+    date(date_)
+{
+    if (parent_) {
+        parent_->addChild(this);
+    }
+}
+
+Node::~Node()
+{
+    qDeleteAll(children);
+}
+
+void Node::addChild(Node *child)
+{
+    children.append(child);
+    child->parent = this;
+}
+
+Node* Node::nextSibling() const
+{
+    if (!parent || parent->children.indexOf(const_cast<Node*>(this)) == parent->children.count() - 1) {
+        return 0;
+    }
+
+    return parent->children.at(parent->children.indexOf(const_cast<Node*>(this)) + 1);
+}
+
+Node* Node::prevSibling() const
+{
+    if (!parent || parent->children.indexOf(const_cast<Node*>(this)) == 0) {
+        return 0;
+    }
+
+    return parent->children.at(parent->children.indexOf(const_cast<Node*>(this)) - 1);
+}
+
+DateNode::DateNode(const QDate &date, const KTp::LogEntity &entity_, Node *parent):
+    Node(Node::Date, date, parent),
+    entity(entity_)
+{
+}
+
+DateNode::~DateNode()
+{
+}
+
+AccountNode::AccountNode(const QDate &date_, const Tp::AccountPtr &account_,
+                         const KTp::LogEntity &entity_, Node* parent):
+    DateNode(date_, entity_, parent),
+    account(account_)
+{
+    type = Node::Account;
+}
+
+AccountNode::~AccountNode()
+{
+}
+
+DatesModel::Private::Private():
+    resetInProgress(0),
+    rootNode(new Node(Node::Root))
+{
+}
+
+DatesModel::Private::~Private()
+{
+    delete rootNode;
+}
+
+Node* DatesModel::Private::nodeForDate(const QDate &date, Node* parent)
+{
+    Q_FOREACH (Node *node, parent->children) {
+        if (node->date == date) {
+            return node;
+        }
+    }
+
+    return 0;
+}
+
+
+bool sortDatesDescending(const Node* date1, const Node* date2)
 {
     return date1->date > date2->date;
 }
 
 DatesModel::DatesModel(QObject* parent):
     QAbstractItemModel(parent),
-    m_resetInProgress(0)
+    d(new Private)
 {
 }
 
 DatesModel::~DatesModel()
 {
     clear();
+    delete d;
 }
 
 void DatesModel::addEntity(const Tp::AccountPtr &account, const KTp::LogEntity &entity)
 {
-    if (m_resetInProgress == 0) {
+    if (d->resetInProgress == 0) {
         beginResetModel();
     }
-    ++m_resetInProgress;
+    ++d->resetInProgress;
 
     KTp::LogManager *logManager = KTp::LogManager::instance();
     KTp::PendingLoggerDates *pendingDates = logManager->queryDates(account, entity);
-    m_pendingDates << pendingDates;
+    d->pendingDates << pendingDates;
     connect(pendingDates, SIGNAL(finished(KTp::PendingLoggerOperation*)),
             SLOT(onDatesReceived(KTp::PendingLoggerOperation*)));
 }
@@ -76,29 +214,26 @@ void DatesModel::setEntity(const Tp::AccountPtr &account, const KTp::LogEntity &
 
 void DatesModel::setSearchHits(const QList<KTp::LogSearchHit> &searchHits)
 {
-    m_searchHits = searchHits;
+    d->searchHits = searchHits;
 }
 
 void DatesModel::clearSearchHits()
 {
-    m_searchHits.clear();
+    d->searchHits.clear();
 }
 
 void DatesModel::clear()
 {
     beginResetModel();
-    m_resetInProgress = 0;
-    Q_FOREACH (KTp::PendingLoggerOperation *op, m_pendingDates) {
+    d->resetInProgress = 0;
+    Q_FOREACH (KTp::PendingLoggerOperation *op, d->pendingDates) {
         disconnect(op, SIGNAL(finished(KTp::PendingLoggerOperation*)));
         op->deleteLater();
     }
-    m_pendingDates.clear();
-    m_groups.clear();
-    Q_FOREACH (const QList<Date*> &list, m_items) {
-        qDeleteAll(list);
-    }
-    m_items.clear();
-    m_pairs.clear();
+    d->pendingDates.clear();
+    delete d->rootNode;
+    d->rootNode = new Node(Node::Root);
+
     // Don't reset searchHits!
     endResetModel();
 }
@@ -110,36 +245,25 @@ QDate DatesModel::nextDate(const QModelIndex &index) const
     }
 
     // Group - it should never be selected
-    if (index.internalId() == -1) {
+    Node *node = static_cast<Node*>(index.internalPointer());
+    if (node->type == Node::Root || node->type == Node::Month) {
         return QDate();
     }
 
     // Date
-    QModelIndex idx;
-    if (index.internalId() >= 0 && index.internalId() < m_groups.count()) {
-        idx = index;
-    } else {
-        idx = index.parent();
-    }
+    Node *dateNode = (node->type == Node::Date) ? node : node->parent;
+    Node *parentNode = dateNode->parent;
+    Node *nextDateNode = dateNode->nextSibling();
 
-    QModelIndex sibling;
-    if (idx.row() == 0) {
-        QModelIndex idxParent = idx.parent();
-        if (idxParent.row() == 0) {
+    if (!nextDateNode) {
+        parentNode = parentNode->nextSibling();
+        if (!parentNode) {
             return QDate();
-        } else {
-            idxParent = idxParent.sibling(idxParent.row() - 1, 0);
-            sibling = idxParent.child(rowCount(idxParent) - 1, 0);
         }
-    } else {
-        sibling = idx.sibling(idx.row() - 1, 0);
-    }
-
-    if (sibling.isValid()) {
-        return sibling.data(DatesModel::DateRole).toDate();
+        nextDateNode = parentNode->children.first();
     }
 
-    return QDate();
+    return nextDateNode->date;
 }
 
 QDate DatesModel::previousDate(const QModelIndex &index) const
@@ -149,47 +273,37 @@ QDate DatesModel::previousDate(const QModelIndex &index) const
     }
 
     // Group - it should never be selected
-    if (index.internalId() == -1) {
+    Node *node = static_cast<Node*>(index.internalPointer());
+    if (node->type == Node::Root || node->type == Node::Month) {
         return QDate();
     }
 
     // Date
-    QModelIndex idx;
-    if (index.internalId() >= 0 && index.internalId() < m_groups.count()) {
-        idx = index;
-    } else {
-        idx = index.parent();
-    }
+    Node *dateNode = (node->type == Node::Date) ? node : node->parent;
+    Node *parentNode = dateNode->parent;
+    Node *prevDateNode = dateNode->prevSibling();
 
-    QModelIndex sibling;
-    if (idx.row() == rowCount(idx.parent()) - 1) {
-        QModelIndex idxParent = idx.parent();
-        if (idxParent.row() == rowCount(idxParent.parent()) - 1) {
+    if (!prevDateNode) {
+        parentNode = parentNode->prevSibling();
+        if (!parentNode) {
             return QDate();
-        } else {
-            idxParent = idxParent.sibling(idxParent.row() + 1, 0);
-            sibling = idxParent.child(0, 0);
         }
-    } else {
-        sibling = idx.sibling(idx.row() + 1, 0);
+        prevDateNode = parentNode->children.last();
     }
 
-    if (sibling.isValid()) {
-        return sibling.data(DatesModel::DateRole).toDate();
-    }
-
-    return QDate();
+    return prevDateNode->date;
 }
 
 QModelIndex DatesModel::indexForDate(const QDate &date) const
 {
-    const QDate groupDate(date.year(), date.month(), 1);
-    const QModelIndex parent = index(m_groups.indexOf(groupDate), 0, QModelIndex());
-
-    QList<Date*> dates = m_items.value(groupDate);
-    for (int i = 0; i < dates.count(); ++i) {
-        if (dates[i]->date == date) {
-            return index(i, 0, parent);
+    // FIXME: Hash table?
+    const QList<Node*> groups = d->rootNode->children;
+    Q_FOREACH (Node *groupNode, groups) {
+        const QList<Node*> dates = groupNode->children;
+        Q_FOREACH (Node *dateNode, dates) {
+            if (dateNode->date == date) {
+                return createIndex(groupNode->children.indexOf(dateNode), 0, dateNode);
+            }
         }
     }
 
@@ -198,56 +312,52 @@ QModelIndex DatesModel::indexForDate(const QDate &date) const
 
 QVariant DatesModel::data(const QModelIndex &index, int role) const
 {
-    Date *date = 0;
-    AccountEntityPair pair;
-    bool isDate = false;
-
-    // It's a group
-    if (index.internalId() == -1) {
-        switch (role) {
-            case Qt::DisplayRole:
-                return m_groups.at(index.row()).toString(QLatin1String("MMMM yyyy"));
-            case DateRole:
-                return m_groups.at(index.row());
-            case TypeRole:
-                return DatesModel::GroupRow;
-            default:
-                return QVariant();
-        }
+    if (!index.isValid()) {
         return QVariant();
     }
 
-    // It's a date node
-    if (index.internalId() >= 0 && index.internalId() <= m_groups.count()) {
-        const QDate key = m_groups.at(index.parent().row());
-        date = m_items.value(key).at(index.row());
-        isDate = true;
-        if (date->matches.count() == 1) {
-            pair = date->matches.first();
-        }
-    // It's an account/entity node
-    } else {
-        date = static_cast<Date*>(index.internalPointer());
-        pair = date->matches.at(index.row());
+    Node *node = static_cast<Node*>(index.internalPointer());
+    if (role == DateRole) {
+        return node->date;
     }
 
-    switch (role) {
-        case Qt::DisplayRole:
-            return isDate
-                ? KLocalizedDate(date->date).formatDate()
-                : pair.first->displayName();
-        case TypeRole:
-            return isDate ? DatesModel::DateRow : DatesModel::ConversationRow;
-        case DateRole:
-            return date->date;
-        case HintRole:
-            return pair.first.isNull()
-                ? i18ncp("Number of existing conversations.", "%1 conversation", "%1 conversations", date->matches.count())
-                : pair.first->displayName();
-        case AccountRole:
-            return QVariant::fromValue<Tp::AccountPtr>(pair.first);
-        case EntityRole:
-            return QVariant::fromValue<KTp::LogEntity>(pair.second);
+    // It's a group
+    if (node->type == Node::Month) {
+        if (role == Qt::DisplayRole) {
+            return node->date.toString(QLatin1String("MMMM yyyy"));
+        } else if (role == TypeRole) {
+            return DatesModel::GroupRow;
+        }
+    } else if (node->type == Node::Date) {
+        if (role == Qt::DisplayRole) {
+            return KLocalizedDate(node->date).formatDate();
+        } else if (role == TypeRole) {
+            return DatesModel::DateRow;
+        } else if (role == HintRole) {
+            return i18ncp("Number of existing conversations.", "%1 conversation", "%1 conversations", node->children.count());
+        } else if (role == EntityRole) {
+            return QVariant::fromValue(static_cast<DateNode*>(node)->entity);
+        } else if (role == AccountRole) {
+            // If there's more than one account, have user pick one
+            if (node->children.count() > 1) {
+                return QVariant();
+            } else {
+                return QVariant::fromValue(static_cast<AccountNode*>(node->children.first())->account);
+            }
+        }
+    } else if (node->type == Node::Account) {
+        AccountNode *accountNode = static_cast<AccountNode*>(node);
+        if (role == Qt::DisplayRole) {
+            return accountNode->entity.alias();
+        } else if (role == HintRole) {
+            return accountNode->account->displayName();
+        } else if (role == TypeRole) {
+            return ConversationRow;
+        } else if (role == AccountRole) {
+            return QVariant::fromValue(accountNode->account);
+        } else if (role == EntityRole) {
+            return QVariant::fromValue(accountNode->entity);
+        }
     }
 
     return QVariant();
@@ -260,34 +370,23 @@ int DatesModel::columnCount(const QModelIndex &parent) const
     return 1;
 }
 
-int DatesModel::rowCount(const QModelIndex &parent) const
-{
+ int DatesModel::rowCount(const QModelIndex &parent) const
+ {
+    Node *parentNode = 0;
+
     // Groups
     if (!parent.isValid()) {
-        return m_groups.count();
-    }
-
-    // parent is a group, list dates
-    if (parent.internalId() == -1) {
-        const QDate key = m_groups.at(parent.row());
-        const QList<Date*> dates = m_items.value(key);
-        return dates.count();
+        parentNode = d->rootNode;
+    } else {
+        parentNode = static_cast<Node*>(parent.internalPointer());
     }
 
-    // parent is a date, list conversations
-    if (parent.internalId() >= 0 && parent.internalId() <= m_groups.count()) {
-        const QDate key = m_groups.at(parent.parent().row());
-        const QList<Date*> dates = m_items.value(key);
-        const Date *date = dates.at(parent.row());
-        // Only make the date expandable if there is more than one account
-        if (date->matches.count() == 1) {
-            return 0;
-        }
-        return date->matches.count();
+    // Don't make date expandable, if there is only one account
+    if (parentNode->type == Node::Date && parentNode->children.count() == 1) {
+        return 0;
     }
 
-    // parent is a conversation
-    return 0;
+    return parentNode->children.count();
 }
 
 QModelIndex DatesModel::parent(const QModelIndex &child) const
@@ -296,108 +395,70 @@ QModelIndex DatesModel::parent(const QModelIndex &child) const
         return QModelIndex();
     }
 
-    // Child is a group
-    if (child.internalId() == -1) {
+    Node *childNode = static_cast<Node*>(child.internalPointer());
+    Node *node = childNode->parent;
+    if (node == d->rootNode) {
         return QModelIndex();
     }
 
-    // Child is a date
-    if (child.internalId() >= 0 && child.internalId() < m_items.count()) {
-        return createIndex(child.internalId(), 0, -1);
-    }
-
-    // Child is a conversation
-    Date *date = static_cast<Date*>(child.internalPointer());
-    if (date) {
-        const QDate key = QDate(date->date.year(), date->date.month(), 1);
-        const QList<Date*> dates = m_items.value(key);
-        return createIndex(dates.indexOf(date), 0, m_items.uniqueKeys().indexOf(key));
-    }
-
-    // Assert?
-    return QModelIndex();
+    Node *parentNode = node->parent;
+    return createIndex(parentNode->children.indexOf(node), 0, node);
 }
 
 QModelIndex DatesModel::index(int row, int column, const QModelIndex &parent) const
 {
-    // Group
-    if (!parent.isValid()) {
-        return createIndex(row, column, -1);
-    }
-
-    // Date, id is index of parent group
-    if (parent.internalId() == -1) {
-        return createIndex(row, column, parent.row());
-    }
+    Node *parentNode = 0;
 
-    // Conversation, data is a pointer to parent date
-    if (!parent.internalId() >= 0) {
-        const QDate key = m_items.uniqueKeys().at(parent.internalId());
-        const QList<Date*> dates = m_items.value(key);
-        return createIndex(row, column, dates.at(parent.row()));
+    if (!parent.isValid()) {
+        parentNode = d->rootNode;
+    } else {
+        parentNode = static_cast<Node*>(parent.internalPointer());
     }
 
-    return QModelIndex();
+    return createIndex(row, column, parentNode->children.at(row));
 }
 
 void DatesModel::onDatesReceived(KTp::PendingLoggerOperation *operation)
 {
     // Stop here if clear() was called meanwhile
-    if (m_resetInProgress == 0) {
+    if (d->resetInProgress == 0) {
         return;
     }
 
     KTp::PendingLoggerDates *op = qobject_cast<KTp::PendingLoggerDates*>(operation);
     Q_ASSERT(op);
-    Q_ASSERT(m_pendingDates.contains(op));
+    Q_ASSERT(d->pendingDates.contains(op));
 
-    m_pendingDates.removeOne(op);
+    d->pendingDates.removeOne(op);
     op->deleteLater();
 
     QList<QDate> newDates = op->dates();
+
     Q_FOREACH (const QDate &newDate, newDates) {
         const QDate groupDate(newDate.year(), newDate.month(), 1);
-        if (!m_groups.contains(groupDate)) {
-            m_groups << groupDate;
-            // Sort dates in descending order
-            qStableSort(m_groups.begin(), m_groups.end(), qGreater<QDate>());
-
-            Date *date = new Date;
-            date->date = newDate;
-            date->matches << AccountEntityPair(op->account(), op->entity());
-            m_items.insert(groupDate, QList<Date*>() << date);
-            continue;
+        Node *groupNode = d->nodeForDate(groupDate, d->rootNode);
+        if (!groupNode) {
+            groupNode = new Node(Node::Month, groupDate, d->rootNode);
+            qStableSort(d->rootNode->children.begin(), d->rootNode->children.end(), sortDatesDescending);
         }
 
-        QList<Date*> dates = m_items.value(groupDate);
-        bool found = false;
-        Q_FOREACH (Date *date, dates) {
-            if (date->date == newDate) {
-                date->matches << AccountEntityPair(op->account(), op->entity());
-                found = true;
-                break;
-            }
+        DateNode *dateNode = static_cast<DateNode*>(d->nodeForDate(newDate, groupNode));
+        if (!dateNode) {
+            dateNode = new DateNode(newDate, op->entity(), groupNode);
+            qStableSort(groupNode->children.begin(), groupNode->children.end(), sortDatesDescending);
         }
 
-        if (found) {
-            continue;
+        if (!op->account().isNull()) {
+            new AccountNode(newDate, op->account(), op->entity(), dateNode);
         }
-
-        Date *date = new Date;
-        date->date = newDate;
-        date->matches << AccountEntityPair(op->account(), op->entity());
-        dates.append(date);
-
-        qStableSort(dates.begin(), dates.end(), sortDatesDescending);
-        m_items.insert(groupDate, dates);
     }
 
-    --m_resetInProgress;
-    if (m_resetInProgress == 0) {
+    --d->resetInProgress;
+    if (d->resetInProgress == 0) {
         endResetModel();
     }
 
-    if (m_pendingDates.isEmpty()) {
+    if (d->pendingDates.isEmpty()) {
         Q_EMIT datesReceived();
     }
 }
diff --git a/logviewer/dates-model.h b/logviewer/dates-model.h
index 773f3b0..f5ca5d0 100644
--- a/logviewer/dates-model.h
+++ b/logviewer/dates-model.h
@@ -82,18 +82,8 @@ class DatesModel : public QAbstractItemModel
     void onDatesReceived(KTp::PendingLoggerOperation *operation);
 
   private:
-    typedef QPair<Tp::AccountPtr, KTp::LogEntity> AccountEntityPair;
-    QList<AccountEntityPair> m_pairs;
-    QList<KTp::LogSearchHit> m_searchHits;
-    int m_resetInProgress;
-
-    class Date;
-    QList<QDate> m_groups;
-    QMap<QDate, QList<Date*> > m_items;
-
-    QList<KTp::PendingLoggerOperation*> m_pendingDates;
-
-    friend bool sortDatesDescending(const Date *date1, const Date *date2);
+    class Private;
+    Private * const d;
 };
 
 #endif // DATESMODEL_H

-- 
ktp-text-ui packaging



More information about the pkg-kde-commits mailing list