#include #include #include #include #include #include #include #include #include "topmenumenubarimpl.h" #include "appmenu.h" #include "qtkeysyms.h" bool TopMenuMenuBarImpl::staticInitialized = false; TopMenuMonitor * TopMenuMenuBarImpl::menuMonitor; static inline QShortcut * get_shortcut_for_action(QAction *action) { QVariant v = action->property("topmenu-shortcut"); if (v.isValid()) { return static_cast(v.value()); } return 0; } static inline void set_shortcut_for_action(QAction *action, QShortcut *shortcut) { if (shortcut) { action->setProperty("topmenu-shortcut", QVariant::fromValue(shortcut)); } else { action->setProperty("topmenu-shortcut", QVariant()); } } static inline QAction * get_action_for_shortcut(QShortcut *shortcut) { QVariant v = shortcut->property("topmenu-action"); if (v.isValid()) { return static_cast(v.value()); } return 0; } static inline void set_action_for_shortcut(QShortcut *shortcut, QAction *action) { if (shortcut) { shortcut->setProperty("topmenu-action", QVariant::fromValue(action)); } else { shortcut->setProperty("topmenu-action", QVariant()); } } TopMenuMenuBarImpl::TopMenuMenuBarImpl(QObject *parent) : MenuProxy(parent), m_window(0), m_menubar(0), m_appmenu(0), m_disable(false), m_visible(true) { // A new instance of this class will be created for each window. if (!staticInitialized) { XErrorHandler qt_x_errhandler = XSetErrorHandler(0); gtk_init(NULL, NULL); XSetErrorHandler(qt_x_errhandler); menuMonitor = topmenu_monitor_get_instance(); // TODO g_signal_connect() staticInitialized = true; } } TopMenuMenuBarImpl::~TopMenuMenuBarImpl() { if (m_menubar) { g_object_unref(m_menubar); m_menubar = 0; } } void TopMenuMenuBarImpl::init(QMenuBar *menuBar) { Q_ASSERT(menuBar); Q_ASSERT(!m_menubar); m_menubar = topmenu_app_menu_bar_new(); g_object_ref_sink(m_menubar); m_appmenu = new AppMenu(this); topmenu_app_menu_bar_set_app_menu(m_menubar, GTK_WIDGET(m_appmenu->getGtkMenu())); gtk_widget_show(GTK_WIDGET(m_menubar)); setTargetMenu(GTK_MENU_SHELL(m_menubar)); } void TopMenuMenuBarImpl::setVisible(bool visible) { m_visible = visible; } void TopMenuMenuBarImpl::actionEvent(QActionEvent *e) { switch (e->type()) { case QEvent::ActionAdded: addAction(e->action(), e->before(), 0); break; case QEvent::ActionRemoved: removeAction(e->action()); break; case QEvent::ActionChanged: updateAction(e->action()); break; default: break; } } void TopMenuMenuBarImpl::handleReparent(QWidget *oldParent, QWidget *newParent, QWidget *oldWindow, QWidget *newWindow) { Q_UNUSED(oldParent); Q_UNUSED(newParent); if (oldWindow) { GdkWindow *old_window = gdk_window_foreign_new(oldWindow->winId()); topmenu_client_disconnect_window(old_window); Q_FOREACH(QAction *action, m_rootitems) { QShortcut *shortcut = get_shortcut_for_action(action); if (shortcut) { set_shortcut_for_action(action, 0); delete shortcut; } } } if (newWindow) { Q_ASSERT(m_menubar); GdkWindow *new_window = gdk_window_foreign_new(newWindow->winId()); topmenu_client_connect_window_widget(new_window, GTK_WIDGET(m_menubar)); Q_FOREACH(QAction *action, m_rootitems) { createMnemonicShortcut(action, newWindow); } } m_window = newWindow; } bool TopMenuMenuBarImpl::allowCornerWidgets() const { return !isNativeMenuBar(); } void TopMenuMenuBarImpl::popupAction(QAction *act) { qDebug() << "TODO Popup action: " << act->text(); } void TopMenuMenuBarImpl::setNativeMenuBar(bool value) { m_disable = !value; } bool TopMenuMenuBarImpl::isNativeMenuBar() const { if (m_disable || QCoreApplication::instance()->testAttribute(Qt::AA_DontUseNativeMenuBar)) return false; return menuMonitor->available; } bool TopMenuMenuBarImpl::shortcutsHandledByNativeMenuBar() const { return false; } bool TopMenuMenuBarImpl::menuBarEventFilter(QObject *src, QEvent *event) { Q_UNUSED(src); Q_UNUSED(event); return false; } GtkMenuItem * TopMenuMenuBarImpl::addAction(QAction* action, QAction* before, QMenu* parent) { if (!parent) { m_rootitems.append(action); if (m_window) { createMnemonicShortcut(action, m_window); } } if (m_appmenu) { m_appmenu->addAction(action); } return MenuProxy::addAction(action, before, parent); } void TopMenuMenuBarImpl::removeAction(QAction *action) { m_rootitems.removeAll(action); QShortcut *shortcut = get_shortcut_for_action(action); if (shortcut) { set_shortcut_for_action(action, 0); delete shortcut; } if (m_appmenu) { m_appmenu->removeAction(action); } MenuProxy::removeAction(action); } void TopMenuMenuBarImpl::updateAction(QAction *action) { if (!action->isSeparator() && m_rootitems.contains(action) && m_window) { QShortcut *shortcut = get_shortcut_for_action(action); if (shortcut) { shortcut->setKey(QKeySequence::mnemonic(action->text())); } else { shortcut = createMnemonicShortcut(action, m_window); } shortcut->setEnabled(action->isEnabled()); } if (m_appmenu) { m_appmenu->updateAction(action); } MenuProxy::updateAction(action); } QShortcut * TopMenuMenuBarImpl::createMnemonicShortcut(QAction *action, QWidget *parent) { QShortcut *shortcut = new QShortcut(parent); set_shortcut_for_action(action, shortcut); set_action_for_shortcut(shortcut, action); shortcut->setKey(QKeySequence::mnemonic(action->text())); connect(shortcut, SIGNAL(activated()), this, SLOT(handleShortcutActivated())); return shortcut; } void TopMenuMenuBarImpl::handleShortcutActivated() { QShortcut *shortcut = static_cast(sender()); QAction *action = get_action_for_shortcut(shortcut); GtkMenuItem *item = getItemForAction(action); gtk_widget_mnemonic_activate(GTK_WIDGET(item), FALSE); }