/* * Copyright 2014 Javier S. Pedro * * This file is part of TopMenu. * * TopMenu 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, either version 3 of the License, or * (at your option) any later version. * * TopMenu 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 TopMenu. If not, see . */ #include #include #include #include #include "appmenu.h" AppMenu::AppMenu(QObject *parent) : MenuProxy(parent), m_menu(0) { } AppMenu::~AppMenu() { if (m_menu) { gtk_widget_destroy(GTK_WIDGET(m_menu)); g_object_unref(m_menu); } } GtkMenu * AppMenu::getGtkMenu() { if (!m_menu) { m_menu = GTK_MENU(gtk_menu_new()); g_object_ref_sink(m_menu); setTargetMenu(GTK_MENU_SHELL(m_menu)); addDefaultItems(); } return m_menu; } GtkMenuItem * AppMenu::addAction(QAction* action) { QAction::MenuRole role = detectRole(action); if (role == QAction::NoRole) return 0; // Item should not appear in appmenu // If we just inserted a custom quit item, remove the default one. if (role == QAction::QuitRole) { removeAction(m_def_quit); } uint order = orderForRole(role); QMap::iterator it = m_actions.insert(order, action); // Get the previous element QAction *before = 0; if (it != m_actions.begin()) { --it; before = it.value(); } return MenuProxy::addAction(action, before, 0); } GtkMenuItem * AppMenu::addAction(QAction* action, QAction* before, QMenu* parent) { if (parent) { return MenuProxy::addAction(action, before, parent); } else { // Never add an action to the root menu here. return 0; } } void AppMenu::removeAction(QAction *action) { if (getItemForAction(action)) { MenuProxy::removeAction(action); m_actions.remove(orderForRole(action->menuRole()), action); } } void AppMenu::updateAction(QAction *action) { GtkMenuItem *item = getItemForAction(action); if (item) { MenuProxy::updateAction(action); } else { QAction::MenuRole role = detectRole(action); if (role != QAction::NoRole) { // The item now has a role! addAction(action); } } } void AppMenu::addDefaultItems() { QAction *separator = new QAction(this); separator->setSeparator(true); m_actions.insert(15, separator); MenuProxy::addAction(separator, 0, 0); m_def_quit = new QAction(QIcon::fromTheme("application-exit"), QMenuBar::tr("Quit"), this); m_actions.insert(11, m_def_quit); MenuProxy::addAction(m_def_quit, 0, 0); connect(m_def_quit, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit())); } uint AppMenu::orderForRole(QAction::MenuRole role) { switch (role) { case QAction::AboutRole: return 50; case QAction::AboutQtRole: return 40; case QAction::PreferencesRole: return 30; case QAction::ApplicationSpecificRole: return 20; case QAction::QuitRole: return 10; default: return 0; } } QAction::MenuRole AppMenu::detectRole(QAction *action) { QAction::MenuRole role = action->menuRole(); if (action->isSeparator()) return QAction::NoRole; if (role == QAction::TextHeuristicRole) { QString t = action->text().toLower().remove('&'); QString aboutString = QMenuBar::tr("About").toLower(); if (t.startsWith(aboutString) || t.endsWith(aboutString)) { if (t.indexOf(QRegExp(QString::fromLatin1("qt$"), Qt::CaseInsensitive)) == -1) { return QAction::AboutRole; } else { return QAction::AboutQtRole; } } else if (t.startsWith(QMenuBar::tr("Config").toLower()) || t.startsWith(QMenuBar::tr("Preference").toLower()) || t.startsWith(QMenuBar::tr("Options").toLower()) || t.startsWith(QMenuBar::tr("Setting").toLower()) || t.startsWith(QMenuBar::tr("Setup").toLower())) { return QAction::PreferencesRole; } else if (t.startsWith(QMenuBar::tr("Quit").toLower()) || t.startsWith(QMenuBar::tr("Exit").toLower())) { return QAction::QuitRole; } return QAction::NoRole; } else { return role; } }