1 //===========================================
2 //  Lumina-DE source code
3 //  Copyright (c) 2015, Ken Moore
4 //  Available under the 3-clause BSD license
5 //  See the LICENSE file for full details
6 //===========================================
7 #include "TrayIcon.h"
8 
9 #include <QDir>
10 #include <QDesktopWidget>
11 
12 #include <LUtils.h>
13 
TrayIcon()14 TrayIcon::TrayIcon() : QSystemTrayIcon(){
15   //Create the child widgets here
16   settings = new QSettings("lumina-desktop","lumina-terminal");
17   this->setContextMenu(new QMenu());
18   ScreenMenu = new QMenu();
19     connect(ScreenMenu, SIGNAL(triggered(QAction*)), this, SLOT(ChangeScreen(QAction*)) );
20   TERM = new TermWindow(settings);
21     //Load the current settings
22     TERM->setTopOfScreen(settings->value("TopOfScreen",true).toBool());
23     TERM->setCurrentScreen(settings->value("OnScreen",0).toInt());
24   connect(TERM, SIGNAL(TerminalHidden()), this, SLOT(TermHidden()));
25   connect(TERM, SIGNAL(TerminalVisible()), this, SLOT(TermVisible()));
26   connect(TERM, SIGNAL(TerminalClosed()), this, SLOT(startCleanup()));
27   connect(TERM, SIGNAL(TerminalFinished()), this, SLOT(stopApplication()));
28   connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(TrayActivated(QSystemTrayIcon::ActivationReason)) );
29 }
30 
~TrayIcon()31 TrayIcon::~TrayIcon(){
32   delete TERM;
33   delete ScreenMenu;
34 }
35 
36 // =============
37 //      PUBLIC
38 // =============
parseInputs(QStringList inputs)39 void TrayIcon::parseInputs(QStringList inputs){
40   //Note that this is only run on the primary process - otherwise inputs are sent to the slotSingleInstance() below
41   termVisible = !inputs.contains("-toggle"); //will automatically show the terminal on first run, even if "-toggle" is set
42 
43   setupContextMenu();
44   updateIcons();
45   inputs = adjustInputs(inputs); //will adjust termVisible as necessary
46   if(inputs.isEmpty()){ inputs << QDir::homePath(); } //always start up with one terminal minimum
47   TERM->OpenDirs(inputs);
48   if(termVisible){ QTimer::singleShot(0, TERM, SLOT(ShowWindow())); }
49 }
50 
51 // =================
52 //     PUBLIC SLOTS
53 // =================
slotSingleInstance(QStringList inputs)54 void TrayIcon::slotSingleInstance(QStringList inputs){
55   //Note that this is only run for a secondary process forwarding its inputs
56   //qDebug() << "Single Instance Event:" << inputs << termVisible;
57   bool visible = termVisible;
58   inputs = adjustInputs(inputs); //will adjust termVisible as necessary
59   if(!inputs.isEmpty()){ TERM->OpenDirs(inputs); }
60   //Only adjust the window if there was a change in the visibility status
61   //qDebug() << "Set Visible:" << termVisible;
62   if(!visible && termVisible){ QTimer::singleShot(0, TERM, SLOT(ShowWindow())); }
63   else if(visible && !termVisible){ QTimer::singleShot(0, TERM, SLOT(HideWindow())); }
64 }
65 
updateIcons()66 void TrayIcon::updateIcons(){
67   this->setIcon(LXDG::findIcon("utilities-terminal",""));
68 }
69 
70 // ================
71 //         PRIVATE
72 // ================
adjustInputs(QStringList inputs)73 QStringList TrayIcon::adjustInputs(QStringList inputs){
74   bool hasHide = false;
75   //Look for the special CLI flags just for the tray icon and trim them out
76   for(int i=0; i<inputs.length(); i++){
77     if(inputs[i]=="-toggle"){ hasHide = termVisible; inputs.removeAt(i); i--; } //toggle the visibility
78     else if(inputs[i]=="-show"){ hasHide = false; inputs.removeAt(i); i--; } //change the visibility
79     else if(inputs[i]=="-hide"){  hasHide = true; inputs.removeAt(i); i--; } //change the visibility
80     else{
81 	//Must be a directory - convert to an absolute path and check for existance
82 	inputs[i] = LUtils::PathToAbsolute(inputs[i]);
83 	QFileInfo info(inputs[i]);
84 	if(!info.exists()){
85 	  qDebug() << "Directory does not exist: " << inputs[i];
86 	  inputs.removeAt(i);
87 	  i--;
88 	}else if(!info.isDir()){
89 	 //Must be some kind of file, open the parent directory
90 	  inputs[i] = inputs[i].section("/",0,-2);
91 	}
92     }
93   }
94   termVisible = !hasHide;
95   return inputs;
96 }
97 
98 // ================
99 //  PRIVATE SLOTS
100 // ================
startCleanup()101 void TrayIcon::startCleanup(){
102   TERM->cleanup();
103 }
104 
stopApplication()105 void TrayIcon::stopApplication(){
106   QApplication::exit(0);
107 }
108 
ChangeTopBottom(bool ontop)109 void TrayIcon::ChangeTopBottom(bool ontop){
110   TERM->setTopOfScreen(ontop);
111   settings->setValue("TopOfScreen",ontop); //save for later
112 }
113 
ChangeScreen(QAction * act)114 void TrayIcon::ChangeScreen(QAction *act){
115   int screen = act->whatsThis().toInt();
116   TERM->setCurrentScreen(screen);
117   settings->setValue("OnScreen",screen);
118   updateScreenMenu();
119 }
120 
setupContextMenu()121 void TrayIcon::setupContextMenu(){
122   this->contextMenu()->clear();
123   this->contextMenu()->addAction(LXDG::findIcon("edit-select",""), tr("Trigger Terminal"), this, SLOT(ToggleVisibility()) );
124   this->contextMenu()->addSeparator();
125   QAction * act = this->contextMenu()->addAction(tr("Top of Screen"), this, SLOT(ChangeTopBottom(bool)) );
126     act->setCheckable(true);
127     act->setChecked(settings->value("TopOfScreen",true).toBool() );
128   this->contextMenu()->addMenu(ScreenMenu);
129   this->contextMenu()->addSeparator();
130   this->contextMenu()->addAction(LXDG::findIcon("application-exit",""), tr("Close Terminal"), this, SLOT(stopApplication()) );
131   updateScreenMenu();
132 }
133 
updateScreenMenu()134 void TrayIcon::updateScreenMenu(){
135   ScreenMenu->clear();
136   QDesktopWidget *desk = QApplication::desktop();
137   int cscreen = settings->value("OnScreen",0).toInt();
138   if(cscreen>=desk->screenCount()){ cscreen = desk->primaryScreen(); }
139   ScreenMenu->setTitle(tr("Move To Monitor"));
140   for(int i=0; i<desk->screenCount(); i++){
141     if(i!=cscreen){
142       QAction *act = new QAction( QString(tr("Monitor %1")).arg(QString::number(i+1)),ScreenMenu);
143 	act->setWhatsThis(QString::number(i));
144       ScreenMenu->addAction(act);
145     }
146   }
147   ScreenMenu->setVisible(!ScreenMenu->isEmpty());
148   ScreenMenu->setEnabled(!ScreenMenu->isEmpty());
149 }
150 
TrayActivated(QSystemTrayIcon::ActivationReason reason)151 void TrayIcon::TrayActivated(QSystemTrayIcon::ActivationReason reason){
152   switch(reason){
153     case QSystemTrayIcon::Context:
154 	this->contextMenu()->popup(this->geometry().center());
155         break;
156     default:
157 	ToggleVisibility();
158   }
159 }
160 
161 //Slots for the window visibility
ToggleVisibility()162 void TrayIcon::ToggleVisibility(){
163   if(termVisible){ QTimer::singleShot(0, TERM, SLOT(HideWindow())); }
164   else{ QTimer::singleShot(0, TERM, SLOT(ShowWindow())); }
165 }
166 
TermHidden()167 void TrayIcon::TermHidden(){
168   termVisible = false;
169 }
170 
TermVisible()171 void TrayIcon::TermVisible(){
172   termVisible = true;
173 }
174