aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.cpp
blob: 47f0e3d7d16e0d15829c98d2e75df47b7e724a48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//===========================================
//  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>

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(NativeWindow *win){
  QString label = win->property(NativeWindow::ShortTitle).toString();
  if(label.isEmpty()){ label = win->property(NativeWindow::Title).toString(); }
  if(label.isEmpty()){ label = win->property(NativeWindow::Name).toString(); }
  QAction *tmp = winMenu->addAction( win->property(NativeWindow::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<NativeWindow*> wins = Lumina::NWS->currentWindows();
  unsigned int wkspace = Lumina::NWS->currentWorkspace();
  for(int i=0; i<wins.length(); i++){
    //First check if this window is in the current workspace (or is "sticky")
    if(wins.at(i)->property(NativeWindow::Workspace).toUInt() != wkspace
	      && wins.at(i)->property(NativeWindow::States).value< QList<NativeWindow::State> >().contains(NativeWindow::S_STICKY) ){
      continue;
    }
    AddWindowToMenu(wins.at(i));
  }
}
bgstack15