2
* This file is part of unity-2d
2
* This file is part of unity-qt
4
4
* Copyright 2010 Canonical Ltd.
7
7
* - Aurélien Gâteau <aurelien.gateau@canonical.com>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; version 3.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include <menubarwidget.h>
12
#include "appmenuapplet.h"
27
#include <indicatorentrywidget.h>
28
#include <indicatorsmanager.h>
16
#include "registrar.h"
19
#include <dbusmenuimporter.h>
22
#include <bamf-matcher.h>
23
#include <bamf-window.h>
31
26
#include <QHBoxLayout>
33
static const int MENU_ITEM_PADDING = 6;
35
MenuBarWidget::MenuBarWidget(IndicatorsManager* indicatorsManager, QWidget* parent)
37
, m_indicatorsManager(indicatorsManager)
38
, m_layout(new QHBoxLayout(this))
42
m_layout->setMargin(0);
43
m_layout->setSpacing(0);
44
indicatorsManager->indicators()->on_object_added.connect(
45
sigc::mem_fun(this, &MenuBarWidget::onObjectAdded)
47
indicatorsManager->indicators()->on_object_removed.connect(
48
sigc::mem_fun(this, &MenuBarWidget::onObjectRemoved)
50
indicatorsManager->indicators()->on_entry_activated.connect(
51
sigc::mem_fun(this, &MenuBarWidget::onEntryActivated)
53
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
54
m_layout->addStretch();
57
MenuBarWidget::~MenuBarWidget()
59
// disconnect from the entry signals
60
entry_added.disconnect();
61
entry_removed.disconnect();
62
qDeleteAll(m_widgetList);
65
bool MenuBarWidget::isEmpty() const
70
bool MenuBarWidget::isOpened() const
75
void MenuBarWidget::setOpened(bool opened)
77
if (m_isOpened != opened) {
83
QList<IndicatorEntryWidget*> MenuBarWidget::entries() const
88
void MenuBarWidget::onObjectAdded(const unity::indicator::Indicator::Ptr& indicator)
90
QString name = QString::fromStdString(indicator->name());
91
if (name == "libappmenu.so") {
92
m_indicator = indicator;
93
entry_added = m_indicator->on_entry_added.connect(
94
sigc::mem_fun(this, &MenuBarWidget::onEntryAdded)
96
entry_removed = m_indicator->on_entry_removed.connect(
97
sigc::mem_fun(this, &MenuBarWidget::onEntryRemoved)
102
void MenuBarWidget::onObjectRemoved(const unity::indicator::Indicator::Ptr& indicator)
104
QString name = QString::fromStdString(indicator->name());
105
if (name == "libappmenu.so" && indicator.get()) {
106
entry_added.disconnect();
107
entry_removed.disconnect();
109
Q_FOREACH(const unity::indicator::Entry::Ptr& entry, m_indicator->GetEntries())
111
onEntryRemoved (entry->id());
118
void MenuBarWidget::onEntryAdded(const unity::indicator::Entry::Ptr& entry)
120
IndicatorEntryWidget* widget = new IndicatorEntryWidget(entry);
121
widget->setPadding(MENU_ITEM_PADDING);
122
connect(widget, SIGNAL(isEmptyChanged()), SLOT(updateIsEmpty()));
124
m_widgetList.append(widget);
125
m_indicatorsManager->addIndicatorEntryWidget(widget);
127
// Insert *before* stretch
128
m_layout->insertWidget(m_layout->count() - 1, widget);
131
void MenuBarWidget::onEntryRemoved(const std::string& entry_id)
133
Q_FOREACH(IndicatorEntryWidget* widget, m_widgetList)
135
if (widget->entry()->id() == entry_id) {
136
disconnect(widget, SIGNAL(isEmptyChanged()));
138
m_layout->removeWidget(widget);
139
m_indicatorsManager->removeIndicatorEntryWidget(widget);
140
m_widgetList.removeOne(widget);
148
void MenuBarWidget::updateIsEmpty()
151
Q_FOREACH(IndicatorEntryWidget* widget, m_widgetList) {
152
if (!widget->isEmpty()) {
157
if (m_isEmpty != empty) {
163
void MenuBarWidget::onEntryActivated(const std::string& id)
165
bool isOpened = false;
167
// We only cares about menubar entries
168
Q_FOREACH(IndicatorEntryWidget* widget, m_widgetList) {
169
if (widget->entry()->id() == id) {
29
class MyDBusMenuImporter : public DBusMenuImporter
32
MyDBusMenuImporter(const QString &service, const QString &path, QObject *parent)
33
: DBusMenuImporter(service, path, parent)
38
QString service() const { return m_service; }
39
QString path() const { return m_path; }
46
AppMenuApplet::AppMenuApplet()
52
connect(&BamfMatcher::get_default(), SIGNAL(ActiveWindowChanged(BamfWindow*, BamfWindow*)),
53
SLOT(slotActiveWindowChanged(BamfWindow*, BamfWindow*)));
54
updateActiveWinId(BamfMatcher::get_default().active_window());
57
void AppMenuApplet::setupRegistrar()
59
m_registrar = new Registrar(this);
60
if (!m_registrar->connectToBus()) {
61
UQ_WARNING << "could not connect registrar to DBus";
64
connect(m_registrar, SIGNAL(WindowRegistered(WId, const QString&, const QDBusObjectPath&)),
65
SLOT(slotWindowRegistered(WId, const QString&, const QDBusObjectPath&)));
68
void AppMenuApplet::setupMenuBar()
70
QHBoxLayout* layout = new QHBoxLayout(this);
72
m_menuBar = new QMenuBar;
73
layout->addWidget(m_menuBar);
74
m_menuBar->setNativeMenuBar(false);
75
m_menuBar->addMenu("File");
78
void AppMenuApplet::slotActiveWindowChanged(BamfWindow* /*former*/, BamfWindow* current)
81
updateActiveWinId(current);
85
void AppMenuApplet::slotWindowRegistered(WId wid, const QString& service, const QDBusObjectPath& menuObjectPath)
87
MyDBusMenuImporter* importer = new MyDBusMenuImporter(service, menuObjectPath.path(), this);
88
delete m_importers.take(wid);
89
m_importers.insert(wid, importer);
90
connect(importer, SIGNAL(menuUpdated()), SLOT(slotMenuUpdated()));
91
connect(importer, SIGNAL(actionActivationRequested(QAction*)), SLOT(slotActionActivationRequested(QAction*)));
92
QMetaObject::invokeMethod(importer, "updateMenu", Qt::QueuedConnection);
95
void AppMenuApplet::slotMenuUpdated()
97
DBusMenuImporter* importer = static_cast<DBusMenuImporter*>(sender());
99
if (m_importers.value(m_activeWinId) == importer) {
104
void AppMenuApplet::slotActionActivationRequested(QAction* action)
106
DBusMenuImporter* importer = static_cast<DBusMenuImporter*>(sender());
108
if (m_importers.value(m_activeWinId) == importer) {
109
m_menuBar->setActiveAction(action);
113
QMenu* AppMenuApplet::menuForWinId(WId wid) const
115
MyDBusMenuImporter* importer = m_importers.value(wid);
116
return importer ? importer->menu() : 0;
119
void AppMenuApplet::updateActiveWinId(BamfWindow* bamfWindow)
121
WId id = bamfWindow ? bamfWindow->xid() : 0;
122
if (id == m_activeWinId) {
125
if (id == window()->winId()) {
126
// Do not update id if the active window is the one hosting this applet
133
void AppMenuApplet::updateMenuBar()
135
WId winId = m_activeWinId;
136
QMenu* menu = menuForWinId(winId);
140
// We have an active window
141
// FIXME: transient check
143
WId mainWinId = KWindowSystem::transientFor(winId);
145
// We have a parent window, use a disabled version of its
146
// menubar if it has one.
147
QMenu* mainMenu = menuForWinId(mainWinId);
149
mMenuCloner->setOriginalMenu(mainMenu);
150
menu = mMenuCloner->clonedMenu();
153
// FIXME: WindowMenuManager
156
// No suitable menubar but we have a window, use the
157
// generic window menu
158
mWindowMenuManager->setWinId(winId);
178
#include "menubarwidget.moc"
163
// No active window, show a desktop menubar
173
void AppMenuApplet::fillMenuBar(QMenu* menu)
180
Q_FOREACH(QAction* action, menu->actions()) {
181
if (action->isSeparator()) {
184
m_menuBar->addAction(action);
188
#include "appmenuapplet.moc"