[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