/* * Copyright 2013-2016 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 . * * Authors: * Nick Dedekind */ #include "modelactionrootstate.h" #include "indicators.h" #include #include #include extern "C" { #include #include } ModelActionRootState::ModelActionRootState(QObject *parent) : RootStateObject(parent), m_menu(nullptr) , m_reentryGuard(false) { } ModelActionRootState::~ModelActionRootState() { } UnityMenuModel* ModelActionRootState::menu() const { return m_menu; } void ModelActionRootState::setMenu(UnityMenuModel* menu) { if (m_menu != menu) { bool wasValid = valid(); if (m_menu) { m_menu->disconnect(this); } m_menu = menu; if (m_menu) { connect(m_menu, &UnityMenuModel::rowsInserted, this, &ModelActionRootState::onModelRowsAdded); connect(m_menu, &UnityMenuModel::rowsRemoved, this, &ModelActionRootState::onModelRowsRemoved); connect(m_menu, &UnityMenuModel::dataChanged, this, &ModelActionRootState::onModelDataChanged); connect(m_menu, &UnityMenuModel::destroyed, this, &ModelActionRootState::reset); } updateActionState(); updateOtherActions(); Q_EMIT menuChanged(); if (wasValid != valid()) Q_EMIT validChanged(); } } QString ModelActionRootState::secondaryAction() const { return m_secondaryAction; } QString ModelActionRootState::scrollAction() const { return m_scrollAction; } QString ModelActionRootState::submenuAction() const { return m_submenuAction; } bool ModelActionRootState::valid() const { return !currentState().empty(); } void ModelActionRootState::onModelRowsAdded(const QModelIndex& parent, int start, int end) { Q_UNUSED(parent); if (start == 0 && end >= 0) { updateActionState(); updateOtherActions(); } } void ModelActionRootState::onModelRowsRemoved(const QModelIndex& parent, int start, int end) { Q_UNUSED(parent); if (start == 0 && end >= 0) { updateActionState(); updateOtherActions(); } } void ModelActionRootState::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles) { Q_UNUSED(roles); if (!topLeft.isValid() || !bottomRight.isValid()) { return; } if (topLeft.row() <= 0 && bottomRight.row() >= 0) { updateActionState(); updateOtherActions(); } } void ModelActionRootState::reset() { m_menu = nullptr; Q_EMIT menuChanged(); setCurrentState(QVariantMap()); updateOtherActions(); } void ModelActionRootState::updateActionState() { if (m_reentryGuard) return; m_reentryGuard = true; if (m_menu && m_menu->rowCount() > 0) { ActionStateParser* oldParser = m_menu->actionStateParser(); m_menu->setActionStateParser(&m_parser); QVariantMap state = m_menu->get(0, "actionState").toMap(); m_menu->setActionStateParser(oldParser); setCurrentState(state); } else if (!m_menu) { setCurrentState(QVariantMap()); } // else if m_menu->rowCount() == 0, let's leave existing cache in place // until the new menu comes in, to avoid flashing the UI empty for a moment m_reentryGuard = false; } void ModelActionRootState::updateOtherActions() { if (m_reentryGuard) return; m_reentryGuard = true; if (m_menu && m_menu->rowCount() > 0) { QVariantMap map; map[QStringLiteral("submenu-action")] = QStringLiteral("string"); map[QStringLiteral("x-canonical-scroll-action")] = QStringLiteral("string"); map[QStringLiteral("x-canonical-secondary-action")] = QStringLiteral("string"); m_menu->loadExtendedAttributes(0, map); QVariantMap extMap = m_menu->get(0, "ext").toMap(); QString secondaryAction = extMap.value(QStringLiteral("xCanonicalSecondaryAction")).toString(); if (m_secondaryAction != secondaryAction) { m_secondaryAction = secondaryAction; Q_EMIT secondaryActionChanged(); } QString scrollAction = extMap.value(QStringLiteral("xCanonicalScrollAction")).toString(); if (m_scrollAction != scrollAction) { m_scrollAction = scrollAction; Q_EMIT scrollActionChanged(); } QString submenuAction = extMap.value(QStringLiteral("submenuAction")).toString(); if (m_submenuAction != submenuAction) { m_submenuAction = submenuAction; Q_EMIT submenuActionChanged(); } } else { if (!m_secondaryAction.isEmpty()) { m_secondaryAction.clear(); Q_EMIT secondaryActionChanged(); } if (!m_scrollAction.isEmpty()) { m_scrollAction.clear(); Q_EMIT scrollActionChanged(); } if (!m_submenuAction.isEmpty()) { m_submenuAction.clear(); Q_EMIT submenuActionChanged(); } } m_reentryGuard = false; }