Loading...
Searching...
No Matches
lomirimenumodelstack.cpp
/*
* Copyright 2013 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Nick Dedekind <nick.dedekind@canonical.com>
*/
#include "lomirimenumodelstack.h"
#include <QDebug>
#include <ayatanamenumodel.h>
class LomiriMenuModelEntry : public QObject {
Q_OBJECT
public:
LomiriMenuModelEntry(AyatanaMenuModel* model, AyatanaMenuModel* parentModel, int index)
: m_model(model),
m_parentModel(parentModel),
m_index(index)
{
if (m_parentModel) {
QObject::connect(m_parentModel, &AyatanaMenuModel::rowsInserted, this, &LomiriMenuModelEntry::onRowsInserted);
QObject::connect(m_parentModel, &AyatanaMenuModel::rowsRemoved, this, &LomiriMenuModelEntry::onRowsRemoved);
QObject::connect(m_parentModel, &AyatanaMenuModel::modelReset, this, &LomiriMenuModelEntry::onModelReset);
}
}
AyatanaMenuModel* model() const { return m_model; }
private Q_SLOTS:
void onRowsInserted(const QModelIndex&, int start, int end)
{
int delta = end-start + 1;
if (start <= m_index) {
m_index += delta;
}
}
void onRowsRemoved(const QModelIndex&, int start, int end)
{
int delta = end-start + 1;
if (start <= m_index) {
if (start + delta > m_index) {
// in the range removed
Q_EMIT remove();
disconnect(m_parentModel, 0, this, 0);
} else {
m_index -= delta;
}
}
}
void onModelReset()
{
Q_EMIT remove();
disconnect(m_parentModel, 0, this, 0);
}
Q_SIGNALS:
void remove();
private:
AyatanaMenuModel* m_model;
AyatanaMenuModel* m_parentModel;
int m_index;
};
LomiriMenuModelStack::LomiriMenuModelStack(QObject* parent)
: QObject(parent)
{
}
LomiriMenuModelStack::~LomiriMenuModelStack()
{
qDeleteAll(m_menuModels);
m_menuModels.clear();
}
AyatanaMenuModel* LomiriMenuModelStack::head() const
{
return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : nullptr;
}
void LomiriMenuModelStack::setHead(AyatanaMenuModel* model)
{
if (head() != model) {
qDeleteAll(m_menuModels);
m_menuModels.clear();
push(model, 0);
Q_EMIT headChanged(model);
}
}
AyatanaMenuModel* LomiriMenuModelStack::tail() const
{
return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : nullptr;
}
int LomiriMenuModelStack::count() const
{
return m_menuModels.count();
}
void LomiriMenuModelStack::push(AyatanaMenuModel* model, int index)
{
LomiriMenuModelEntry* entry = new LomiriMenuModelEntry(model, tail(), index);
QObject::connect(entry, &LomiriMenuModelEntry::remove, this, &LomiriMenuModelStack::onRemove);
m_menuModels << entry;
Q_EMIT tailChanged(model);
Q_EMIT countChanged(m_menuModels.count());
}
AyatanaMenuModel* LomiriMenuModelStack::pop()
{
if (m_menuModels.isEmpty()) {
return nullptr;
}
LomiriMenuModelEntry* entry = m_menuModels.takeLast();
AyatanaMenuModel* model = entry->model();
entry->deleteLater();
Q_EMIT tailChanged(tail());
if (m_menuModels.isEmpty()) {
Q_EMIT headChanged(nullptr);
}
Q_EMIT countChanged(m_menuModels.count());
return model;
}
void LomiriMenuModelStack::onRemove()
{
LomiriMenuModelEntry* removed = qobject_cast<LomiriMenuModelEntry*>(sender());
if (!m_menuModels.contains(removed))
return;
for (int i = m_menuModels.count() -1; i >= 0; i--) {
LomiriMenuModelEntry* entry = m_menuModels[i];
pop();
if (entry == removed) {
break;
}
}
}
#include "lomirimenumodelstack.moc"