mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-26 11:52:54 +00:00
398 lines
11 KiB
C++
398 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2007, 2008, 2009, 2010 Ivan Cukic <ivan.cukic(at)kde.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser/Library General Public License version 2,
|
|
* or (at your option) any later version, as published by the Free
|
|
* Software Foundation
|
|
*
|
|
* 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 Lesser/Library General Public License for more details
|
|
*
|
|
* You should have received a copy of the GNU Lesser/Library 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 "MergedActionListModel.h"
|
|
|
|
namespace Lancelot {
|
|
|
|
class MergedActionListModel::Private {
|
|
public:
|
|
void toChildCoordinates(int index, int & model, int & modelIndex) const;
|
|
void fromChildCoordinates(int & index, int model, int modelIndex) const;
|
|
|
|
QList < ActionListModel * > models;
|
|
QList < QPair < QString, QIcon > > modelsMetadata;
|
|
|
|
bool hideEmptyModels : 1;
|
|
bool showModelTitles : 1;
|
|
};
|
|
|
|
MergedActionListModel::MergedActionListModel()
|
|
: d(new Private)
|
|
{
|
|
d->hideEmptyModels = true;
|
|
d->showModelTitles = true;
|
|
}
|
|
|
|
MergedActionListModel::~MergedActionListModel()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
void MergedActionListModel::modelUpdated()
|
|
{
|
|
emit updated();
|
|
}
|
|
|
|
void MergedActionListModel::modelItemInserted(int modelIndex)
|
|
{
|
|
if (!sender()) return;
|
|
|
|
ActionListModel * m = (ActionListModel *)sender();
|
|
int model = d->models.indexOf(m);
|
|
if (model == -1) return;
|
|
|
|
int index;
|
|
d->fromChildCoordinates(index, model, modelIndex);
|
|
|
|
if (d->hideEmptyModels && m->size() == 1) {
|
|
modelUpdated();
|
|
} else {
|
|
emit itemInserted(index);
|
|
}
|
|
}
|
|
|
|
void MergedActionListModel::modelItemDeleted(int modelIndex)
|
|
{
|
|
if (!sender()) return;
|
|
|
|
ActionListModel * m = (ActionListModel *)sender();
|
|
int model = d->models.indexOf(m);
|
|
if (model == -1) return;
|
|
|
|
int index;
|
|
d->fromChildCoordinates(index, model, modelIndex);
|
|
|
|
if (d->hideEmptyModels && m->size() == 0) {
|
|
modelUpdated();
|
|
} else {
|
|
emit itemDeleted(index);
|
|
}
|
|
}
|
|
|
|
void MergedActionListModel::modelItemAltered(int modelIndex)
|
|
{
|
|
if (!sender()) return;
|
|
|
|
int model = d->models.indexOf((ActionListModel *)sender());
|
|
if (model == -1) return;
|
|
|
|
int index;
|
|
d->fromChildCoordinates(index, model, modelIndex);
|
|
emit itemAltered(index);
|
|
}
|
|
|
|
QString MergedActionListModel::description(int index) const
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1 || modelIndex == -1) return "";
|
|
return d->models.at(model)->description(modelIndex);
|
|
|
|
}
|
|
|
|
QIcon MergedActionListModel::icon(int index) const
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return QIcon();
|
|
if (modelIndex == -1) return d->modelsMetadata.at(model).second;
|
|
return d->models.at(model)->icon(modelIndex);
|
|
}
|
|
|
|
QMimeData * MergedActionListModel::mimeData(int index) const
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return NULL;
|
|
if (modelIndex == -1) return modelMimeData(model);
|
|
return d->models.at(model)->mimeData(modelIndex);
|
|
}
|
|
|
|
void MergedActionListModel::dataDragFinished(int index, Qt::DropAction action)
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
d->showModelTitles = true;
|
|
|
|
if (model == -1) return;
|
|
if (modelIndex == -1) return modelDataDropped(model, action);
|
|
return d->models.at(model)->dataDragFinished(modelIndex, action);
|
|
}
|
|
|
|
void MergedActionListModel::modelDataDropped(int index, Qt::DropAction action)
|
|
{
|
|
Q_UNUSED(index);
|
|
Q_UNUSED(action);
|
|
}
|
|
|
|
void MergedActionListModel::setDropActions(int index, Qt::DropActions & actions, Qt::DropAction & defaultAction)
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return;
|
|
if (modelIndex == -1) return setModelDropActions(model, actions, defaultAction);
|
|
return d->models.at(model)->setDropActions(modelIndex, actions, defaultAction);
|
|
}
|
|
|
|
void MergedActionListModel::setModelDropActions(int index,
|
|
Qt::DropActions & actions, Qt::DropAction & defaultAction)
|
|
{
|
|
Q_UNUSED(index);
|
|
actions = Qt::IgnoreAction;
|
|
defaultAction = Qt::IgnoreAction;
|
|
}
|
|
|
|
QMimeData * MergedActionListModel::modelMimeData(int index) const
|
|
{
|
|
Q_UNUSED(index);
|
|
return NULL;
|
|
}
|
|
|
|
bool MergedActionListModel::dataDropAvailable(int where, const QMimeData * mimeData)
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(where, model, modelIndex);
|
|
|
|
if (model == -1) return false;
|
|
if (modelIndex == -1) return false;
|
|
return d->models.at(model)->dataDropAvailable(modelIndex, mimeData);
|
|
}
|
|
|
|
void MergedActionListModel::dataDropped(int where, const QMimeData * mimeData)
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(where, model, modelIndex);
|
|
|
|
if (model == -1) return;
|
|
if (modelIndex == -1) return;
|
|
return d->models.at(model)->dataDropped(modelIndex, mimeData);
|
|
}
|
|
|
|
bool MergedActionListModel::hasModelContextActions(int index) const
|
|
{
|
|
Q_UNUSED(index);
|
|
return false;
|
|
}
|
|
|
|
void MergedActionListModel::setModelContextActions(int index, Lancelot::PopupMenu * menu)
|
|
{
|
|
Q_UNUSED(index);
|
|
Q_UNUSED(menu);
|
|
// do nothing
|
|
}
|
|
|
|
void MergedActionListModel::modelContextActivate(int index, QAction * context)
|
|
{
|
|
Q_UNUSED(index);
|
|
Q_UNUSED(context);
|
|
// do nothing
|
|
}
|
|
|
|
bool MergedActionListModel::isCategory(int index) const
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return false;
|
|
if (model != -1 && modelIndex == -1) return true;
|
|
return d->models.at(model)->isCategory(modelIndex);
|
|
}
|
|
|
|
void MergedActionListModel::activate(int index)
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1 || modelIndex == -1) return;
|
|
|
|
d->models.at(model)->activated(modelIndex);
|
|
}
|
|
|
|
QString MergedActionListModel::title(int index) const
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return "Error";
|
|
if (modelIndex == -1) return d->modelsMetadata.at(model).first;
|
|
return d->models.at(model)->title(modelIndex);
|
|
}
|
|
|
|
bool MergedActionListModel::hasContextActions(int index) const
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return false;
|
|
if (modelIndex == -1) return hasModelContextActions(model);
|
|
return d->models.at(model)->hasContextActions(modelIndex);
|
|
}
|
|
|
|
void MergedActionListModel::setContextActions(int index, Lancelot::PopupMenu * menu)
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return;
|
|
if (modelIndex == -1) return setModelContextActions(model, menu);
|
|
d->models.at(model)->setContextActions(modelIndex, menu);
|
|
}
|
|
|
|
void MergedActionListModel::contextActivate(int index, QAction * context)
|
|
{
|
|
int model, modelIndex;
|
|
d->toChildCoordinates(index, model, modelIndex);
|
|
|
|
if (model == -1) return;
|
|
if (modelIndex == -1) return modelContextActivate(model, context);
|
|
d->models.at(model)->contextActivate(modelIndex, context);
|
|
}
|
|
|
|
#define TITLE_OFFSET (showModelTitles ? 1 : 0)
|
|
|
|
void MergedActionListModel::Private::toChildCoordinates(int index, int & model, int & modelIndex) const
|
|
{
|
|
model = 0; modelIndex = 0;
|
|
foreach (ActionListModel * m, models) {
|
|
if (!hideEmptyModels || m->size() != 0) {
|
|
if (index < m->size() + TITLE_OFFSET) {
|
|
modelIndex = index - TITLE_OFFSET;
|
|
return;
|
|
} else {
|
|
index -= m->size() + TITLE_OFFSET;
|
|
++model;
|
|
}
|
|
} else {
|
|
++model;
|
|
}
|
|
}
|
|
model = -1;
|
|
modelIndex = -1;
|
|
}
|
|
|
|
void MergedActionListModel::Private::fromChildCoordinates(int & index, int model, int modelIndex) const
|
|
{
|
|
index = -1;
|
|
if (model >= models.size()) return;
|
|
if (modelIndex >= models.at(model)->size()) return;
|
|
|
|
index = 0;
|
|
foreach (ActionListModel * m, models) {
|
|
if (!hideEmptyModels || m->size() != 0) {
|
|
if (model > 0) {
|
|
index += m->size() + 1;//TITLE_OFFSET;
|
|
} else {
|
|
index += modelIndex + 1;//TITLE_OFFSET;
|
|
return;
|
|
}
|
|
}
|
|
--model;
|
|
}
|
|
index = -1;
|
|
}
|
|
|
|
#undef TITLE_OFFSET
|
|
|
|
void MergedActionListModel::addModel(ActionListModel * model)
|
|
{
|
|
addModel(model->selfIcon(), model->selfTitle(), model);
|
|
}
|
|
|
|
void MergedActionListModel::addModel(QIcon icon, const QString & title, ActionListModel * model)
|
|
{
|
|
if (!model) return;
|
|
d->models.append(model);
|
|
d->modelsMetadata.append(QPair< QString, QIcon >(title, icon));
|
|
|
|
connect(model, SIGNAL(updated()), this, SLOT(modelUpdated()));
|
|
connect(model, SIGNAL(itemInserted(int)), this, SLOT(modelItemInserted(int)));
|
|
connect(model, SIGNAL(itemDeleted(int)), this, SLOT(modelItemDeleted(int)));
|
|
connect(model, SIGNAL(itemAltered(int)), this, SLOT(modelItemAltered(int)));
|
|
|
|
if (d->hideEmptyModels && model->size() == 0) return; // We will not show empty models
|
|
|
|
emit updated();
|
|
}
|
|
|
|
ActionListModel * MergedActionListModel::modelAt(int index)
|
|
{
|
|
return d->models.at(index);
|
|
}
|
|
|
|
void MergedActionListModel::removeModel(int index)
|
|
{
|
|
if (index < 0 || index >= d->models.size()) {
|
|
return;
|
|
}
|
|
|
|
ActionListModel * model = d->models.takeAt(index);
|
|
d->modelsMetadata.removeAt(index);
|
|
model->disconnect(this);
|
|
emit updated();
|
|
}
|
|
|
|
int MergedActionListModel::modelCount() const
|
|
{
|
|
return d->models.size();
|
|
}
|
|
|
|
|
|
int MergedActionListModel::size() const
|
|
{
|
|
int result = 0;
|
|
foreach (ActionListModel * model, d->models) {
|
|
if (d->hideEmptyModels && model->size() == 0) continue; // We will not show empty models
|
|
result += model->size() + (d->showModelTitles ? 1 : 0);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool MergedActionListModel::hideEmptyModels() const
|
|
{
|
|
return d->hideEmptyModels;
|
|
}
|
|
|
|
void MergedActionListModel::setHideEmptyModels(bool hide)
|
|
{
|
|
if (d->hideEmptyModels == hide) return;
|
|
d->hideEmptyModels = hide;
|
|
emit updated();
|
|
}
|
|
|
|
bool MergedActionListModel::showModelTitles() const
|
|
{
|
|
return d->showModelTitles;
|
|
}
|
|
|
|
void MergedActionListModel::setShowModelTitles(bool show)
|
|
{
|
|
if (d->showModelTitles == show) return;
|
|
d->showModelTitles = show;
|
|
emit updated();
|
|
}
|
|
|
|
} // namespace Lancelot
|
|
|
|
#include "MergedActionListModel.moc"
|
|
|