--override default contextmenu behavior
--clean up old code
pull/1/head
Michail Vourlakos 8 years ago
parent 9259ee3bc3
commit 83e0a7564a

@ -1,3 +1,4 @@
find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Quick Qml)
find_package(KF5I18n NO_MODULE)
include(KDEInstallDirs)

@ -29,17 +29,23 @@
#include <QQmlEngine>
#include <QQmlProperty>
#include <QQuickItem>
#include <QMenu>
#include <QMetaEnum>
#include <Plasma/Containment>
#include <Plasma/ContainmentActions>
#include <KActionCollection>
#include <KAuthorized>
#include <KLocalizedContext>
#include <KLocalizedString>
#include <Plasma/Containment>
#include <Plasma/ContainmentActions>
#include <PlasmaQuick/AppletQuickItem>
namespace Latte {
DockView::DockView(Plasma::Corona *corona, QScreen *targetScreen)
: PlasmaQuick::ContainmentView(corona)
: PlasmaQuick::ContainmentView(corona),
m_contextMenu(0)
{
setVisible(false);
setTitle(corona->kPackage().metadata().name());
@ -75,8 +81,8 @@ DockView::DockView(Plasma::Corona *corona, QScreen *targetScreen)
QAction *lockWidgetsAction = containment()->actions()->action("lock widgets");
containment()->actions()->removeAction(lockWidgetsAction);
//QAction *addWidgetsAction = containment()->actions()->action("add widgets");
//containment()->actions()->removeAction(addWidgetsAction);
QAction *addWidgetsAction = containment()->actions()->action("add widgets");
containment()->actions()->removeAction(addWidgetsAction);
}, Qt::DirectConnection);
}
@ -503,39 +509,6 @@ bool DockView::event(QEvent *e)
return ContainmentView::event(e);
}
/*void DockView::showEvent(QShowEvent *ev)
{
KWindowSystem::setType(winId(), NET::Dock);
KWindowSystem::setOnAllDesktops(winId(), true);
//QQuickWindow::showEvent(ev);
ContainmentView::showEvent(ev);
}*/
bool DockView::containmentContainsPosition(const QPointF &point) const
{
QQuickItem *containmentItem = containment()->property("_plasma_graphicObject").value<QQuickItem *>();
if (!containmentItem) {
return false;
}
return QRectF(containmentItem->mapToScene(QPoint(0, 0)), QSizeF(containmentItem->width(), containmentItem->height())).contains(point);
}
QPointF DockView::positionAdjustedForContainment(const QPointF &point) const
{
QQuickItem *containmentItem = containment()->property("_plasma_graphicObject").value<QQuickItem *>();
if (!containmentItem) {
return point;
}
QRectF containmentRect(containmentItem->mapToScene(QPoint(0, 0)), QSizeF(containmentItem->width(), containmentItem->height()));
return QPointF(qBound(containmentRect.left() + 2, point.x(), containmentRect.right() - 2),
qBound(containmentRect.top() + 2, point.y(), containmentRect.bottom() - 2));
}
QList<int> DockView::freeEdges() const
{
QList<Plasma::Types::Location> edges = corona()->freeEdges(containment()->screen());
@ -620,7 +593,325 @@ QVariantList DockView::containmentActions()
return actions;
}
//!END SLOTS
//!BEGIN overriding context menus behavior
void DockView::addAppletItem(QObject *item)
{
PlasmaQuick::AppletQuickItem *dynItem = qobject_cast<PlasmaQuick::AppletQuickItem *>(item);
if (!dynItem || m_appletItems.contains(dynItem)) {
return;
}
m_appletItems.append(dynItem);
}
void DockView::removeAppletItem(QObject *item)
{
PlasmaQuick::AppletQuickItem *dynItem = qobject_cast<PlasmaQuick::AppletQuickItem *>(item);
if (!dynItem) {
return;
}
m_appletItems.removeAll(dynItem);
}
void DockView::menuAboutToHide()
{
m_contextMenu = 0;
m_visibility->setBlockHiding(false);
}
void DockView::mouseReleaseEvent(QMouseEvent *event)
{
if (!event || !containment()) {
return;
}
PlasmaQuick::ContainmentView::mouseReleaseEvent(event);
event->setAccepted(containment()->containmentActions().contains(Plasma::ContainmentActions::eventToString(event)));
}
void DockView::mousePressEvent(QMouseEvent *event)
{
if (!event || !containment()) {
return;
}
// PlasmaQuick::ContainmentView::mousePressEvent(event);
//even if the menu is executed synchronously, other events may be processed
//by the qml incubator when plasma is loading, so we need to guard there
if (m_contextMenu) {
m_contextMenu->close();
PlasmaQuick::ContainmentView::mousePressEvent(event);
return;
}
//qDebug() << "1...";
const QString trigger = Plasma::ContainmentActions::eventToString(event);
if (trigger == "RightButton;NoModifier") {
Plasma::ContainmentActions *plugin = containment()->containmentActions().value(trigger);
if (!plugin || plugin->contextualActions().isEmpty()) {
event->setAccepted(false);
return;
}
//qDebug() << "2...";
//the plugin can be a single action or a context menu
//Don't have an action list? execute as single action
//and set the event position as action data
/*if (plugin->contextualActions().length() == 1) {
QAction *action = plugin->contextualActions().at(0);
action->setData(event->pos());
action->trigger();
event->accept();
return;
}*/
//qDebug() << "3...";
//FIXME: very inefficient appletAt() implementation
Plasma::Applet *applet = 0;
foreach (PlasmaQuick::AppletQuickItem *ai, m_appletItems) {
if (ai && ai->isVisible() && ai->contains(ai->mapFromItem(contentItem(), event->pos()))) {
applet = ai->applet();
break;
} else {
ai = 0;
}
}
if (applet) {
KPluginMetaData meta = applet->pluginMetaData();
if ((meta.pluginId() != "org.kde.plasma.systemtray") &&
(meta.pluginId() != "org.kde.latte.plasmoid")) {
//qDebug() << "4...";
QMenu *desktopMenu = new QMenu;
desktopMenu->setAttribute(Qt::WA_DeleteOnClose);
m_contextMenu = desktopMenu;
if (this->mouseGrabberItem()) {
//workaround, this fixes for me most of the right click menu behavior
if (applet) {
KPluginMetaData meta = applet->pluginMetaData();
//gives the systemtray direct right click behavior for its applets
if (meta.pluginId() != "org.kde.plasma.systemtray") {
this->mouseGrabberItem()->ungrabMouse();
}
}
return;
}
//qDebug() << "5...";
if (applet) {
emit applet->contextualActionsAboutToShow();
addAppletActions(desktopMenu, applet, event);
} else {
emit containment()->contextualActionsAboutToShow();
addContainmentActions(desktopMenu, event);
}
//qDebug() << "6...";
//this is a workaround where Qt now creates the menu widget
//in .exec before oxygen can polish it and set the following attribute
desktopMenu->setAttribute(Qt::WA_TranslucentBackground);
//end workaround
QPoint pos = event->globalPos();
if (applet) {
desktopMenu->adjustSize();
if (screen()) {
const QRect scr = screen()->geometry();
int smallStep = 3;
int x = event->globalPos().x() + smallStep;
int y = event->globalPos().y() + smallStep;
//qDebug()<<x << " - "<<y;
if (event->globalPos().x() > scr.center().x()) {
x = event->globalPos().x() - desktopMenu->width() - smallStep;
}
if (event->globalPos().y() > scr.center().y()) {
y = event->globalPos().y() - desktopMenu->height() - smallStep;
}
pos = QPoint(x, y);
}
}
//qDebug() << "7...";
if (desktopMenu->isEmpty()) {
delete desktopMenu;
event->accept();
return;
}
connect(desktopMenu, SIGNAL(aboutToHide()), this, SLOT(menuAboutToHide()));
m_visibility->setBlockHiding(true);
desktopMenu->popup(pos);
event->setAccepted(true);
return;
}
}
}
PlasmaQuick::ContainmentView::mousePressEvent(event);
}
void DockView::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event)
{
if (!containment()) {
return;
}
foreach (QAction *action, applet->contextualActions()) {
if (action) {
desktopMenu->addAction(action);
}
}
if (!applet->failedToLaunch()) {
QAction *runAssociatedApplication = applet->actions()->action(QStringLiteral("run associated application"));
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
desktopMenu->addAction(runAssociatedApplication);
}
QAction *configureApplet = applet->actions()->action(QStringLiteral("configure"));
if (configureApplet && configureApplet->isEnabled()) {
desktopMenu->addAction(configureApplet);
}
QAction *appletAlternatives = applet->actions()->action(QStringLiteral("alternatives"));
if (appletAlternatives && appletAlternatives->isEnabled()) {
desktopMenu->addAction(appletAlternatives);
}
}
QMenu *containmentMenu = new QMenu(i18nc("%1 is the name of the containment", "%1 Options", containment()->title()), desktopMenu);
addContainmentActions(containmentMenu, event);
if (!containmentMenu->isEmpty()) {
int enabled = 0;
//count number of real actions
QListIterator<QAction *> actionsIt(containmentMenu->actions());
while (enabled < 3 && actionsIt.hasNext()) {
QAction *action = actionsIt.next();
if (action->isVisible() && !action->isSeparator()) {
++enabled;
}
}
if (enabled) {
//if there is only one, don't create a submenu
if (enabled < 2) {
foreach (QAction *action, containmentMenu->actions()) {
if (action->isVisible() && !action->isSeparator()) {
desktopMenu->addAction(action);
}
}
} else {
desktopMenu->addMenu(containmentMenu);
}
}
}
if (containment()->immutability() == Plasma::Types::Mutable &&
(containment()->containmentType() != Plasma::Types::PanelContainment || containment()->isUserConfiguring())) {
QAction *closeApplet = applet->actions()->action(QStringLiteral("remove"));
//qDebug() << "checking for removal" << closeApplet;
if (closeApplet) {
if (!desktopMenu->isEmpty()) {
desktopMenu->addSeparator();
}
//qDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
desktopMenu->addAction(closeApplet);
}
}
}
void DockView::addContainmentActions(QMenu *desktopMenu, QEvent *event)
{
if (!containment()) {
return;
}
if (containment()->corona()->immutability() != Plasma::Types::Mutable &&
!KAuthorized::authorizeAction(QStringLiteral("plasma/containment_actions"))) {
//qDebug() << "immutability";
return;
}
//this is what ContainmentPrivate::prepareContainmentActions was
const QString trigger = Plasma::ContainmentActions::eventToString(event);
//"RightButton;NoModifier"
Plasma::ContainmentActions *plugin = containment()->containmentActions().value(trigger);
if (!plugin) {
return;
}
if (plugin->containment() != containment()) {
plugin->setContainment(containment());
// now configure it
KConfigGroup cfg(containment()->corona()->config(), "ActionPlugins");
cfg = KConfigGroup(&cfg, QString::number(containment()->containmentType()));
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
plugin->restore(pluginConfig);
}
QList<QAction *> actions = plugin->contextualActions();
if (actions.isEmpty()) {
//it probably didn't bother implementing the function. give the user a chance to set
//a better plugin. note that if the user sets no-plugin this won't happen...
if ((containment()->containmentType() != Plasma::Types::PanelContainment &&
containment()->containmentType() != Plasma::Types::CustomPanelContainment) &&
containment()->actions()->action(QStringLiteral("configure"))) {
desktopMenu->addAction(containment()->actions()->action(QStringLiteral("configure")));
}
} else {
desktopMenu->addActions(actions);
}
return;
}
//!END overriding context menus behavior
}
//!END SLOTS
//!END namespace

@ -27,23 +27,19 @@
#include <QQuickView>
#include <QQmlListProperty>
#include <QMenu>
#include <QScreen>
#include <QPointer>
#include <QTimer>
#include <PlasmaQuick/AppletQuickItem>
namespace Plasma {
class Types;
class Corona;
class Containment;
}
/*namespace Candil {
class Dock;
class DockView;
class DockConfigView;
class VisibilityManager;
}*/
namespace Latte {
class DockView : public PlasmaQuick::ContainmentView {
@ -103,6 +99,8 @@ public:
static QScreen *atScreens(QQmlListProperty<QScreen> *property, int index);
public slots:
Q_INVOKABLE void addAppletItem(QObject *item);
Q_INVOKABLE void removeAppletItem(QObject *item);
Q_INVOKABLE void addNewDock();
Q_INVOKABLE QVariantList containmentActions();
//used from the configuration window
@ -121,7 +119,8 @@ protected slots:
protected:
bool event(QEvent *ev) override;
// void showEvent(QShowEvent *ev) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
signals:
// void visibilityChanged();
@ -144,6 +143,9 @@ public slots:
void updateDockPositionSlot();
void updateAbsDockGeometry();
private slots:
void menuAboutToHide();
private:
bool m_secondInitPass;
@ -155,6 +157,9 @@ private:
QRect m_localDockGeometry;
QRect m_maskArea;
QPointer<PlasmaQuick::ConfigView> m_configView;
QMenu *m_contextMenu;
QList<PlasmaQuick::AppletQuickItem *> m_appletItems;
QTimer m_timerGeometry;
QTimer m_lockGeometry;
@ -162,9 +167,10 @@ private:
QPointer<VisibilityManager> m_visibility;
bool containmentContainsPosition(const QPointF &point) const;
QPointF positionAdjustedForContainment(const QPointF &point) const;
void initWindow();
void addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEvent *event);
void addContainmentActions(QMenu *desktopMenu, QEvent *event);
};
}

@ -424,6 +424,12 @@ DragDrop.DropArea {
dock.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged);
dock.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide);
dock.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown);
// adding the AppletQuickItem to the Now Dock in order to be
// used for right clicking events
for(var i=0; i<plasmoid.applets.length; ++i) {
dock.addAppletItem(plasmoid.applets[i]);
}
}
}
@ -546,6 +552,8 @@ DragDrop.DropArea {
LayoutManager.save();
updateIndexes();
dock.removeAppletItem(applet)
}
Plasmoid.onUserConfiguringChanged: {

@ -626,12 +626,18 @@ PlasmaComponents.ContextMenu {
var actionList = nowDockPanel.containmentActions();
if (actionList.length > 1) {
for (var i=0; i<actionList.length; ++i){
var item = menu.newMenuItem(containmentSubMenu);
item.visible = false;
item.action = actionList[i];
containmentSubMenu.addMenuItem(item,containmentMenuItem);
}
} else if (actionList.length === 1){
var item = menu.newMenuItem(menu);
item.action = actionList[0];
containmentMenuItem.visible = false;
}
}
Component.onCompleted: refresh();

Loading…
Cancel
Save