diff options
author | Ken Moore <moorekou@gmail.com> | 2015-09-17 12:23:59 -0400 |
---|---|---|
committer | Ken Moore <moorekou@gmail.com> | 2015-09-17 12:23:59 -0400 |
commit | 849295c448bd70b54d4ca2aa8b6269ae58e4ae4c (patch) | |
tree | f5f075a6cfd1a0820f034ec5e8116df477fd6dd3 | |
parent | Make the snapshot load/reload operations "active", in that it will detect whe... (diff) | |
download | lumina-849295c448bd70b54d4ca2aa8b6269ae58e4ae4c.tar.gz lumina-849295c448bd70b54d4ca2aa8b6269ae58e4ae4c.tar.bz2 lumina-849295c448bd70b54d4ca2aa8b6269ae58e4ae4c.zip |
Add my work-in-progress for a lumina-terminal application. This is *not* ready to be distributed yet, only the basic application wrapper is functional (no terminal functionality yet).
-rw-r--r-- | desktop-utilities/desktop-utilities.pro | 3 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TermWindow.cpp | 256 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TermWindow.h | 66 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TerminalWidget.cpp | 83 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TerminalWidget.h | 36 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TrayIcon.cpp | 172 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TrayIcon.h | 59 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/lumina-terminal.pro | 110 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/main.cpp | 47 |
9 files changed, 832 insertions, 0 deletions
diff --git a/desktop-utilities/desktop-utilities.pro b/desktop-utilities/desktop-utilities.pro new file mode 100644 index 00000000..8d6c5f46 --- /dev/null +++ b/desktop-utilities/desktop-utilities.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS+= lumina-terminal diff --git a/desktop-utilities/lumina-terminal/TermWindow.cpp b/desktop-utilities/lumina-terminal/TermWindow.cpp new file mode 100644 index 00000000..4fc7fab5 --- /dev/null +++ b/desktop-utilities/lumina-terminal/TermWindow.cpp @@ -0,0 +1,256 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "TermWindow.h" +//#include "ui_TermWindow.h" + +#include <QDesktopWidget> +#include <QDebug> +#include <QTimer> +#include <QApplication> +#include <QVBoxLayout> +#include "TerminalWidget.h" + +// =============== +// PUBLIC +// =============== +TermWindow::TermWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint){//, ui(new Ui::TermWindow){ + CLOSING = false; //internal flag + //Create the Window + this->setLayout(new QVBoxLayout()); + this->setCursor(Qt::SplitVCursor); + tabWidget = new QTabWidget(this); + tabWidget->clear(); //just in case + tabWidget->setCursor(Qt::ArrowCursor); + tabWidget->setTabBarAutoHide(true); + tabWidget->setTabsClosable(true); + tabWidget->setMovable(true); + tabWidget->setUsesScrollButtons(true); + this->layout()->addWidget(tabWidget); + //Setup the animation + ANIM = new QPropertyAnimation(this, "geometry", this); + ANIM->setDuration(300); //1/3 second animation + connect(ANIM, SIGNAL(finished()), this, SLOT(AnimFinished()) ); + //Create the keyboard shortcuts + hideS = new QShortcut(QKeySequence(Qt::Key_Escape),this); + closeS = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q),this); + newTabS = new QShortcut(QKeySequence::AddTab,this); + closeTabS = new QShortcut(QKeySequence::Close,this); + //Connect the signals/slots + connect(tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(Close_Tab(int)) ); + connect(closeTabS, SIGNAL(activated()), this, SLOT(Close_Tab()) ); + connect(newTabS, SIGNAL(activated()), this, SLOT(New_Tab()) ); + connect(hideS, SIGNAL(activated()), this, SLOT(HideWindow()) ); + connect(closeS, SIGNAL(activated()), this, SLOT(CloseWindow()) ); + + //Now set the defaults + screennum = 0; //default value + setTopOfScreen(true); //default value + //this->resize(this->width(),300); + //this->setMinimumSize(20, 300); + +} + + +TermWindow::~TermWindow(){ + +} + +void TermWindow::cleanup(){ + //called right before the window is closed + //Make sure to close any open tabs/processes + CLOSING = true; + for(int i=0; i<tabWidget->count(); i++){ + static_cast<TerminalWidget*>(tabWidget->widget(i))->aboutToClose(); + } +} + +void TermWindow::OpenDirs(QStringList dirs){ + for(int i=0; i<dirs.length(); i++){ + //Open a new tab for each directory + TerminalWidget *page = new TerminalWidget(tabWidget, dirs[i]); + QString ID = GenerateTabID(); + page->setWhatsThis(ID); + tabWidget->addTab(page, ID); + qDebug() << "New Tab:" << ID << dirs[i]; + connect(page, SIGNAL(ProcessClosed(QString)), this, SLOT(Close_Tab(QString)) ); + } +} + +void TermWindow::setCurrentScreen(int num){ + screennum = num; + QTimer::singleShot(0,this, SLOT(ReShowWindow())); +} + +void TermWindow::setTopOfScreen(bool ontop){ + onTop = ontop; + this->layout()->setContentsMargins(0, (onTop ? 0 : 3), 0, (onTop ? 3 : 0)); + tabWidget->setTabPosition(onTop ? QTabWidget::South : QTabWidget::North); + QTimer::singleShot(0,this, SLOT(ReShowWindow())); +} + +// ======================= +// PUBLIC SLOTS +// ======================= +void TermWindow::ShowWindow(){ + this->hide(); + QApplication::processEvents(); + CalculateGeom(); + //Now setup the animation + animRunning = 1; + ANIM->setEndValue(this->geometry()); + if(onTop){ //use top edge + ANIM->setStartValue( QRect(this->x(), this->y(), this->width(), 0) ); //same location - no height + }else{ + ANIM->setStartValue( QRect(this->x(), this->geometry().bottom(), this->width(), 0) ); //same location - no height + } + this->show(); + ANIM->start(); +} + +void TermWindow::HideWindow(){ + //Now setup the animation + //Note: Do *not* use the private settings/variables because it may be changing right now - use the current geometry *ONLY* + animRunning = 0; + ANIM->setStartValue(this->geometry()); + QDesktopWidget *desk = QApplication::desktop(); + int screen = desk->screenNumber(this); //which screen it is currently on + if(desk->availableGeometry(screen).top() == this->geometry().top()){ //use top edge + ANIM->setEndValue( QRect(this->x(), this->y(), this->width(), 0) ); //same location - no height + }else{ + ANIM->setEndValue( QRect(this->x(), this->y()+this->height(), this->width(), 0) ); //same location - no height + } + this->show(); + ANIM->start(); +} + +void TermWindow::CloseWindow(){ + //Now setup the animation + animRunning = 2; + ANIM->setStartValue(this->geometry()); + if(onTop){ //use top edge + ANIM->setEndValue( QRect(this->x(), this->y(), this->width(), 0) ); //same location - no height + }else{ + ANIM->setEndValue( QRect(this->x(), this->geometry().bottom(), this->width(), 0) ); //same location - no height + } + this->show(); + ANIM->start(); +} + +void TermWindow::ReShowWindow(){ + if(this->isVisible()){ + HideWindow(); //start with same animation as hide + animRunning = 3; //flag as a re-show (hide, then show); + }else{ + //Already hidden, just show it + ShowWindow(); + } +} +// ======================= +// PRIVATE +// ======================= +void TermWindow::CalculateGeom(){ + QDesktopWidget *desk = QApplication::desktop(); + if(desk->screenCount() <= screennum){ screennum = desk->primaryScreen(); } //invalid screen detected + //Now align the window with the proper screen edge + QRect workarea = desk->availableGeometry(screennum); //this respects the WORKAREA property + if(onTop){ + this->setGeometry( workarea.x(), workarea.y(), workarea.width(), this->height()); //maintain current hight of window + + }else{ + this->setGeometry( workarea.x(), workarea.y() + workarea.height() - this->height(), workarea.width(), this->height()); //maintain current hight of window + } + this->setFixedWidth(this->width()); //Make sure the window is not re-sizeable in the width dimension + this->setMinimumHeight(0); +} + +QString TermWindow::GenerateTabID(){ + //generate a unique ID for this new tab + int num = 1; + for(int i=0; i<tabWidget->count(); i++){ + if(tabWidget->widget(i)->whatsThis().toInt() >= num){ num = tabWidget->widget(i)->whatsThis().toInt()+1; } + } + return QString::number(num); +} + +// ======================= +// PRIVATE SLOTS +// ======================= + +//Tab Interactions +void TermWindow::New_Tab(){ + OpenDirs(QStringList() << QDir::homePath()); +} + +void TermWindow::Close_Tab(int tab){ + //qDebug() << "Close Tab:" << tab; + if(tab<0){ tab = tabWidget->currentIndex(); } + static_cast<TerminalWidget*>(tabWidget->widget(tab))->aboutToClose(); + delete tabWidget->widget(tab); //delete the page within the tag + tabWidget->removeTab(tab); // remove the tab itself + //Make sure there is always at least one tab + if(tabWidget->count() < 1){ + if(CLOSING){ emit TerminalFinished(); } + else{ New_Tab(); } + } +} + +void TermWindow::Close_Tab(QString ID){ + //Close a tab based on it's ID instead of it's tab number + for(int i=0; i<tabWidget->count(); i++){ + if(tabWidget->widget(i)->whatsThis()==ID){ + Close_Tab(i); + return; //all done + } + } +} + +//Animation finishing +void TermWindow::AnimFinished(){ + if(animRunning <0){ return; } //nothing running + if(animRunning==0){ + //Hide Event + this->hide(); //need to hide the whole thing now + this->setGeometry( ANIM->startValue().toRect() ); //reset back to initial size after hidden + emit TerminalHidden(); + }else if(animRunning==1){ + //Show Event + this->activateWindow(); + tabWidget->currentWidget()->setFocus(); + emit TerminalVisible(); + }else if(animRunning==2){ + //Close Event + this->hide(); //need to hide the whole thing now + emit TerminalClosed(); + }else if(animRunning>2){ + //Re-Show event + this->hide(); + this->setGeometry( ANIM->startValue().toRect() ); //reset back to initial size after hidden + //Now re-show it + QTimer::singleShot(0,this, SLOT(ShowWindow())); + } + animRunning = -1; //done +} + +// =================== +// PROTECTED +// =================== +void TermWindow::mouseMoveEvent(QMouseEvent *ev){ + //Note: With mouse tracking turned off, this event only happens when the user is holding down the mouse button + if(onTop){ + //Move the bottom edge to the current point + if( (ev->globalPos().y() - this->y()) < 50){ return; } //quick check that the window is not smaller than 20 pixels + QRect geom = this->geometry(); + geom.setBottom(ev->globalPos().y()); + this->setGeometry(geom); + }else{ + //Move the top edge to the current point + if( (this->y() + this->height() -ev->globalPos().y()) < 50){ return; } //quick check that the window is not smaller than 20 pixels + QRect geom = this->geometry(); + geom.setTop(ev->globalPos().y()); + this->setGeometry(geom); + } +}
\ No newline at end of file diff --git a/desktop-utilities/lumina-terminal/TermWindow.h b/desktop-utilities/lumina-terminal/TermWindow.h new file mode 100644 index 00000000..ae40928f --- /dev/null +++ b/desktop-utilities/lumina-terminal/TermWindow.h @@ -0,0 +1,66 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_UTILITIES_TERMINAL_MAIN_WINDOW_H +#define _LUMINA_DESKTOP_UTILITIES_TERMINAL_MAIN_WINDOW_H + +#include <QWidget> +#include <QPropertyAnimation> +#include <QTabWidget> +#include <QDir> +#include <QShortcut> +#include <QMouseEvent> + +class TermWindow : public QWidget{ + Q_OBJECT +public: + TermWindow(); + ~TermWindow(); + + void cleanup(); //called right before the window is closed + void OpenDirs(QStringList); + + void setCurrentScreen(int num = 0); + void setTopOfScreen(bool ontop); + +public slots: + void ShowWindow(); + void HideWindow(); + void CloseWindow(); + void ReShowWindow(); + +private: + QTabWidget *tabWidget; + QShortcut *hideS, *closeS, *newTabS, *closeTabS; + int screennum; + bool onTop, CLOSING; + QPropertyAnimation *ANIM; + int animRunning; //internal flag for what animation is currently running + + //Calculate the window geometry necessary based on screen/location + void CalculateGeom(); + QString GenerateTabID(); + +private slots: + //Tab Interactions + void New_Tab(); + void Close_Tab(int tab = -1); + void Close_Tab(QString ID); //alternate form of the close routine - based on tab ID + + //Animation finishing + void AnimFinished(); + +protected: + void mouseMoveEvent(QMouseEvent*); + +signals: + void TerminalHidden(); + void TerminalVisible(); + void TerminalClosed(); + void TerminalFinished(); +}; + +#endif diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.cpp b/desktop-utilities/lumina-terminal/TerminalWidget.cpp new file mode 100644 index 00000000..4cfd3849 --- /dev/null +++ b/desktop-utilities/lumina-terminal/TerminalWidget.cpp @@ -0,0 +1,83 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "TerminalWidget.h" + +#include <QProcessEnvironment> +#include <QDebug> +#include <QApplication> + +TerminalWidget::TerminalWidget(QWidget *parent, QString dir) : QTextEdit(parent){ + //Setup the text widget + this->setLineWrapMode(QTextEdit::WidgetWidth); + this->setReadOnly(true); //the key event catch will do the process/widget forwarding + this->setPlainText("WARNING: This utility is still incomplete and does not function properly yet"); + //Create/launch the process + PROC = new QProcess(this); + PROC->setProcessEnvironment(QProcessEnvironment::systemEnvironment()); + PROC->setWorkingDirectory(dir); + PROC->setProcessChannelMode(QProcess::MergedChannels); + //Connect the signals/slots + connect(PROC, SIGNAL(readyReadStandardOutput()), this, SLOT(UpdateText()) ); + connect(PROC, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(ShellClosed()) ); + //Now start the shell + PROC->start( PROC->processEnvironment().value("SHELL","/bin/sh"), QIODevice::ReadWrite); + +} + +TerminalWidget::~TerminalWidget(){ + +} + +void TerminalWidget::aboutToClose(){ + if(PROC->state()!=QProcess::NotRunning){ PROC->close(); } + if(PROC->state()!=QProcess::NotRunning){ PROC->kill(); } + if(PROC->state()!=QProcess::NotRunning){ PROC->terminate(); } +} + +// ================== +// PRIVATE SLOTS +// ================== +void TerminalWidget::UpdateText(){ + while(PROC->canReadLine()){ + QString line = PROC->readLine(); + this->insertPlainText( line ); + } +} + +void TerminalWidget::ShellClosed(){ + emit ProcessClosed(this->whatsThis()); +} + +// ================== +// PROTECTED +// ================== +void TerminalWidget::keyPressEvent(QKeyEvent *ev){ + //The way this works is by printing the keys directly to the text edit widget + // While also keeping an internal "buffer" of the input string so it can all be written to the process at the same time + + QString key = ev->text(); + //Check for special key combinations first + switch(ev->key()){ + case Qt::Key_Enter: + case Qt::Key_Return: + //send the current input buffer to the process + qDebug() << "Write to process:" << inBuffer; + this->insertPlainText("\n"); + PROC->write( QString(inBuffer+"\n").toLocal8Bit() ); + inBuffer.clear(); + qDebug() << "Current Dir:" << PROC->workingDirectory(); + break; + case Qt::Key_Backspace: + inBuffer.chop(1); + break; + default: + this->insertPlainText(key); + inBuffer.append(key); + } + + ev->ignore(); +}
\ No newline at end of file diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.h b/desktop-utilities/lumina-terminal/TerminalWidget.h new file mode 100644 index 00000000..b16d298d --- /dev/null +++ b/desktop-utilities/lumina-terminal/TerminalWidget.h @@ -0,0 +1,36 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_UTILITIES_TERMINAL_PROCESS_WIDGET_H +#define _LUMINA_DESKTOP_UTILITIES_TERMINAL_PROCESS_WIDGET_H + +#include <QTextEdit> +#include <QProcess> +#include <QKeyEvent> + +class TerminalWidget : public QTextEdit{ + Q_OBJECT +public: + TerminalWidget(QWidget *parent =0, QString dir=""); + ~TerminalWidget(); + + void aboutToClose(); + +private: + QProcess *PROC; + QString inBuffer; +private slots: + void UpdateText(); + void ShellClosed(); + +signals: + void ProcessClosed(QString); + +protected: + void keyPressEvent(QKeyEvent *event); +}; + +#endif
\ No newline at end of file diff --git a/desktop-utilities/lumina-terminal/TrayIcon.cpp b/desktop-utilities/lumina-terminal/TrayIcon.cpp new file mode 100644 index 00000000..14ea24b4 --- /dev/null +++ b/desktop-utilities/lumina-terminal/TrayIcon.cpp @@ -0,0 +1,172 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "TrayIcon.h" + +#include <QDir> +#include <QDesktopWidget> + +#include <LuminaUtils.h> + +TrayIcon::TrayIcon() : QSystemTrayIcon(){ + //Create the child widgets here + settings = new QSettings("lumina-desktop","lumina-terminal"); + this->setContextMenu(new QMenu()); + ScreenMenu = new QMenu(); + connect(ScreenMenu, SIGNAL(triggered(QAction*)), this, SLOT(ChangeScreen(QAction*)) ); + TERM = new TermWindow(); + //Load the current settings + TERM->setTopOfScreen(settings->value("TopOfScreen",true).toBool()); + TERM->setCurrentScreen(settings->value("OnScreen",0).toInt()); + connect(TERM, SIGNAL(TerminalHidden()), this, SLOT(TermHidden())); + connect(TERM, SIGNAL(TerminalVisible()), this, SLOT(TermVisible())); + connect(TERM, SIGNAL(TerminalClosed()), this, SLOT(startCleanup())); + connect(TERM, SIGNAL(TerminalFinished()), this, SLOT(stopApplication())); + connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(TrayActivated(QSystemTrayIcon::ActivationReason)) ); +} + +TrayIcon::~TrayIcon(){ + delete TERM; + delete ScreenMenu; +} + +// ============= +// PUBLIC +// ============= +void TrayIcon::parseInputs(QStringList inputs){ + //Note that this is only run on the primary process - otherwise inputs are sent to the slotSingleInstance() below + termVisible = !inputs.contains("-toggle"); //will automatically show the terminal on first run, even if "-toggle" is set + + setupContextMenu(); + updateIcons(); + inputs = adjustInputs(inputs); //will adjust termVisible as necessary + if(inputs.isEmpty()){ inputs << QDir::homePath(); } //always start up with one terminal minimum + TERM->OpenDirs(inputs); + if(termVisible){ QTimer::singleShot(0, TERM, SLOT(ShowWindow())); } +} + +// ================= +// PUBLIC SLOTS +// ================= +void TrayIcon::slotSingleInstance(QStringList inputs){ + //Note that this is only run for a secondary process forwarding its inputs + qDebug() << "Single Instance Event:" << inputs << termVisible; + bool visible = termVisible; + inputs = adjustInputs(inputs); //will adjust termVisible as necessary + if(!inputs.isEmpty()){ TERM->OpenDirs(inputs); } + //Only adjust the window if there was a change in the visibility status + qDebug() << "Set Visible:" << termVisible; + if(!visible && termVisible){ QTimer::singleShot(0, TERM, SLOT(ShowWindow())); } + else if(visible && !termVisible){ QTimer::singleShot(0, TERM, SLOT(HideWindow())); } +} + +void TrayIcon::updateIcons(){ + this->setIcon(LXDG::findIcon("utilities-terminal","")); +} + +// ================ +// PRIVATE +// ================ +QStringList TrayIcon::adjustInputs(QStringList inputs){ + bool hasHide = false; + //Look for the special CLI flags just for the tray icon and trim them out + for(int i=0; i<inputs.length(); i++){ + if(inputs[i]=="-toggle"){ hasHide = termVisible; inputs.removeAt(i); i--; } //toggle the visibility + else if(inputs[i]=="-show"){ hasHide = false; inputs.removeAt(i); i--; } //change the visibility + else if(inputs[i]=="-hide"){ hasHide = true; inputs.removeAt(i); i--; } //change the visibility + else{ + //Must be a directory - convert to an absolute path and check for existance + inputs[i] = LUtils::PathToAbsolute(inputs[i]); + QFileInfo info(inputs[i]); + if(!info.exists()){ + qDebug() << "Directory does not exist: " << inputs[i]; + inputs.removeAt(i); + i--; + }else if(!info.isDir()){ + //Must be some kind of file, open the parent directory + inputs[i] = inputs[i].section("/",0,-2); + } + } + } + termVisible = !hasHide; + return inputs; +} + +// ================ +// PRIVATE SLOTS +// ================ +void TrayIcon::startCleanup(){ + TERM->cleanup(); +} + +void TrayIcon::stopApplication(){ + QApplication::exit(0); +} + +void TrayIcon::ChangeTopBottom(bool ontop){ + TERM->setTopOfScreen(ontop); + settings->setValue("TopOfScreen",ontop); //save for later +} + +void TrayIcon::ChangeScreen(QAction *act){ + int screen = act->whatsThis().toInt(); + TERM->setCurrentScreen(screen); + settings->setValue("OnScreen",screen); + updateScreenMenu(); +} + +void TrayIcon::setupContextMenu(){ + this->contextMenu()->clear(); + this->contextMenu()->addAction(LXDG::findIcon("edit-select",""), tr("Trigger Terminal"), this, SLOT(ToggleVisibility()) ); + this->contextMenu()->addSeparator(); + QAction * act = this->contextMenu()->addAction(tr("Top of Screen"), this, SLOT(ChangeTopBottom(bool)) ); + act->setCheckable(true); + act->setChecked(settings->value("TopOfScreen",true).toBool() ); + this->contextMenu()->addMenu(ScreenMenu); + this->contextMenu()->addSeparator(); + this->contextMenu()->addAction(LXDG::findIcon("application-exit",""), tr("Close Terminal"), this, SLOT(stopApplication()) ); + updateScreenMenu(); +} + +void TrayIcon::updateScreenMenu(){ + ScreenMenu->clear(); + QDesktopWidget *desk = QApplication::desktop(); + int cscreen = settings->value("OnScreen",0).toInt(); + if(cscreen>=desk->screenCount()){ cscreen = desk->primaryScreen(); } + ScreenMenu->setTitle(tr("Move To Monitor")); + for(int i=0; i<desk->screenCount(); i++){ + if(i!=cscreen){ + QAction *act = new QAction( QString(tr("Monitor %1")).arg(QString::number(i+1)),ScreenMenu); + act->setWhatsThis(QString::number(i)); + ScreenMenu->addAction(act); + } + } + ScreenMenu->setVisible(!ScreenMenu->isEmpty()); +} + +void TrayIcon::TrayActivated(QSystemTrayIcon::ActivationReason reason){ + switch(reason){ + case QSystemTrayIcon::Context: + this->contextMenu()->popup(this->geometry().center()); + break; + default: + ToggleVisibility(); + } +} + +//Slots for the window visibility +void TrayIcon::ToggleVisibility(){ + if(termVisible){ QTimer::singleShot(0, TERM, SLOT(HideWindow())); } + else{ QTimer::singleShot(0, TERM, SLOT(ShowWindow())); } +} + +void TrayIcon::TermHidden(){ + termVisible = false; +} + +void TrayIcon::TermVisible(){ + termVisible = true; +}
\ No newline at end of file diff --git a/desktop-utilities/lumina-terminal/TrayIcon.h b/desktop-utilities/lumina-terminal/TrayIcon.h new file mode 100644 index 00000000..961aaa90 --- /dev/null +++ b/desktop-utilities/lumina-terminal/TrayIcon.h @@ -0,0 +1,59 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_UTILITIES_TERMINAL_TRAY_ICON_H +#define _LUMINA_DESKTOP_UTILITIES_TERMINAL_TRAY_ICON_H +// QT Includes +#include <QApplication> +#include <QSystemTrayIcon> +#include <QMenu> +#include <QTimer> +#include <QSettings> + +#include <LuminaXDG.h> + +#include "TermWindow.h" + +class TrayIcon : public QSystemTrayIcon { + Q_OBJECT + +public: + TrayIcon(); + ~TrayIcon(); + + //First run + void parseInputs(QStringList); //Note that this is only run on the primary process - otherwise it gets sent to the singleInstance slot below + +public slots: + void slotSingleInstance(QStringList inputs = QStringList()); + void updateIcons(); + +private: + bool termVisible; + TermWindow *TERM; + QMenu *ScreenMenu; + QStringList adjustInputs(QStringList); + QSettings *settings; +private slots: + //Action Buttons + void startCleanup(); + void stopApplication(); + void ChangeTopBottom(bool ontop); + void ChangeScreen(QAction*); + + //Tray Updates + void setupContextMenu(); + void updateScreenMenu(); + void TrayActivated(QSystemTrayIcon::ActivationReason); + + //Slots for the window visibility + void ToggleVisibility(); + void TermHidden(); + void TermVisible(); + +}; + +#endif diff --git a/desktop-utilities/lumina-terminal/lumina-terminal.pro b/desktop-utilities/lumina-terminal/lumina-terminal.pro new file mode 100644 index 00000000..82a5f8a4 --- /dev/null +++ b/desktop-utilities/lumina-terminal/lumina-terminal.pro @@ -0,0 +1,110 @@ +TEMPLATE = app +LANGUAGE = C++ +QT += core gui widgets network +CONFIG += qt warn_on release + +isEmpty(PREFIX) { + PREFIX = /usr/local +} +TARGET = lumina-terminal +target.path = $$DESTDIR$$PREFIX/bin + +isEmpty(LIBPREFIX) { + LIBPREFIX = $$PREFIX/lib +} + +HEADERS += TrayIcon.h \ + TermWindow.h \ + TerminalWidget.h + +SOURCES += main.cpp \ + TrayIcon.cpp \ + TermWindow.cpp \ + TerminalWidget.cpp + + +INCLUDEPATH += ../../libLumina $$PREFIX/include +LIBS += -L../../libLumina -L$$LIBPREFIX -lLuminaUtils + +isEmpty(QT5LIBDIR) { + QT5LIBDIR = $$PREFIX/lib/qt5 +} + +LRELEASE = $$QT5LIBDIR/bin/lrelease + + +QMAKE_LIBDIR = ../libLumina +DEPENDPATH += ../../libLumina + +TRANSLATIONS = i18n/lumina-terminal_af.ts \ + i18n/lumina-terminal_ar.ts \ + i18n/lumina-terminal_az.ts \ + i18n/lumina-terminal_bg.ts \ + i18n/lumina-terminal_bn.ts \ + i18n/lumina-terminal_bs.ts \ + i18n/lumina-terminal_ca.ts \ + i18n/lumina-terminal_cs.ts \ + i18n/lumina-terminal_cy.ts \ + i18n/lumina-terminal_da.ts \ + i18n/lumina-terminal_de.ts \ + i18n/lumina-terminal_el.ts \ + i18n/lumina-terminal_en_GB.ts \ + i18n/lumina-terminal_en_ZA.ts \ + i18n/lumina-terminal_es.ts \ + i18n/lumina-terminal_et.ts \ + i18n/lumina-terminal_eu.ts \ + i18n/lumina-terminal_fa.ts \ + i18n/lumina-terminal_fi.ts \ + i18n/lumina-terminal_fr.ts \ + i18n/lumina-terminal_fr_CA.ts \ + i18n/lumina-terminal_gl.ts \ + i18n/lumina-terminal_he.ts \ + i18n/lumina-terminal_hi.ts \ + i18n/lumina-terminal_hr.ts \ + i18n/lumina-terminal_hu.ts \ + i18n/lumina-terminal_id.ts \ + i18n/lumina-terminal_is.ts \ + i18n/lumina-terminal_it.ts \ + i18n/lumina-terminal_ja.ts \ + i18n/lumina-terminal_ka.ts \ + i18n/lumina-terminal_ko.ts \ + i18n/lumina-terminal_lt.ts \ + i18n/lumina-terminal_lv.ts \ + i18n/lumina-terminal_mk.ts \ + i18n/lumina-terminal_mn.ts \ + i18n/lumina-terminal_ms.ts \ + i18n/lumina-terminal_mt.ts \ + i18n/lumina-terminal_nb.ts \ + i18n/lumina-terminal_nl.ts \ + i18n/lumina-terminal_pa.ts \ + i18n/lumina-terminal_pl.ts \ + i18n/lumina-terminal_pt.ts \ + i18n/lumina-terminal_pt_BR.ts \ + i18n/lumina-terminal_ro.ts \ + i18n/lumina-terminal_ru.ts \ + i18n/lumina-terminal_sk.ts \ + i18n/lumina-terminal_sl.ts \ + i18n/lumina-terminal_sr.ts \ + i18n/lumina-terminal_sv.ts \ + i18n/lumina-terminal_sw.ts \ + i18n/lumina-terminal_ta.ts \ + i18n/lumina-terminal_tg.ts \ + i18n/lumina-terminal_th.ts \ + i18n/lumina-terminal_tr.ts \ + i18n/lumina-terminal_uk.ts \ + i18n/lumina-terminal_uz.ts \ + i18n/lumina-terminal_vi.ts \ + i18n/lumina-terminal_zh_CN.ts \ + i18n/lumina-terminal_zh_HK.ts \ + i18n/lumina-terminal_zh_TW.ts \ + i18n/lumina-terminal_zu.ts + +dotrans.path=$$PREFIX/share/Lumina-DE/i18n/ +dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$$PREFIX/share/Lumina-DE/i18n/ + +INSTALLS += target dotrans + +NO_I18N{ + INSTALLS -= dotrans +} + diff --git a/desktop-utilities/lumina-terminal/main.cpp b/desktop-utilities/lumina-terminal/main.cpp new file mode 100644 index 00000000..c117b8fb --- /dev/null +++ b/desktop-utilities/lumina-terminal/main.cpp @@ -0,0 +1,47 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2015, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include <QSystemTrayIcon> +#include <QDebug> + +#include <LuminaSingleApplication.h> +#include <LuminaThemes.h> + +#include <unistd.h> + +#include "TrayIcon.h" +int main(int argc, char *argv[]) { + LTHEME::LoadCustomEnvSettings(); + LSingleApplication a(argc, argv, "lumina-terminal"); + if( !a.isPrimaryProcess() ){ return 0; } //poked the current process instead + + //First make sure a system tray is available + qDebug() << "Checking for system tray"; + bool ready = false; + for(int i=0; i<60 && !ready; i++){ + ready = QSystemTrayIcon::isSystemTrayAvailable(); + if(!ready){ + //Pause for 5 seconds + sleep(5); //don't worry about stopping event handling - nothing running yet + } + } + if(!ready){ + qDebug() << "Could not find any available system tray after 5 minutes: exiting...."; + return 1; + } + + //Now go ahead and setup the app + LuminaThemeEngine theme(&a); + QApplication::setQuitOnLastWindowClosed(false); + + //Now start the tray icon + TrayIcon tray; + QObject::connect(&a, SIGNAL(InputsAvailable(QStringList)), &tray, SLOT(slotSingleInstance(QStringList)) ); + QObject::connect(&theme, SIGNAL(updateIcons()), &tray, SLOT(updateIcons()) ); + tray.parseInputs(a.inputlist); + tray.show(); + return a.exec(); +} |