diff options
Diffstat (limited to 'src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets')
5 files changed, 404 insertions, 0 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.cpp new file mode 100644 index 00000000..139eee89 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.cpp @@ -0,0 +1,184 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2012-2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "ContextMenu.h" +#include <global-objects.h> +#include <JsonMenu.h> +#include <LIconCache.h> + +void DesktopContextMenu::SettingsChanged(DesktopSettings::File file){ + if(file == DesktopSettings::ContextMenu){ UpdateMenu(false); } +} + +void DesktopContextMenu::UpdateMenu(bool fast){ + //Put a label at the top + unsigned int num = Lumina::NWS->currentWorkspace(); + workspaceLabel->setText( "<b>"+QString(tr("Workspace %1")).arg(QString::number(num+1))+"</b>"); + if(fast && usewinmenu){ updateWinMenu(); } + if(fast){ return; } //already done + this->clear(); //clear it for refresh + this->addAction(wkspaceact); + this->addSeparator(); + //Now load the user's menu setup and fill the menu + QStringList items = DesktopSettings::instance()->value(DesktopSettings::ContextMenu, "itemlist", QStringList()<< "terminal" << "filemanager" << "line" << "applications" << "windowlist" << "settings" << "lockdesktop").toStringList(); + usewinmenu=false; + for(int i=0; i<items.length(); i++){ + if(items[i]=="terminal"){ + QAction *act = this->addAction( tr("Terminal")); + LIconCache::instance()->loadIcon(act, "utilities-terminal"); + act->setWhatsThis("--terminal"); + } + else if(items[i]=="lockdesktop"){ + QAction *act = this->addAction( tr("Lock Session"), this, SIGNAL(LockSession()) ); + LIconCache::instance()->loadIcon(act, "system-lock-screen"); + } + else if(items[i]=="filemanager"){ + QAction *act = this->addAction( tr("Browse Files")); + LIconCache::instance()->loadIcon(act, "user-home"); + act->setWhatsThis(QDir::homePath()); + } + else if(items[i]=="applications"){ + if(appMenu==0){ updateAppMenu(); } + this->addMenu( appMenu ); + } + else if(items[i]=="line"){ this->addSeparator(); } + //else if(items[i]=="settings"){ this->addMenu( LSession::handle()->settingsMenu() ); } + else if(items[i]=="windowlist"){ + if(winMenu==0){ updateWinMenu(); } + this->addMenu( winMenu); + usewinmenu=true; + }else if(items[i].startsWith("app::::") && items[i].endsWith(".desktop")){ + //Custom *.desktop application + QString file = items[i].section("::::",1,1).simplified(); + //Try to use the pre-loaded app entry for this + XDGDesktop *xdg = XDGDesktopList::instance()->findAppFile(file); + if(xdg!=0){ xdg->addToMenu(this); } + else{ + XDGDesktop xdgf(file);// = LXDG::loadDesktopFile(file, ok); + if(xdgf.type!=XDGDesktop::BAD){ xdgf.addToMenu(this); } + } + }else if(items[i].startsWith("jsonmenu::::")){ + //Custom JSON menu system (populated on demand via external scripts/tools + QStringList info = items[i].split("::::"); //FORMAT:[ "jsonmenu",exec,name, icon(optional)] + if(info.length()>=3){ + //qDebug() << "Custom JSON Menu Loaded:" << info; + JsonMenu *tmp = new JsonMenu(info[1], this); + tmp->setTitle(info[2]); + connect(tmp, SIGNAL(triggered(QAction*)), this, SLOT(SystemApplication(QAction*)) ); + if(info.length()>=4){ tmp->setIcon( LXDG::findIcon(info[3],"") ); } + this->addMenu(tmp); + } + } + } + //Now add the system quit options + this->addSeparator(); + this->addAction(LXDG::findIcon("system-log-out",""), tr("Leave"), this, SIGNAL(showLeaveDialog()) ); +} + +// === PRIVATE === +void DesktopContextMenu::AddWindowToMenu(NativeWindowObject *win){ + QString label = win->property(NativeWindowObject::ShortTitle).toString(); + if(label.isEmpty()){ label = win->property(NativeWindowObject::Title).toString(); } + if(label.isEmpty()){ label = win->property(NativeWindowObject::Name).toString(); } + QAction *tmp = winMenu->addAction( win->property(NativeWindowObject::Icon).value<QIcon>(), label, win, SLOT(toggleVisibility()) ); + //Need to change the visual somehow to indicate whether it is visible or not + //bool visible = win->property(NativeWindow::Visible).toBool(); + // TODO +} + +// === PUBLIC === +DesktopContextMenu::DesktopContextMenu(QWidget *parent) : QMenu(parent){ + if(parent!=0){ + parent->setContextMenuPolicy(Qt::CustomContextMenu); + connect(parent, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMenu(const QPoint&)) ); + } + appMenu = 0; + winMenu = 0; + usewinmenu = false; + workspaceLabel = new QLabel(0); + workspaceLabel->setAlignment(Qt::AlignCenter); + wkspaceact = new QWidgetAction(0); + wkspaceact->setDefaultWidget(workspaceLabel); + connect(this, SIGNAL(triggered(QAction*)), this, SLOT(LaunchAction(QAction*)) ); + //Connect to a couple global objects + connect(this, SIGNAL(aboutToShow()), this, SLOT(UpdateMenu()) ); //this will do a "fast" update + qDebug() << "Done Creating Context Menu"; +} + +DesktopContextMenu::~DesktopContextMenu(){ + //nothing special + //workspaceLabel->deleteLater(); //The QWidgetAction takes ownership of the label when inserted - do not manually delete + wkspaceact->deleteLater(); +} + +void DesktopContextMenu::start(){ + connect(DesktopSettings::instance(), SIGNAL(FileModified(DesktopSettings::File)), this, SLOT(SettingsChanged(DesktopSettings::File)) ); + connect(this, SIGNAL(LockSession()), Lumina::SS, SLOT(LockScreenNow()) ); + connect(XDGDesktopList::instance(), SIGNAL(appsUpdated()), this, SLOT(updateAppMenu()) ); + UpdateMenu(false); + //Still need to connect to some "workspaceChanged(int)" signal +} + +// === PRIVATE SLOTS === +void DesktopContextMenu::LaunchAction(QAction *act){ + //qDebug() << "Launch Action Triggered:" << act->whatsThis(); + if(act->whatsThis().isEmpty() || act->parent()!=this ){ return; } + qDebug() << "Launch Menu Action:" << act->whatsThis(); + QString cmd = act->whatsThis(); + if(cmd.startsWith("-action ")){ + LaunchApp(act); //forward this to the XDGDesktop parser + }else if(cmd.startsWith("--") || cmd.endsWith(".desktop")){ + LSession::instance()->LaunchStandardApplication(cmd); + }else if(QFile::exists(cmd)){ + QString mime = XDGMime::fromFileName(cmd); + LSession::instance()->LaunchStandardApplication(mime, QStringList() << cmd); + } +} + +void DesktopContextMenu::LaunchApp(QAction *act){ + + // The "whatsThis() field is set by the XDGDesktop object/format + if(act->whatsThis().isEmpty()){ return; } + QString action, file; + QString wt = act->whatsThis(); + if(wt.startsWith("-action")){ + action = wt.section(" ",1,1); action=action.remove("\""); + file = wt.section(" ",2,-1); file=file.remove("\""); + } + else{ file = wt; } + LSession::instance()->LaunchDesktopApplication(file, action); + +} + +void DesktopContextMenu::showMenu(const QPoint &pt){ + this->popup(pt); +} + +void DesktopContextMenu::updateAppMenu(){ + //qDebug() << "Update App Menu"; + if(appMenu==0){ + appMenu = new QMenu(this); + appMenu->setTitle( tr("Applications")); + LIconCache::instance()->loadIcon( appMenu, "system-run"); + connect(appMenu, SIGNAL(triggered(QAction*)), this, SLOT(LaunchApp(QAction*)) ); + } + //qDebug() << "Populate App Menu"; + XDGDesktopList::instance()->populateMenu(appMenu); +} + +void DesktopContextMenu::updateWinMenu(){ + //qDebug() << "Update Win Menu"; + if(winMenu==0){ + winMenu = new QMenu(this); + winMenu->setTitle( tr("Task Manager") ); + LIconCache::instance()->loadIcon( winMenu, "preferences-system-windows"); + } + winMenu->clear(); + QList<NativeWindowObject*> wins = RootDesktopObject::instance()->windowObjects(); + for(int i=0; i<wins.length(); i++){ + AddWindowToMenu(wins.at(i)); + } +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.h new file mode 100644 index 00000000..b20087ef --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/ContextMenu.h @@ -0,0 +1,48 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2012-2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_CONTEXT_MENU_H +#define _LUMINA_DESKTOP_CONTEXT_MENU_H + +#include <global-includes.h> + +class DesktopContextMenu : public QMenu{ + Q_OBJECT +public slots: + void SettingsChanged(DesktopSettings::File); + void UpdateMenu(bool fast = true); //re-create the menu + +private: + QLabel *workspaceLabel; + QWidgetAction *wkspaceact; + QMenu *appMenu, *winMenu; + bool usewinmenu; + + void AddWindowToMenu(NativeWindowObject*); + +public: + DesktopContextMenu(QWidget *parent = 0); + ~DesktopContextMenu(); + + void start(); //setup connections to global objects + +private slots: + void LaunchAction(QAction *act); + void LaunchApp(QAction *act); + + void showMenu(const QPoint&); + + void updateAppMenu(); + void updateWinMenu(); + +signals: + void LockSession(); + void showLeaveDialog(); + void LaunchStandardApplication(QString); + void LaunchApplication(QString); +}; + +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.cpp new file mode 100644 index 00000000..9e22a143 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.cpp @@ -0,0 +1,120 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2018, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include <global-objects.h> +#include "RootDesktop.h" + +// === PUBLIC === +RootDesktop::RootDesktop(QWindow *) : QWidget(0, Qt::Widget | Qt::FramelessWindowHint | Qt::WindowStaysOnBottomHint){ + +} + +RootDesktop::~RootDesktop(){ + +} + +void RootDesktop::start(){ + //qDebug() << "Starting RootDesktop" << this->geometry() << this->isVisible(); + bgTimer = new QTimer(this); + bgTimer->setInterval(50); + bgTimer->setSingleShot(true); + connect(bgTimer, SIGNAL(timeout()), this, SLOT(bgTimerUpdate()) ); + + cmenu = new DesktopContextMenu(this); + + //Setup the connections to the main objects + connect(RootDesktopObject::instance(), SIGNAL(screensChanged()), this, SLOT(on_screensChanged()) ); + connect(RootDesktopObject::instance(), SIGNAL(panelsChanged()), this, SLOT(on_panelsChanged()) ); + connect(RootDesktopObject::instance(), SIGNAL(windowsChanged()), this, SLOT(on_windowsChanged()) ); + connect(RootDesktopObject::instance(), SIGNAL(trayWindowsChanged()), this, SLOT(on_trayWindowsChanged()) ); + + connect(cmenu, SIGNAL(LockSession()), RootDesktopObject::instance(), SIGNAL(lockScreen()) ); + connect(cmenu, SIGNAL(showLeaveDialog()), RootDesktopObject::instance(), SIGNAL(startLogout()) ); + connect(cmenu, SIGNAL(LaunchStandardApplication(QString)), RootDesktopObject::instance(), SIGNAL(launchApplication(QString)) ); + connect(cmenu, SIGNAL(LaunchApplication(QString)), RootDesktopObject::instance(), SIGNAL(launchApplication(QString)) ); + + on_screensChanged(); //make sure this is setup right away (sets up connections + QTimer::singleShot(0, this, SLOT(on_panelsChanged()) ); + QTimer::singleShot(2, this, SLOT(on_windowsChanged()) ); + QTimer::singleShot(4, this, SLOT(on_trayWindowsChanged()) ); + + //Now start the first-run of the background change system + cmenu->start(); + bgTimer->start(); + this->show(); +} + +// === PRIVATE === +//QImage bgimage; + + +// === PRIVATE SLOTS === +//RootDesktopObject connections +void RootDesktop::on_screensChanged(){ + QStringList screens = RootDesktopObject::instance()->screens(); + //qDebug() << "Screens Changed:" << lastscreens << screens; + for(int i=0; i<screens.length(); i++){ + if(!lastscreens.contains(screens[i])){ + connect(RootDesktopObject::instance()->screen(screens[i]), SIGNAL(backgroundChanged()), this, SLOT(on_screen_bg_changed()) ); + } + } + on_screen_bg_changed(); //start the timer to update the backgrounds now + lastscreens = screens; //save this for later +} + +void RootDesktop::on_panelsChanged(){ + +} + +void RootDesktop::on_windowsChanged(){ + +} + +void RootDesktop::on_trayWindowsChanged(){ + +} + +void RootDesktop::on_screen_bg_changed(){ + if(!bgTimer->isActive()){ bgTimer->start(); } +} + +//Internal use +void RootDesktop::bgTimerUpdate(){ + //qDebug() << "bgTimerUpdate"; + //QtConcurrent::run(this, &RootDesktop::updateBG, this); + updateBG(this); +} + +void RootDesktop::updateBG(RootDesktop* obj){ + + QImage tmp(obj->size(), QImage::Format_ARGB32_Premultiplied); + QStringList scr = RootDesktopObject::instance()->screens(); + //qDebug() << "updateBG" << scr << tmp.size() << obj->geometry(); + QPainter imgpaint(&tmp); + for(int i=0; i<scr.length(); i++){ + ScreenObject * screen = RootDesktopObject::instance()->screen(scr[i]); + QString file = screen->background(); //in URL format + //qDebug() << "Got BG File:" << file << QUrl(file).toLocalFile(); + QImage img(QUrl(file).toLocalFile()); + //qDebug() << " - BG File is null:" << img.isNull(); + imgpaint.drawImage(screen->geometry(), img, QRect(0,0,img.width(), img.height()) ); + } + bgimage = tmp; + //QTimer::singleShot(0, obj, SLOT(update()) ); + obj->update(); +} + +// === PROTECTED === +void RootDesktop::paintEvent(QPaintEvent *ev){ + //qDebug() << "Paint Event:" << bgimage.isNull(); + if (!bgimage.isNull()) { + //qDebug() << "Wallpaper paint Event:" << ev->rect(); + QPainter painter(this); + painter.drawImage(ev->rect(), bgimage, ev->rect()); + }else{ + QWidget::paintEvent(ev); + } +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.h new file mode 100644 index 00000000..16ce0e47 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/RootDesktop.h @@ -0,0 +1,44 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2018, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_WIDGETS_ROOT_DESKTOP_H +#define _LUMINA_DESKTOP_WIDGETS_ROOT_DESKTOP_H + +#include <global-includes.h> +#include "ContextMenu.h" + +class RootDesktop : public QWidget{ + Q_OBJECT +public: + RootDesktop(QWindow *root); + ~RootDesktop(); + + void start(); + +private: + QImage bgimage; + QStringList lastscreens; + QTimer *bgTimer; + DesktopContextMenu *cmenu; + +private slots: + //RootDesktopObject connections + void on_screensChanged(); + void on_panelsChanged(); + void on_windowsChanged(); + void on_trayWindowsChanged(); + void on_screen_bg_changed(); + + //Internal use + void bgTimerUpdate(); + void updateBG(RootDesktop* obj); //designed to be run in a background thread + +protected: + virtual void paintEvent(QPaintEvent *ev); + +}; + +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri new file mode 100644 index 00000000..7994bb93 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-widgets/src-widgets.pri @@ -0,0 +1,8 @@ +#update the includepath so we can just #include as needed without paths +INCLUDEPATH *= $${PWD} + +SOURCES *= $${PWD}/RootDesktop.cpp \ + $${PWD}/ContextMenu.cpp + +HEADERS *= $${PWD}/RootDesktop.h \ + $${PWD}/ContextMenu.h |