/* * * Copyright (C) 2013 * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include 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(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(event); if (e->button() == Qt::LeftButton) mDragStartPosition = e->pos(); } else if (event->type() == QEvent::MouseMove) { QMouseEvent *e = static_cast(event); handleMouseMoveEvent(e); } else if(event->type() == QEvent::ToolTip) { QHelpEvent* helpEvent = static_cast(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(actionAt(mDragStartPosition)); if (!a) return; QList 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(action)->updateIcon(); // this seems to cause some incorrect menu behaviour. // qApp->processEvents(); } } }