You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

248 lines
8.0 KiB

/***************************************************************************
* 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 <strategies/activitysortingstrategy.h>
#include <taskitem.h>
#include <taskgroup.h>
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<int>::const_iterator it1 = m_priorityCache[i1->id()].constBegin();
QList<int>::const_iterator it2 = m_priorityCache[i2->id()].constBegin();
QList<int>::const_iterator i1end = m_priorityCache[i1->id()].constEnd();
QList<int>::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<int> getActivitiesIndexes(const AbstractGroupableItem *item) {
QList<int> cacheEntry;
const TaskItem *taskItem = qobject_cast<const TaskItem*>(item);
if (taskItem) {
Q_FOREACH(QString activity, taskItem->activities()) {
cacheEntry << m_activitiesOrder->indexOf(activity);
}
}
const TaskGroup *taskGroup = qobject_cast<const TaskGroup*>(item);
if (taskGroup) {
Q_FOREACH(AbstractGroupableItem *member, taskGroup->members()) {
QList<int> memberIndexes = getActivitiesIndexes(member);
Q_FOREACH(int i, memberIndexes) {
if (!cacheEntry.contains(i)) {
cacheEntry << i;
}
}
}
}
return cacheEntry;
}
void addToCache(const AbstractGroupableItem *item) {
QList<int> cacheEntry = getActivitiesIndexes(item);
qSort(cacheEntry.begin(), cacheEntry.end());
m_priorityCache[item->id()] = cacheEntry;
}
GroupManager *m_groupManager;
const QStringList *m_activitiesOrder;
QHash<int, QList<int> > m_priorityCache;
};
ActivitySortingStrategy::~ActivitySortingStrategy()
{
}
void ActivitySortingStrategy::sortItems(ItemList& items)
{
if (m_activitiesOrder.isEmpty()) {
checkActivitiesOrder(items);
}
Comparator comparator(&m_activitiesOrder, qobject_cast<GroupManager *>(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<QString, int>& 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<QString, int> activityCount;
addActivitiesToActivityCount(items, activityCount);
QList<QPair<QString, int> > activityData;
Q_FOREACH(QString activity, activityCount.keys()) {
activityData << QPair<QString, int>(activity, activityCount[activity]);
}
qSort(activityData.begin(), activityData.end(), lessThanActivityData);
QStringList newActivitiesOrder;
QList<QPair<QString, int> >::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);
}
}
}
}
}