/*************************************************************************** * Copyright (C) 2013 OPENTIA Group http://opentia.com * * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * * This program 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include #include #include namespace TaskManager { ActivitySortingStrategy::ActivitySortingStrategy(QObject *parent) :AbstractSortingStrategy(parent) { setType(GroupManager::ActivitySorting); } class ActivitySortingStrategy::Comparator { public: Comparator(QStringList *activitiesOrder, GroupManager *groupManager) { m_activitiesOrder = activitiesOrder; m_groupManager = groupManager; } bool operator()(const AbstractGroupableItem *i1, const AbstractGroupableItem *i2) { if (m_groupManager && m_groupManager->separateLaunchers()) { if (i1->isStartupItem()) { if (i2->isStartupItem()) { return i1->name().toLower() < i2->name().toLower(); } return false; } if (i2->isStartupItem()) { return true; } if (i1->itemType() == LauncherItemType) { if (i2->itemType() == LauncherItemType) { return i1->name().toLower() < i2->name().toLower(); } return true; } if (i2->itemType() == LauncherItemType) { return false; } } if (!m_priorityCache.contains(i1->id())) { addToCache(i1); } if (!m_priorityCache.contains(i2->id())) { addToCache(i2); } QList::const_iterator it1 = m_priorityCache[i1->id()].constBegin(); QList::const_iterator it2 = m_priorityCache[i2->id()].constBegin(); QList::const_iterator i1end = m_priorityCache[i1->id()].constEnd(); QList::const_iterator i2end = m_priorityCache[i2->id()].constEnd(); while (it1 != i1end) { if (it2 == i2end) { return true; } else if (*it1 == *it2) { it1++; it2++; } else { return *it1 < *it2; } } return false; } private: QList getActivitiesIndexes(const AbstractGroupableItem *item) { QList cacheEntry; const TaskItem *taskItem = qobject_cast(item); if (taskItem) { Q_FOREACH(QString activity, taskItem->activities()) { cacheEntry << m_activitiesOrder->indexOf(activity); } } const TaskGroup *taskGroup = qobject_cast(item); if (taskGroup) { Q_FOREACH(AbstractGroupableItem *member, taskGroup->members()) { QList memberIndexes = getActivitiesIndexes(member); Q_FOREACH(int i, memberIndexes) { if (!cacheEntry.contains(i)) { cacheEntry << i; } } } } return cacheEntry; } void addToCache(const AbstractGroupableItem *item) { QList cacheEntry = getActivitiesIndexes(item); qSort(cacheEntry.begin(), cacheEntry.end()); m_priorityCache[item->id()] = cacheEntry; } GroupManager *m_groupManager; const QStringList *m_activitiesOrder; QHash > m_priorityCache; }; ActivitySortingStrategy::~ActivitySortingStrategy() { } void ActivitySortingStrategy::sortItems(ItemList& items) { if (m_activitiesOrder.isEmpty()) { checkActivitiesOrder(items); } Comparator comparator(&m_activitiesOrder, qobject_cast(parent())); qStableSort(items.begin(), items.end(), comparator); } void ActivitySortingStrategy::handleItem(AbstractGroupableItem* item) { connect(item, SIGNAL(changed(::TaskManager::TaskChanges)), this, SLOT(checkChanges(::TaskManager::TaskChanges))); AbstractSortingStrategy::handleItem(item); checkChanges(ActivitiesChanged, item); } bool ActivitySortingStrategy::lessThanActivityData(QPair< QString, int >& d1, QPair< QString, int >& d2) { if (d1.second == d2.second) { return d1.first < d2.first; } return d1.second > d2.second; } void ActivitySortingStrategy::addActivitiesToActivityCount(ItemList& items, QHash& activityCount) { Q_FOREACH(AbstractGroupableItem *item, items) { const TaskItem *taskItem = qobject_cast< const TaskItem* >(item); if (taskItem){ Q_FOREACH(QString activity, taskItem->activities()) { if (activityCount.contains(activity)) { activityCount[activity]++; } else { activityCount[activity] = 1; } } } const TaskGroup *taskGroup = qobject_cast< const TaskGroup* >(item); if (taskGroup) { ItemList subItems = taskGroup->members(); addActivitiesToActivityCount(subItems, activityCount); } } } bool ActivitySortingStrategy::checkActivitiesOrder(ItemList& items) { //Number of tasks by activity QHash activityCount; addActivitiesToActivityCount(items, activityCount); QList > activityData; Q_FOREACH(QString activity, activityCount.keys()) { activityData << QPair(activity, activityCount[activity]); } qSort(activityData.begin(), activityData.end(), lessThanActivityData); QStringList newActivitiesOrder; QList >::const_iterator it; for (it = activityData.constBegin(); it != activityData.constEnd(); it++) { newActivitiesOrder << it->first; } if (newActivitiesOrder != m_activitiesOrder) { m_activitiesOrder = newActivitiesOrder; return true; } return false; } void ActivitySortingStrategy::checkChanges(TaskChanges changes, AbstractGroupableItem *item) { if (!item) { item = qobject_cast< AbstractGroupableItem* >(sender()); } if (!item) { return; } if (changes & ActivitiesChanged) { if (!item->parentGroup()) { check(item); } else { TaskGroup* base = item->parentGroup(); while (base->parentGroup()) { base = base->parentGroup(); } ItemList items = base->members(); if (checkActivitiesOrder(items)) { //If the order of the activities has changed, all elements //should be put in order again sortItems(items); int i = 0; Q_FOREACH(AbstractGroupableItem *element, items) { moveItem(element, i); i++; } } else { check(item); } } } } }