You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lxqt-panel-packaging/plugin-mainmenu/xdgcachedmenu.cpp

204 lines
6.0 KiB

/*
* <one line to give the library's name and an idea of what it does.>
* Copyright (C) 2013 <copyright holder> <email>
*
* This library 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 2.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "xdgcachedmenu.h"
#include <QAction>
#include <QIcon>
#include <QCursor>
#include <QToolTip>
#include <QList>
#include <QUrl>
#include <QDrag>
#include <QMouseEvent>
#include <QApplication>
#include <XdgDesktopFile>
#include <XdgIcon>
#include <QHelpEvent>
#include <QMimeData>
#include <QDebug>
XdgCachedMenuAction::XdgCachedMenuAction(MenuCacheItem* item, QObject* parent):
QAction{parent}
, iconName_{QString::fromUtf8(menu_cache_item_get_icon(item))}
{
QString title = QString::fromUtf8(menu_cache_item_get_name(item));
title = title.replace('&', QLatin1String("&&")); // & is reserved for mnemonics
setText(title);
// Only set tooltips for app items
if(menu_cache_item_get_type(item) == MENU_CACHE_TYPE_APP)
{
QString comment = QString::fromUtf8(menu_cache_item_get_comment(item));
setToolTip(comment);
}
if (char * file_path = menu_cache_item_get_file_path(item))
{
filePath_ = QString::fromUtf8(file_path);
g_free(file_path);
}
}
void XdgCachedMenuAction::updateIcon()
{
if(icon().isNull())
{
QIcon icon = XdgIcon::fromTheme(iconName_, QIcon::fromTheme("unknown"));
setIcon(icon);
}
}
XdgCachedMenu::XdgCachedMenu(QWidget* parent): QMenu(parent)
{
connect(this, SIGNAL(aboutToShow()), SLOT(onAboutToShow()));
}
XdgCachedMenu::XdgCachedMenu(MenuCache* menuCache, QWidget* parent): QMenu(parent)
{
// qDebug() << "CREATE MENU FROM CACHE" << menuCache;
MenuCacheDir* dir = menu_cache_dup_root_dir(menuCache);
// get current desktop name or fallback to LXQt
const QByteArray xdgDesktop = qgetenv("XDG_CURRENT_DESKTOP");
const QByteArray desktop = xdgDesktop.isEmpty() ? "LXQt:X-LXQt" : xdgDesktop;
menu_cache_desktop_ = menu_cache_get_desktop_env_flag(menuCache, desktop.constData());
addMenuItems(this, dir);
menu_cache_item_unref(MENU_CACHE_ITEM(dir));
connect(this, SIGNAL(aboutToShow()), SLOT(onAboutToShow()));
}
XdgCachedMenu::~XdgCachedMenu()
{
}
void XdgCachedMenu::addMenuItems(QMenu* menu, MenuCacheDir* dir)
{
GSList* list = menu_cache_dir_list_children(dir);
for(GSList * l = list; l; l = l->next)
{
MenuCacheItem* item = (MenuCacheItem*)l->data;
MenuCacheType type = menu_cache_item_get_type(item);
if(type == MENU_CACHE_TYPE_SEP)
{
menu->addSeparator();
continue;
}
else
{
bool appVisible = type == MENU_CACHE_TYPE_APP
&& menu_cache_app_get_is_visible(MENU_CACHE_APP(item),
menu_cache_desktop_);
bool dirVisible = type == MENU_CACHE_TYPE_DIR
&& menu_cache_dir_is_visible(MENU_CACHE_DIR(item));
if(!appVisible && !dirVisible)
continue;
XdgCachedMenuAction* action = new XdgCachedMenuAction(item, menu);
menu->addAction(action);
if(type == MENU_CACHE_TYPE_APP)
connect(action, SIGNAL(triggered(bool)), SLOT(onItemTrigerred()));
else if(type == MENU_CACHE_TYPE_DIR)
{
XdgCachedMenu* submenu = new XdgCachedMenu(menu);
action->setMenu(submenu);
addMenuItems(submenu, MENU_CACHE_DIR(item));
}
}
menu_cache_item_unref(item);
}
if (list)
g_slist_free(list);
}
void XdgCachedMenu::onItemTrigerred()
{
XdgCachedMenuAction* action = static_cast<XdgCachedMenuAction*>(sender());
XdgDesktopFile df;
df.load(action->filePath());
df.startDetached();
}
// taken from libqtxdg: XdgMenuWidget
bool XdgCachedMenu::event(QEvent* event)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *e = static_cast<QMouseEvent*>(event);
if (e->button() == Qt::LeftButton)
mDragStartPosition = e->pos();
}
else if (event->type() == QEvent::MouseMove)
{
QMouseEvent *e = static_cast<QMouseEvent*>(event);
handleMouseMoveEvent(e);
}
else if(event->type() == QEvent::ToolTip)
{
QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
QAction* action = actionAt(helpEvent->pos());
if(action && action->menu() == NULL)
QToolTip::showText(helpEvent->globalPos(), action->toolTip(), this);
}
return QMenu::event(event);
}
// taken from libqtxdg: XdgMenuWidget
void XdgCachedMenu::handleMouseMoveEvent(QMouseEvent *event)
{
if (!(event->buttons() & Qt::LeftButton))
return;
if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance())
return;
XdgCachedMenuAction *a = qobject_cast<XdgCachedMenuAction*>(actionAt(mDragStartPosition));
if (!a)
return;
QList<QUrl> urls;
urls << QUrl(QString("file://%1").arg(a->filePath()));
QMimeData *mimeData = new QMimeData();
mimeData->setUrls(urls);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction | Qt::LinkAction);
}
void XdgCachedMenu::onAboutToShow()
{
Q_FOREACH(QAction* action, actions())
{
if(action->inherits("XdgCachedMenuAction"))
{
static_cast<XdgCachedMenuAction*>(action)->updateIcon();
// this seems to cause some incorrect menu behaviour.
// qApp->processEvents();
}
}
}