aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-qt5/core/lumina-desktop-unified/defaults/desktop/panels.conf21
-rw-r--r--src-qt5/core/lumina-desktop-unified/defaults/desktop/screensaver.conf1
-rw-r--r--src-qt5/core/lumina-desktop-unified/lumina-desktop.pro3
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp30
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h1
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp65
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.h26
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp4
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri6
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp75
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h17
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp40
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h1
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp36
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h7
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp32
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h9
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml231
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml8
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml10
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml14
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp31
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h31
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-events/Window-mgmt.cpp (renamed from src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp)50
-rw-r--r--src-qt5/core/lumina-desktop-unified/src-events/events.pri3
-rw-r--r--src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp21
-rw-r--r--src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp5
-rw-r--r--src-qt5/desktop-utils/lumina-notify/README.md41
-rw-r--r--src-qt5/desktop-utils/lumina-notify/lumina-notify.pro19
-rw-r--r--src-qt5/desktop-utils/lumina-notify/main.cpp25
-rw-r--r--src-qt5/src-cpp/framework-OSInterface-template.cpp97
-rw-r--r--src-qt5/src-cpp/framework-OSInterface.h66
-rw-r--r--src-qt5/src-cpp/framework-OSInterface_private.cpp241
33 files changed, 887 insertions, 380 deletions
diff --git a/src-qt5/core/lumina-desktop-unified/defaults/desktop/panels.conf b/src-qt5/core/lumina-desktop-unified/defaults/desktop/panels.conf
new file mode 100644
index 00000000..07cf4635
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/defaults/desktop/panels.conf
@@ -0,0 +1,21 @@
+[General]
+
+[templates]
+windows/anchor="bottom"
+windows/align="center"
+windows/length_percent=100
+windows/plugins=""
+windows/background="rgba(0,0,0,120)"
+
+[default]
+active_ids="initial"
+
+[session]
+
+[initial]
+anchor="bottom"
+align="center"
+length_percent=100
+width_percent=2.1
+plugins=""
+background="rgba(0,0,0,120)"
diff --git a/src-qt5/core/lumina-desktop-unified/defaults/desktop/screensaver.conf b/src-qt5/core/lumina-desktop-unified/defaults/desktop/screensaver.conf
index b4bfec59..98e6f20a 100644
--- a/src-qt5/core/lumina-desktop-unified/defaults/desktop/screensaver.conf
+++ b/src-qt5/core/lumina-desktop-unified/defaults/desktop/screensaver.conf
@@ -1,3 +1,2 @@
[General]
default_plugin="random"
-plugin_VGA-0="random"
diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro
index 07781770..96d84a71 100644
--- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro
+++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro
@@ -10,7 +10,7 @@ lessThan(QT_MINOR_VERSION, 7){
}
QT *= core gui network widgets x11extras multimedia multimediawidgets concurrent svg quick qml
-
+CONFIG += c++11
TARGET = lumina-desktop-unified
target.path = $${L_BINDIR}
@@ -24,6 +24,7 @@ include(../libLumina/ExternalProcess.pri)
include(../libLumina/XDGMime.pri)
include(../../src-cpp/plugins-base.pri)
+include(../../src-cpp/framework-OSInterface.pri)
#include all the main individual source groups
include(src-events/events.pri)
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp
index eefe6d7e..bfded781 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.cpp
@@ -84,10 +84,6 @@ void DesktopManager::updateWallpaper(QString screen_id, int wkspace){
RootDesktopObject::instance()->ChangeWallpaper(screen_id,QUrl::fromLocalFile(wpaper).toString() );
}
-void DesktopManager::updatePanels(QString panel_id){
-
-}
-
void DesktopManager::updatePlugins(QString plugin_id){
}
@@ -103,13 +99,13 @@ void DesktopManager::settingsChanged(DesktopSettings::File type){
case DesktopSettings::Desktop:
QTimer::singleShot(0, this, SLOT(updateDesktopSettings()) );
case DesktopSettings::Panels:
- QTimer::singleShot(0, this, SLOT(updatePanelSettings()) );
+ QTimer::singleShot(1, this, SLOT(updatePanelSettings()) );
case DesktopSettings::Plugins:
- QTimer::singleShot(0, this, SLOT(updatePluginSettings()) );
+ QTimer::singleShot(2, this, SLOT(updatePluginSettings()) );
case DesktopSettings::ContextMenu:
- QTimer::singleShot(0, this, SLOT(updateMenuSettings()) );
+ QTimer::singleShot(3, this, SLOT(updateMenuSettings()) );
case DesktopSettings::Animation:
- QTimer::singleShot(0, this, SLOT(updateAnimationSettings()) );
+ QTimer::singleShot(4, this, SLOT(updateAnimationSettings()) );
default:
break;
//Do nothing - not a settings change we care about here
@@ -148,14 +144,28 @@ void DesktopManager::syncTrayWindowList(){
// === PRIVATE SLOTS ===
void DesktopManager::updateDesktopSettings(){
qDebug() << "Update Desktop Settings...";
- QList<QScreen*> scrns= QApplication::screens();
+ QList<QScreen*> scrns = QGuiApplication::screens();
int wkspace = Lumina::NWS->currentWorkspace();
for(int i=0; i<scrns.length(); i++){ updateWallpaper(scrns[i]->name(), wkspace); }
}
void DesktopManager::updatePanelSettings(){
-
+ QList<QScreen*> scrns = QGuiApplication::screens();
+ int primary = QApplication::desktop()->primaryScreen();
+ for(int i=0; i<scrns.length(); i++){
+ ScreenObject *sObj = RootDesktopObject::instance()->screen(scrns[i]->name());
+ if(sObj == 0){ continue; } //screen is not managed directly - skip it
+ QStringList ids = DesktopSettings::instance()->value(DesktopSettings::Panels, scrns[i]->name().replace("-","_")+"/active_ids", QStringList()).toStringList();
+ if(ids.isEmpty() && (scrns.length()==1 || i==primary)){
+ //Also look for the "default" panel id's for the primary/default screen
+ ids = DesktopSettings::instance()->value(DesktopSettings::Panels, "default/active_ids", QStringList()).toStringList();
+ }
+ sObj->setPanels(ids);
+ }
+ //Now do the global-session panels
+ QStringList ids = DesktopSettings::instance()->value(DesktopSettings::Panels, "session/active_ids", QStringList()).toStringList();
+ RootDesktopObject::instance()->setPanels(ids); //put the new ones in place
}
void DesktopManager::updatePluginSettings(){
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h
index d4a0cf79..da42e477 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/DesktopManager.h
@@ -23,7 +23,6 @@ public:
private:
void updateWallpaper(QString screen_id, int wkspace);
- void updatePanels(QString panel_id);
void updatePlugins(QString plugin_id);
public slots:
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp
new file mode 100644
index 00000000..a74d2585
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.cpp
@@ -0,0 +1,65 @@
+//===========================================
+// 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 "QMLImageProvider.h"
+
+QMLImageProvider::QMLImageProvider(QQmlImageProviderBase::ImageType type) : QQuickImageProvider(type, 0){
+
+}
+
+QMLImageProvider::~QMLImageProvider(){
+
+}
+
+/*QMLImageProvider* QMLImageProvider::instance(){
+ static QMLImageProvider *_prov = 0;
+ if(_prov==0){ _prov = new QMLImageProvider(); }
+ return _prov;
+}*/
+
+QImage QMLImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize){
+ NativeWindowObject *win = Lumina::NWS->findWindow( id.section(":",1,1).toInt(), false);
+ if(win==0){ win = Lumina::NWS->findTrayWindow(id.section(":",1,1).toInt()); }
+
+ if(!id.startsWith("image:")){ qDebug() << "Request Image:" << id << win << requestedSize; }
+
+ QImage img(requestedSize,QImage::Format_RGB32);
+ if(win==0){ img.fill("black"); } //invalid window ID (should never happen)
+ else if(id.startsWith("image:")){ img = Lumina::NWS->GetWindowImage(win); }
+ else if(id.startsWith("icon:")){
+ QIcon ico = win->property(NativeWindowObject::Icon).value<QIcon>();
+ QList<QSize> sizes = ico.availableSizes();
+ QSize sz(0,0);
+ //Just grab the largest size currently available
+ for(int i=0; i<sizes.length(); i++){
+ if(sz.width()<sizes[i].width() && sz.height()<sizes[i].height()){ sz = sizes[i]; }
+ }
+ qDebug() << "Icon Sizes:" <<sizes;
+ img = ico.pixmap(sz).toImage();
+ }
+ //qDebug() << "Got Window Image:" << img.size();
+ if(img.size().isNull()){
+ if(requestedSize.isValid()){ img = QImage(requestedSize,QImage::Format_RGB32); }
+ else{ img = QImage(QSize(64,64), QImage::Format_RGB32); }
+ img.fill("black");
+ }
+ //qDebug() << "Final Window Image:" << img.size();
+ if(size!=0){
+ size->setHeight(img.height());
+ size->setWidth( img.width() );
+ }
+ if(requestedSize.isValid() && !requestedSize.isNull() && img.size()!=requestedSize){
+ img = img.scaled(requestedSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ }
+ return img;
+}
+
+QPixmap QMLImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize){
+ qDebug() << "Pixmap Requested:" << id;
+ QImage img = requestImage(id, size, requestedSize);
+ return QPixmap::fromImage(img);
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.h b/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.h
new file mode 100644
index 00000000..8719176e
--- /dev/null
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/QMLImageProvider.h
@@ -0,0 +1,26 @@
+//===========================================
+// 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_QML_IMAGE_PROVIDER_H
+#define _LUMINA_DESKTOP_QML_IMAGE_PROVIDER_H
+
+#include <QQuickImageProvider>
+#include <QImage>
+#include <QPixmap>
+#include <QSize>
+
+class QMLImageProvider : public QQuickImageProvider{
+public:
+ QMLImageProvider(QQmlImageProviderBase::ImageType);
+ ~QMLImageProvider();
+
+ //static QMLImageProvider* instance();
+
+ virtual QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
+ virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);
+};
+
+#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp
index 0cfa4e6b..2ceff4a0 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp
@@ -5,6 +5,8 @@
// See the LICENSE file for full details
//===========================================
#include "RootWindow.h"
+#include "QMLImageProvider.h"
+#include <QQmlImageProviderBase>
RootWindow::RootWindow() : QObject(){
root_win = QWindow::fromWinId( QX11Info::appRootWindow() ); //
@@ -16,6 +18,8 @@ RootWindow::RootWindow() : QObject(){
//Now setup the QQuickView
root_view->setResizeMode(QQuickView::SizeRootObjectToView);
root_view->engine()->rootContext()->setContextProperty("RootObject", root_obj);
+ root_view->engine()->addImageProvider("native_window", new QMLImageProvider(QQmlImageProviderBase::Image) );
+ //root_view->engine()->addImageProvider("native_window_icon", new QMLImageProvider(QQmlImageProviderBase::Pixmap) );
RootDesktopObject::RegisterType(); //make sure object classes are registered with the QML subsystems
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri
index f4a6882d..ee5ada62 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri
@@ -1,10 +1,12 @@
QT *= gui widgets qml quick
SOURCES *= $${PWD}/RootWindow.cpp \
- $${PWD}/Desktopmanager.cpp
+ $${PWD}/Desktopmanager.cpp \
+ $${PWD}/QMLImageProvider.cpp
HEADERS *= $${PWD}/RootWindow.h \
- $${PWD}/DesktopManager.h
+ $${PWD}/DesktopManager.h \
+ $${PWD}/QMLImageProvider.h
#update the includepath so we can just #include as needed without paths
INCLUDEPATH *= $${PWD}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp
index e9049cdd..9bb78dd0 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.cpp
@@ -21,7 +21,11 @@ void NativeWindowObject::RegisterType(){
NativeWindowObject::NativeWindowObject(WId id) : QObject(){
winid = id;
frameid = 0;
- dmgID = 0;
+ dmgID = dmg = 0;
+ geomTimer = new QTimer(this);
+ geomTimer->setSingleShot(true);
+ geomTimer->setInterval(50); //1/20 second
+ connect(geomTimer, SIGNAL(timeout()), this, SLOT(sendNewGeom()) );
}
NativeWindowObject::~NativeWindowObject(){
@@ -62,17 +66,9 @@ void NativeWindowObject::setProperty(NativeWindowObject::Property prop, QVariant
if(prop == NativeWindowObject::RelatedWindows){ relatedTo = val.value< QList<WId> >(); }
else if(prop == NativeWindowObject::None || (!force && hash.value(prop)==val)){ return; }
else if(prop == NativeWindowObject::WinImage){
- //special case - QImage is passed in, but QString is passed out (needed for QML)
- QByteArray ba;
- QBuffer buffer(&ba);
- buffer.open(QIODevice::WriteOnly);
- val.value<QImage>().save(&buffer, "PNG");
- QString img("data:image/png;base64,");
- img.append(QString::fromLatin1(ba.toBase64().data()));
- qDebug() << "Image Data Header:" << img.section(",",0,0);
- hash.insert(prop, img); //save the string instead
- }
- else{ hash.insert(prop, val); }
+ //special case - This should never be actually set in the property hash
+ // it is loaded dynamically by the QMLImageProvider instead (prevent flickering/caching image)
+ } else{ hash.insert(prop, val); }
emitSinglePropChanged(prop);
emit PropertiesChanged(QList<NativeWindowObject::Property>() << prop, QList<QVariant>() << val);
}
@@ -83,15 +79,8 @@ void NativeWindowObject::setProperties(QList<NativeWindowObject::Property> props
if(props[i] == NativeWindowObject::None || (!force && (hash.value(props[i]) == vals[i])) ){
props.removeAt(i); vals.removeAt(i); i--; continue; //Invalid property or identical value
}else if(props[i] == NativeWindowObject::WinImage){
- //special case - QImage is passed in, but QString is passed out (needed for QML)
- QByteArray ba;
- QBuffer buffer(&ba);
- buffer.open(QIODevice::WriteOnly);
- vals[i].value<QImage>().save(&buffer, "PNG");
- QString img("data:image/png;base64,");
- img.append(QString::fromLatin1(ba.toBase64().data()));
- qDebug() << "Image Data Header:" << img.section(",",0,0);
- hash.insert(props[i], img); //save the string instead
+ //special case - This should never be actually set in the property hash
+ // it is loaded dynamically by the QMLImageProvider instead (prevent flickering/caching image)
}else{
hash.insert(props[i], vals[i]);
}
@@ -141,9 +130,16 @@ QRect NativeWindowObject::geometry(){
return geom;
}
+void NativeWindowObject::setGeometryNow(QRect geom){
+ updateGeometry(geom.x(), geom.y(), geom.width(), geom.height(), true);
+}
+
// QML ACCESS FUNCTIONS (shortcuts for particular properties in a format QML can use)
QString NativeWindowObject::winImage(){
- return this->property(NativeWindowObject::WinImage).toString();
+ //Need to alternate something on the end to ensure that QML knows to fetch the new image (non-cached only)
+ if(dmg==0){ dmg = 1; }
+ else{ dmg = 0; }
+ return "image://native_window/image:"+QString::number(winid)+":"+QString::number(dmg);
}
QString NativeWindowObject::name(){
@@ -161,8 +157,11 @@ QString NativeWindowObject::shortTitle(){
return tmp;
}
-QIcon NativeWindowObject::icon(){
- return this->property(NativeWindowObject::Name).value<QIcon>();
+QString NativeWindowObject::icon(){
+ if(icodmg==0){ icodmg=1; }
+ else{ icodmg = 0; }
+ qDebug() << "Window Icon:" << icodmg << this->property(NativeWindowObject::Icon).value<QIcon>().availableSizes();
+ return "image://native_window/icon:"+QString::number(winid)+":"+QString::number(icodmg);
}
//QML Button states
@@ -257,6 +256,23 @@ QRect NativeWindowObject::imageGeometry(){
return geom;
}
+void NativeWindowObject::updateGeometry(int x, int y, int width, int height, bool now){
+ // Full frame+window geometry - go ahead and pull it apart and only update the interior window geom
+ QList<int> fgeom = this->property(NativeWindowObject::FrameExtents).value<QList<int> >();
+ if(fgeom.isEmpty()){ fgeom << 0<<0<<0<<0; } //just in case (left/right/top/bottom)
+ QPoint pos(x+fgeom[0], y+fgeom[2]);
+ QSize sz(width-fgeom[0]-fgeom[1], height-fgeom[2]-fgeom[3]);
+ if(!now){
+ newgeom = QRect(pos, sz);
+ //qDebug() << "Update Geometry:" << fgeom << QRect(x,y,width,height) << pos << sz;
+ //requestProperties(QList<NativeWindowObject::Property>() << NativeWindowObject::GlobalPos << NativeWindowObject::Size, QList<QVariant>() << pos << sz);
+ if(!geomTimer->isActive()){ geomTimer->start(); }
+ }else{
+ requestProperties(QList<NativeWindowObject::Property>() << NativeWindowObject::GlobalPos << NativeWindowObject::Size , QList<QVariant>() << pos << sz );
+ setProperties(QList<NativeWindowObject::Property>() << NativeWindowObject::GlobalPos << NativeWindowObject::Size , QList<QVariant>() << pos << sz );
+ }
+}
+
// ==== PUBLIC SLOTS ===
void NativeWindowObject::toggleVisibility(){
setProperty(NativeWindowObject::Visible, !property(NativeWindowObject::Visible).toBool() );
@@ -281,7 +297,9 @@ void NativeWindowObject::emitSinglePropChanged(NativeWindowObject::Property prop
case NativeWindowObject::Name:
emit nameChanged(); break;
case NativeWindowObject::Title:
- emit titleChanged(); break;
+ emit titleChanged();
+ if(this->property(NativeWindowObject::ShortTitle).toString().isEmpty()){ emit shortTitleChanged(); }
+ break;
case NativeWindowObject::ShortTitle:
emit shortTitleChanged(); break;
case NativeWindowObject::Icon:
@@ -297,3 +315,10 @@ void NativeWindowObject::emitSinglePropChanged(NativeWindowObject::Property prop
break; //do nothing otherwise
}
}
+
+void NativeWindowObject::sendNewGeom(){
+ QList<NativeWindowObject::Property> props; props << NativeWindowObject::GlobalPos << NativeWindowObject::Size;
+ QList<QVariant> vals; vals << newgeom.topLeft() << newgeom.size();
+ requestProperties(props, vals);
+ setProperties(props,vals);
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h
index e4f9d41e..6a63813e 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/NativeWindowObject.h
@@ -21,7 +21,7 @@ class NativeWindowObject : public QObject{
Q_PROPERTY( QString name READ name NOTIFY nameChanged)
Q_PROPERTY( QString title READ title NOTIFY titleChanged)
Q_PROPERTY( QString shortTitle READ shortTitle NOTIFY shortTitleChanged)
- Q_PROPERTY( QIcon icon READ icon NOTIFY iconChanged)
+ Q_PROPERTY( QString icon READ icon NOTIFY iconChanged)
Q_PROPERTY( bool sticky READ isSticky NOTIFY stickyChanged)
//Button/Titlebar visibility
Q_PROPERTY( bool showCloseButton READ showCloseButton NOTIFY winTypeChanged)
@@ -38,6 +38,8 @@ public:
enum State{ S_MODAL, S_STICKY, S_MAX_VERT, S_MAX_HORZ, S_SHADED, S_SKIP_TASKBAR, S_SKIP_PAGER, S_HIDDEN, S_FULLSCREEN, S_ABOVE, S_BELOW, S_ATTENTION };
enum Type{T_DESKTOP, T_DOCK, T_TOOLBAR, T_MENU, T_UTILITY, T_SPLASH, T_DIALOG, T_DROPDOWN_MENU, T_POPUP_MENU, T_TOOLTIP, T_NOTIFICATION, T_COMBO, T_DND, T_NORMAL };
enum Action {A_MOVE, A_RESIZE, A_MINIMIZE, A_SHADE, A_STICK, A_MAX_VERT, A_MAX_HORZ, A_FULLSCREEN, A_CHANGE_DESKTOP, A_CLOSE, A_ABOVE, A_BELOW};
+ enum Location { TOP_LEFT, TOP, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT, LEFT };
+ Q_ENUM(Location)
enum Property{ /*QVariant Type*/
None=0, /*null*/
@@ -90,13 +92,14 @@ public:
void requestProperties(QList<NativeWindowObject::Property>, QList<QVariant>, bool force = false);
Q_INVOKABLE QRect geometry(); //this returns the "full" geometry of the window (window + frame)
+ void setGeometryNow(QRect geom);
// QML ACCESS FUNCTIONS (shortcuts for particular properties in a format QML can use)
Q_INVOKABLE QString winImage();
Q_INVOKABLE QString name();
Q_INVOKABLE QString title();
Q_INVOKABLE QString shortTitle();
- Q_INVOKABLE QIcon icon();
+ Q_INVOKABLE QString icon();
//QML Button states
Q_INVOKABLE bool showCloseButton();
Q_INVOKABLE bool showMaxButton();
@@ -111,6 +114,7 @@ public:
//QML Geometry reporting
Q_INVOKABLE QRect frameGeometry();
Q_INVOKABLE QRect imageGeometry();
+ Q_INVOKABLE void updateGeometry(int x, int y, int width, int height, bool now = false); //For QML to change the current window position
public slots:
Q_INVOKABLE void toggleVisibility();
@@ -123,17 +127,22 @@ private:
//QWindow *WIN;
WId winid, frameid;
QList<WId> relatedTo;
- unsigned int dmgID;
+ unsigned int dmgID, dmg, icodmg;
+ //Collation/Delay for window resize events
+ QTimer *geomTimer;
+ QRect newgeom;
void emitSinglePropChanged(NativeWindowObject::Property);
+private slots:
+ void sendNewGeom();
+
signals:
//General Notifications
void PropertiesChanged(QList<NativeWindowObject::Property>, QList<QVariant>);
void RequestPropertiesChange(WId, QList<NativeWindowObject::Property>, QList<QVariant>);
void WindowClosed(WId);
void WindowNotResponding(WId); //will be sent out if a window does not respond to a ping request
- void VisualChanged();
//Action Requests (not automatically emitted - typically used to ask the WM to do something)
//Note: "WId" should be the NativeWindowObject id()
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp
index 471da58f..9054f528 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.cpp
@@ -5,6 +5,8 @@
// See the LICENSE file for full details
//===========================================
#include "PanelObject.h"
+#include <global-objects.h>
+
#include <QQmlEngine>
#include <QDebug>
@@ -42,3 +44,41 @@ void PanelObject::setGeometry( QRect newgeom ){
emit geomChanged();
}
}
+
+void PanelObject::syncWithSettings(QRect parent_geom){
+ //Read off all the settings
+ //qDebug() << "Sync Panel Settings:" << panel_id << parent_geom;
+ QString anchor = DesktopSettings::instance()->value(DesktopSettings::Panels, panel_id+"/anchor", "bottom").toString().toLower();
+ QString align = DesktopSettings::instance()->value(DesktopSettings::Panels, panel_id+"/align", "center").toString().toLower();
+ double length = DesktopSettings::instance()->value(DesktopSettings::Panels, panel_id+"/length_percent", 100).toDouble()/100.0;
+ double width = DesktopSettings::instance()->value(DesktopSettings::Panels, panel_id+"/width_font_percent", 2.1).toDouble();
+ width = qRound(width * QApplication::fontMetrics().height() );
+ this->setBackground( DesktopSettings::instance()->value(DesktopSettings::Panels, panel_id+"/background", "rgba(0,0,0,120)").toString() );
+ // qDebug() << "Update Panel:" << panel_id << anchor+"/"+align << length << width;
+ //Now calculate the geometry of the panel
+ QRect newgeom;
+ //Figure out the size of the panel
+ if(anchor=="top" || anchor=="bottom"){ newgeom.setWidth( parent_geom.width()*length ); newgeom.setHeight(width); }
+ else{ newgeom.setWidth(width); newgeom.setHeight(parent_geom.height()*length); }
+ //qDebug() << " - Size:" << newgeom;
+ //Now figure out the location of the panel
+ if(align=="left" || align=="top"){
+ if(anchor=="top" || anchor=="left"){ newgeom.moveTopLeft(QPoint(0,0)); }
+ else if(anchor=="right"){ newgeom.moveTopRight(QPoint(parent_geom.width(), 0)); }
+ else{ newgeom.moveBottomLeft(QPoint(0, parent_geom.height()) ); } //bottom by default
+
+ }else if(align=="right" || align=="bottom"){
+ if(anchor=="top"){ newgeom.moveTopRight(QPoint(parent_geom.width(),0)); }
+ else if(anchor=="left"){ newgeom.moveBottomLeft(QPoint(0, parent_geom.height())); }
+ else if(anchor=="right"){ newgeom.moveBottomRight(QPoint(parent_geom.width(), parent_geom.height())); }
+ else{ newgeom.moveBottomRight(QPoint(parent_geom.width(), parent_geom.height()) ); }
+
+ }else{ //center
+ if(anchor=="top"){ newgeom.moveTopLeft(QPoint( (parent_geom.width()-newgeom.width())/2,0)); }
+ else if(anchor=="left"){ newgeom.moveTopLeft(QPoint(0, (parent_geom.height()-newgeom.height())/2 )); }
+ else if(anchor=="right"){ newgeom.moveTopRight(QPoint(parent_geom.width(), (parent_geom.height()-newgeom.height())/2 )); }
+ else{ newgeom.moveBottomLeft(QPoint( (parent_geom.width()-newgeom.width())/2, parent_geom.height()) ); }
+ }
+ //qDebug() << " - Calculated Geometry:" << newgeom;
+ this->setGeometry(newgeom); //Note: This is in parent-relative coordinates (not global)
+}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h
index a788fa07..8cf59dee 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/PanelObject.h
@@ -40,6 +40,7 @@ public:
public slots:
void setBackground(QString fileOrColor);
void setGeometry(QRect newgeom);
+ void syncWithSettings(QRect parent_geom);
signals:
void backgroundChanged();
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp
index 39dc30c1..07d4e463 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp
@@ -14,6 +14,7 @@
// === PUBLIC ===
RootDesktopObject::RootDesktopObject(QObject *parent) : QObject(parent){
updateScreens(); //make sure the internal list is updated right away
+ connect(this, SIGNAL(changePanels(QStringList)), this, SLOT(setPanels(QStringList)) );
}
RootDesktopObject::~RootDesktopObject(){
@@ -87,6 +88,41 @@ void RootDesktopObject::setPanels(QList<PanelObject*> list){
emit panelsChanged();
}
+void RootDesktopObject::setPanels(QStringList ids){
+ //Make this thread-safe for object creation
+ if(this->thread() != QThread::currentThread()){
+ //use internal signal/slot combo to change threads
+ this->emit changePanels(ids);
+ return;
+ }
+
+ //Get the current bounding rectangle for the session
+ QRect total;
+ for(int i=0; i<s_objects.length(); i++){
+ total = total.united(s_objects[i]->geometry());
+ }
+ //First update/remove any current panel objects
+ bool change = false;
+ for(int i=0; i<panel_objects.length(); i++){
+ if(ids.contains(panel_objects[i]->name()) ){
+ ids.removeAll(panel_objects[i]->name()); //already handled
+ panel_objects[i]->syncWithSettings(total);
+ }else{
+ panel_objects.takeAt(i)->deleteLater();
+ i--;
+ change = true; //list changed
+ }
+ }
+ //Now create any new panel objects as needed
+ for(int i=0; i<ids.length(); i++){
+ PanelObject *tmp = new PanelObject(ids[i], this);
+ tmp->syncWithSettings(total);
+ panel_objects << tmp;
+ change = true; //list changed
+ }
+ if(change){ emit panelsChanged(); }
+}
+
void RootDesktopObject::setWindows(QList<NativeWindowObject*> list){
window_objects = list;
emit windowsChanged();
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h
index a4236596..ad0e538b 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h
@@ -10,6 +10,7 @@
#define _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H
#include <global-includes.h>
#include <ScreenObject.h>
+#include <QThread>
class RootDesktopObject : public QObject{
Q_OBJECT
@@ -53,6 +54,9 @@ public slots:
QString CurrentWallpaper(QString screen);
void setPanels(QList<PanelObject*> list);
+ void setPanels(QStringList ids);
+ QList<PanelObject*> panelObjectList(){ return panel_objects; }
+
void setWindows(QList<NativeWindowObject*> list);
private slots:
@@ -66,5 +70,8 @@ signals:
void mouseMoved();
void lockScreen();
void launchApplication(QString);
+
+ //Internal signals for thread-safety
+ void changePanels(QStringList);
};
#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp
index 1b22c450..c754906d 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp
@@ -10,6 +10,7 @@
ScreenObject::ScreenObject(QScreen *scrn, QObject *parent) : QObject(parent){
bg_screen = scrn;
+ connect(this, SIGNAL(changePanels(QStringList)), this, SLOT(setPanels(QStringList)) );
}
void ScreenObject::RegisterType(){
@@ -40,6 +41,37 @@ void ScreenObject::setPanels(QList<PanelObject*> list){
emit panelsChanged();
}
+void ScreenObject::setPanels(QStringList ids){
+ //Make this thread-safe for object creation
+ if(this->thread() != QThread::currentThread()){
+ //use internal signal/slot combo to change threads
+ this->emit changePanels(ids);
+ return;
+ }
+
+ //First update/remove any current panel objects
+ bool change = false;
+ for(int i=0; i<panel_objects.length(); i++){
+ if(ids.contains(panel_objects[i]->name()) ){
+ ids.removeAll(panel_objects[i]->name()); //already handled
+ panel_objects[i]->syncWithSettings(bg_screen->geometry());
+ }else{
+ panel_objects.takeAt(i)->deleteLater();
+ i--;
+ change = true; //list changed
+ }
+ }
+ //Now create any new panel objects as needed
+ for(int i=0; i<ids.length(); i++){
+ PanelObject *tmp = new PanelObject(ids[i], this);
+ tmp->syncWithSettings(bg_screen->geometry());
+ panel_objects << tmp;
+ change = true; //list changed
+ }
+ if(change){ emit panelsChanged(); }
+}
+
+
//QML Read Functions
QStringList ScreenObject::panels(){
//qDebug() << "Request Panels:" << panel_objects.length();
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h
index 1afff6d2..250c9403 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h
@@ -11,6 +11,7 @@
#include <QObject>
#include <QString>
#include <QScreen>
+#include <QThread>
#include "PanelObject.h"
@@ -42,16 +43,24 @@ public:
Q_INVOKABLE int height();
Q_INVOKABLE QStringList panels();
Q_INVOKABLE PanelObject* panel(QString id);
+ Q_INVOKABLE QRect geometry(){ return bg_screen->geometry(); }
void setPanels(QList<PanelObject*> list);
+ QList<PanelObject*> panelObjectList(){ return panel_objects; }
+
public slots:
+ void setPanels(QStringList ids);
void setBackground(QString fileOrColor);
signals:
void backgroundChanged();
void geomChanged();
void panelsChanged();
+
+ //Internal signals for thread-safety
+ void changePanels(QStringList);
+
};
#endif
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml
index 92263689..2150e37c 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/NativeWindow.qml
@@ -5,6 +5,7 @@ import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3
import Lumina.Backend.NativeWindowObject 2.0
+import Lumina.Backend.RootDesktopObject 2.0
Rectangle {
property NativeWindowObject object
@@ -14,94 +15,119 @@ Rectangle {
id: windowFrame
border.width: 5
- //border.color: palette.window
- color: palette.window
+ border.color: palette.highlight
+ radius: 5
+ color: "transparent" //palette.window
x: object.frameGeometry.x
y: object.frameGeometry.y
width: object.frameGeometry.width
height: object.frameGeometry.height
+ onXChanged: {
+ windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height)
+ }
+ onYChanged: {
+ windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height)
+ }
+
MouseArea {
id: resizeArea
anchors.fill: parent
- property int positionX: 0
- property int positionY: 0
- property int newWidth: 0
- property int newHeight: 0
-
- onPositionChanged: {
- var globalP = windowFrame.mapToGlobal(mouse.x, mouse.y)
- if(positionY < windowFrame.y + 15 ) {
- /*if(positionX < windowFrame.x + 15) {
- console.log("Top Left");
- //Top Left
- newWidth = windowFrame.width + (windowFrame.x - mouse.x)
- newHeight = windowFrame.height + (windowFrame.y - mouse.y)
- windowFrame.x = mouse.x
- windowFrame.y = mouse.y
- }else if(positionX > windowFrame.x + windowFrame.width - 15) {
- console.log("Top Right");
- //Top Right
- newX = positionX - mouse.x
- newY = positionY - mouse.y
- newWidth = windowFrame.width - (positionX - mouse.x)
- newHeight = windowFrame.height + (windowFrame.y - mouse.y)
- windowFrame.y = mouse.y
- }else{*/
- //Top
- windowFrame.height -= 1
- windowFrame.y = globalP.y
- // }
+ drag.target: undefined
+ property int resizeDirection: NativeWindowObject.TOP_LEFT
+ property int positionX: -1
+ property int positionY: -1
+
+ onPressed: {
+ //NOTE: This is only triggered for resize events
+ var globalP = windowFrame.mapToItem(rootCanvas, mouse.x, mouse.y)
+ positionX = globalP.x
+ positionY = globalP.y
+ if(positionY <= windowFrame.y + 10 ) {
+ if(positionX <= windowFrame.x + 10)
+ resizeDirection = NativeWindowObject.TOP_LEFT
+ else if(positionX >= windowFrame.x + windowFrame.width - 10)
+ resizeDirection = NativeWindowObject.TOP_RIGHT
+ else
+ resizeDirection = NativeWindowObject.TOP
+ }else if(positionY >= windowFrame.y + windowFrame.height - 10) {
+ if(positionX <= windowFrame.x + 10)
+ resizeDirection = NativeWindowObject.BOTTOM_LEFT
+ else if(positionX >= windowFrame.x + windowFrame.width - 10)
+ resizeDirection = NativeWindowObject.BOTTOM_RIGHT
+ else
+ resizeDirection = NativeWindowObject.BOTTOM
+ }else if(positionX <= windowFrame.x + 10) {
+ resizeDirection = NativeWindowObject.LEFT
+ }else if(positionX >= windowFrame.x + windowFrame.width - 10) {
+ resizeDirection = NativeWindowObject.RIGHT
}
-/*else if(mouse.x < windowFrame.x + 15) {
- if(mouse.y > windowFrame.y + windowFrame.height - 15) {
- //Bottom Left
- newX = positionX - mouse.x
- newWidth = windowFrame.width - newX
- newHeight = windowFrame.height - newY
- }else{
- //Left
- }
- }else if(mouse.y > windowFrame.y + windowFrame.height - 15) {
- if(mouse.x > windowFrame.x + windowFrame.width - 15) {
- //Bottom Right
- }else{
- //Bottom
- }
- }else if(mouse.x > windowFrame.x + windowFrame.width - 15) {
- //Right
- } else {
- console.log("Cursor error");
- }*/
+ //console.log("Initial X: ", positionX, "Initial Y: ", positionY);
+ //console.log("Initial X Frame: ", windowFrame.x, "Initial Y Frame: ", windowFrame.y);
}
- }
-
- MouseArea {
- id: dragArea
- anchors.fill: titleBar
- drag.target: windowFrame
- drag.axis: Drag.XAndYAxis
- onClicked: { console.log("dragArea"); }
- //released: { function(); }
- }
- states: [
- State {
- when: resizeArea.drag.held
- PropertyChanges { target: Window; color:"red" }
- },
- State {
- when: dragArea.drag.held
- AnchorChanges { target: windowFrame; anchors.verticalCenter: undefined; anchors.horizontalCenter: undefined }
+ onReleased: {
+ positionX = -1
+ positionY = -1
+ //windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height)
}
- ]
-
+ onPositionChanged: {
+ //NOTE: This is only triggered for resize events
+ if(positionX != -1 && positionY != -1) {
+ var globalP = windowFrame.mapToItem(rootCanvas, mouse.x, mouse.y)
+ /*console.log("Global P: ", globalP);
+ console.log("Position X: ", positionX, "Position Y: ", positionY)
+ console.log("Old Position : ", windowFrame.x, " , ", windowFrame.y)
+ console.log(resizeDirection);*/
+ if(resizeDirection == NativeWindowObject.TOP_LEFT) {
+ windowFrame.height -= globalP.y - positionY
+ windowFrame.width -= globalP.x - positionX
+ windowFrame.y = globalP.y
+ windowFrame.x = globalP.x
+ }else if(resizeDirection == NativeWindowObject.TOP_RIGHT) {
+ //console.log("TOP RIGHT Old Height: ", windowFrame.height, "Old Width: ", windowFrame.width)
+ windowFrame.height -= globalP.y - positionY
+ windowFrame.width += globalP.x - positionX
+ //console.log("New Height: ", windowFrame.height, "New Width: ", windowFrame.width)
+ windowFrame.y = globalP.y
+ //console.log("New Position : ", windowFrame.x, " , ", windowFrame.y)
+ }else if(resizeDirection == NativeWindowObject.TOP) {
+ windowFrame.height -= globalP.y - positionY
+ windowFrame.y = globalP.y
+ } else if(resizeDirection == NativeWindowObject.RIGHT) {
+ windowFrame.width += globalP.x - positionX
+ } else if(resizeDirection == NativeWindowObject.BOTTOM_RIGHT) {
+ windowFrame.height += globalP.y - positionY
+ windowFrame.width += globalP.x - positionX
+ } else if(resizeDirection == NativeWindowObject.BOTTOM) {
+ windowFrame.height += globalP.y - positionY
+ } else if(resizeDirection == NativeWindowObject.BOTTOM_LEFT) {
+ windowFrame.width -= globalP.x - positionX
+ windowFrame.height += globalP.y - positionY
+ windowFrame.x = globalP.x
+ } else if(resizeDirection == NativeWindowObject.LEFT) {
+ windowFrame.width -= globalP.x - positionX
+ windowFrame.x = globalP.x
+ }
+ //Set a miniumum width and height as 80x50
+ if(windowFrame.width < 80) {
+ windowFrame.width = 80
+ }
+ if(windowFrame.height < 50) {
+ windowFrame.height = 50
+ }
+ positionY = globalP.y
+ positionX = globalP.x
+ }
+ windowFrame.object.updateGeometry(windowFrame.x, windowFrame.y, windowFrame.width, windowFrame.height)
+ }
+ }
Rectangle {
id: titleBar
- border.width: 2
- color: palette.window
+ border.width: 0
+ color: palette.window
height: 25
anchors.top: windowFrame.top
anchors.right: windowFrame.right
@@ -109,48 +135,51 @@ Rectangle {
anchors.margins: windowFrame.border.width
width: parent.width
- RowLayout {
- anchors.fill: titleBar
- spacing: 0
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+ drag.target: windowFrame
+ drag.axis: Drag.XAndYAxis
+ //acceptedButtons: Qt.RightButton
+ //onClicked: contextMenu.open()
+ //released: { function(); }
+ }
- Button {
- id: otherButton
- anchors.left: parent.left
- Layout.fillHeight: true
- iconSource: windowFrame.object.icon
- }
+ ToolButton {
+ id: otherButton
+ anchors.left: parent.left
+ height: parent.height
+ iconSource: windowFrame.object.icon
+ }
- Text {
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
- color: palette.windowText
- text: windowFrame.object.shortTitle
-
- MouseArea {
- acceptedButtons: Qt.RightButton
- anchors.fill: parent
- //onClicked: contextMenu.open()
- }
- }
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ color: palette.windowText
+ text: windowFrame.object.shortTitle
+ fontSizeMode: Text.Fit
+ }
- Button {
+ RowLayout {
+ spacing: 0
+ anchors.right: parent.right
+ height: parent.height
+
+ ToolButton {
id: minButton
Layout.fillHeight: true
iconName: "window-minimize"
onClicked: { windowFrame.object.toggleVisibility() }
}
- Button {
+ ToolButton {
id: maxButton
Layout.fillHeight: true
iconName: "window-maximize"
//onClicked: { windowFrame.object.toggleMaximize() }
}
- Button {
+ ToolButton {
id: closeButton
Layout.fillHeight: true
iconName: "document-close"
@@ -161,6 +190,7 @@ Rectangle {
Image {
id: frameContents
+ cache: false
source: windowFrame.object.winImage
anchors.top: titleBar.bottom
anchors.bottom: parent.bottom
@@ -173,11 +203,10 @@ Rectangle {
height: parent.height
MouseArea {
- width: parent.width;
+ width: parent.width
height: parent.height
anchors.fill: frameContents
onClicked: { console.log(parent.mapToGlobal(mouse.x, mouse.y)); }
-
}
}
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml
index 846b5b55..556da5ec 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Panel.qml
@@ -10,15 +10,13 @@ import QtQuick.Controls 1
import Lumina.Backend.PanelObject 2.0
-AnimatedImage {
+Rectangle {
//C++ backend object
- property string screen_id
+ property string panel_id
property PanelObject object
//Normal geometries/placements
- asynchronous: true
- clip: true
- source: object.background
+ color: object.background
x: object.x
y: object.y
width: object.width
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml
index 9122ce5b..f48f7751 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml
@@ -66,4 +66,14 @@ Rectangle {
z: 100+index
}
}
+
+ //Setup the Panels
+ Repeater{
+ model: RootObject.panels
+ QML.Panel{
+ panel_id: modelData
+ object: RootObject.panel(panel_id)
+ z: 10100+index
+ }
+ }
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml
index 3b83653a..82e7c89d 100644
--- a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml
+++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/Screen.qml
@@ -9,6 +9,9 @@ import QtQuick.Window 2.2
import QtQuick.Controls 1
import Lumina.Backend.ScreenObject 2.0
+import Lumina.Backend.PanelObject 2.0
+
+import "." as QML
AnimatedImage {
//C++ backend object
@@ -23,4 +26,15 @@ AnimatedImage {
y: object.y
width: object.width
height: object.height
+
+ //Setup the Panels
+ Repeater{
+ model: object.panels
+ QML.Panel{
+ panel_id: modelData
+ object: parent.object.panel(panel_id)
+ z: 10000+index
+ }
+ }
+
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp
index 30a6a47d..063c1337 100644
--- a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.cpp
@@ -10,7 +10,7 @@
#include "NativeWindowSystem.h"
#include <global-objects.h>
-#define DISABLE_COMPOSITING 1
+#define DISABLE_COMPOSITING 0
//XCB Library includes
#include <xcb/xcb.h>
@@ -523,7 +523,7 @@ void NativeWindowSystem::ChangeWindowProperties(NativeWindowObject* win, QList<
}
if(props.contains(NativeWindowObject::Size) || props.contains(NativeWindowObject::GlobalPos) ){
- /*xcb_configure_window_value_list_t valList;
+ xcb_configure_window_value_list_t valList;
//valList.x = 0; //Note that this is the relative position - should always be 0,0 relative to the embed widget
//valList.y = 0;
QSize sz = win->property(NativeWindowObject::Size).toSize();
@@ -543,7 +543,7 @@ void NativeWindowSystem::ChangeWindowProperties(NativeWindowObject* win, QList<
uint16_t mask = 0;
mask = mask | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
//qDebug() << "Configure window Geometry:" << sz;
- xcb_configure_window_aux(QX11Info::connection(), win->id(), mask, &valList);*/
+ xcb_configure_window_aux(QX11Info::connection(), win->id(), mask, &valList);
}
if(props.contains(NativeWindowObject::Name)){
@@ -628,9 +628,9 @@ void NativeWindowSystem::SetupNewWindow(NativeWindowObject *win){
registerClientEvents(win->id());
}
-void NativeWindowSystem::UpdateWindowImage(NativeWindowObject* win){
+QImage NativeWindowSystem::GetWindowImage(NativeWindowObject* win){
QImage img;
- qDebug() << "Update Window Image:" << win->name();
+ //qDebug() << "Update Window Image:" << win->name();
QRect geom(QPoint(0,0), win->property(NativeWindowObject::Size).toSize());
if(DISABLE_COMPOSITING){
QList<QScreen*> screens = static_cast<QApplication*>( QApplication::instance() )->screens();
@@ -641,12 +641,12 @@ void NativeWindowSystem::UpdateWindowImage(NativeWindowObject* win){
//Pull the XCB pixmap out of the compositing layer
xcb_pixmap_t pix = xcb_generate_id(QX11Info::connection());
xcb_composite_name_window_pixmap(QX11Info::connection(), win->id(), pix);
- if(pix==0){ qDebug() << "Got blank pixmap!"; return; }
+ if(pix==0){ return QImage(); }
//Convert this pixmap into a QImage
//xcb_image_t *ximg = xcb_image_get(QX11Info::connection(), pix, 0, 0, this->width(), this->height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP);
xcb_image_t *ximg = xcb_image_get(QX11Info::connection(), pix, geom.x(), geom.y(), geom.width(), geom.height(), ~0, XCB_IMAGE_FORMAT_Z_PIXMAP);
- if(ximg == 0){ qDebug() << "Got blank image!"; return; }
+ if(ximg == 0){ return QImage(); }
QImage tmp(ximg->data, ximg->width, ximg->height, ximg->stride, QImage::Format_ARGB32_Premultiplied);
img = tmp.copy(); //detach this image from the XCB data structures before we clean them up, otherwise the QImage will try to clean it up a second time on window close and crash
xcb_image_destroy(ximg);
@@ -654,7 +654,8 @@ void NativeWindowSystem::UpdateWindowImage(NativeWindowObject* win){
//Cleanup the XCB data structures
xcb_free_pixmap(QX11Info::connection(), pix);
}
- win->setProperty(NativeWindowObject::WinImage, QVariant::fromValue<QImage>(img) );
+ return img;
+ //win->setProperty(NativeWindowObject::WinImage, QVariant::fromValue<QImage>(img) );
}
// === PUBLIC SLOTS ===
@@ -783,15 +784,19 @@ void NativeWindowSystem::NewWindowDetected(WId id){
registerClientEvents(win->id());
NWindows << win;
UpdateWindowProperties(win, NativeWindowObject::allProperties());
- win->setProperty(NativeWindowObject::FrameExtents, QVariant::fromValue<QList<int> >( QList<int>() << 5 << 5 << 30 << 5 ));
+ if(win->showWindowFrame()){
+ win->setProperty(NativeWindowObject::FrameExtents, QVariant::fromValue<QList<int> >( QList<int>() << 5 << 5 << 30 << 5 ));
+ }
qDebug() << "New Window [& associated ID's]:" << win->id() << win->property(NativeWindowObject::Name).toString();
SetupNewWindow(win);
+ CheckWindowPosition(id, true); //first time placement
//Now setup the connections with this window
connect(win, SIGNAL(RequestClose(WId)), this, SLOT(RequestClose(WId)) );
connect(win, SIGNAL(RequestKill(WId)), this, SLOT(RequestKill(WId)) );
connect(win, SIGNAL(RequestPing(WId)), this, SLOT(RequestPing(WId)) );
connect(win, SIGNAL(RequestReparent(WId, WId, QPoint)), this, SLOT(RequestReparent(WId, WId, QPoint)) );
connect(win, SIGNAL(RequestPropertiesChange(WId, QList<NativeWindowObject::Property>, QList<QVariant>)), this, SLOT(RequestPropertiesChange(WId, QList<NativeWindowObject::Property>, QList<QVariant>)) );
+ connect(win, SIGNAL(VerifyNewGeometry(WId)), this, SLOT(CheckWindowPosition(WId)) );
xcb_map_window(QX11Info::connection(), win->id());
emit NewWindowAvailable(win);
}
@@ -942,12 +947,12 @@ void NativeWindowSystem::NewMouseRelease(int buttoncode, WId win){
}
void NativeWindowSystem::CheckDamageID(WId win){
- qDebug() << "Got Damage Event:" << win;
+ //qDebug() << "Got Damage Event:" << win;
for(int i=0; i<NWindows.length(); i++){
if(NWindows[i]->damageId() == win || NWindows[i]->id() == win || NWindows[i]->frameId()==win){
- qDebug() << " - Found window";
- UpdateWindowImage(NWindows[i]);
- NWindows[i]->emit VisualChanged();
+ //qDebug() << " - Found window";
+ //UpdateWindowImage(NWindows[i]);
+ NWindows[i]->emit winImageChanged();
return;
}
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h
index c50babff..5810fc36 100644
--- a/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h
+++ b/src-qt5/core/lumina-desktop-unified/src-events/NativeWindowSystem.h
@@ -23,11 +23,6 @@ private:
QList<NativeWindowObject*> NWindows;
QList<NativeWindowObject*> TWindows;
- //Simplifications to find an already-created window object
- NativeWindowObject* findWindow(WId id, bool checkRelated = true);
-
- NativeWindowObject* findTrayWindow(WId id);
-
//Now define a simple private_objects class so that each implementation
// has a storage container for defining/placing private objects as needed
class p_objects;
@@ -51,14 +46,6 @@ private:
}
}
- // Since some properties may be easier to update in bulk
- // let the native system interaction do them in whatever logical groups are best
- void UpdateWindowProperties(NativeWindowObject* win, QList< NativeWindowObject::Property > props);
- void ChangeWindowProperties(NativeWindowObject* win, QList< NativeWindowObject::Property > props, QList<QVariant> vals);
-
- void SetupNewWindow(NativeWindowObject *win);
- void UpdateWindowImage(NativeWindowObject *win);
-
//Generic private variables
bool screenLocked;
@@ -66,6 +53,18 @@ public:
//enum Property{ None, CurrentWorkspace, Workspaces, VirtualRoots, WorkAreas };
enum MouseButton{NoButton, LeftButton, RightButton, MidButton, BackButton, ForwardButton, TaskButton, WheelUp, WheelDown, WheelLeft, WheelRight};
+ //Simplifications to find an already-created window object
+ NativeWindowObject* findWindow(WId id, bool checkRelated = true);
+
+ NativeWindowObject* findTrayWindow(WId id);
+ // Since some properties may be easier to update in bulk
+ // let the native system interaction do them in whatever logical groups are best
+ void UpdateWindowProperties(NativeWindowObject* win, QList< NativeWindowObject::Property > props);
+ void ChangeWindowProperties(NativeWindowObject* win, QList< NativeWindowObject::Property > props, QList<QVariant> vals);
+
+ void SetupNewWindow(NativeWindowObject *win);
+ QImage GetWindowImage(NativeWindowObject *win);
+
NativeWindowSystem();
~NativeWindowSystem();
@@ -130,6 +129,12 @@ private slots:
void RequestPing(WId);
void RequestReparent(WId, WId, QPoint); //client, parent, relative origin point in parent
+ //Window-mgmt functions (see Window-mgmt.cpp for details)
+ void ArrangeWindows(WId primary, QString type);
+ void TileWindows(WId primary, QString type);
+ void CheckWindowPosition(WId id, bool newwindow = false);
+ void arrangeWindows(NativeWindowObject *primary, QString type, bool primaryonly = false);
+
signals:
void NewWindowAvailable(NativeWindowObject*);
void WindowClosed();
diff --git a/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp b/src-qt5/core/lumina-desktop-unified/src-events/Window-mgmt.cpp
index 24ea639b..0b45c208 100644
--- a/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp
+++ b/src-qt5/core/lumina-desktop-unified/src-events/Window-mgmt.cpp
@@ -4,28 +4,38 @@
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
-#include "RootWindow.h"
+#include "NativeWindowSystem.h"
+inline QScreen* screenUnderMouse(){
+ QPoint pos = QCursor::pos();
+ QList<QScreen*> scrns = QGuiApplication::screens();
+ for(int i=0; i<scrns.length(); i++){
+ if(scrns[i]->geometry().contains(pos)){ return scrns[i]; }
+ }
+ return 0;
+}
+
//Primary/private function
-void RootWindow::arrangeWindows(RootSubWindow *primary, QString type, bool primaryonly){
+void NativeWindowSystem::arrangeWindows(NativeWindowObject *primary, QString type, bool primaryonly){
if(type.isEmpty()){ type = "center"; }
if(primary==0){
//Get the currently active window and treat that as the primary
- for(int i=0; i<WINDOWS.length(); i++){
- if(WINDOWS[i]->nativeWindow()->property(NativeWindow::Active).toBool()){ primary = WINDOWS[i]; }
+ for(int i=0; i<NWindows.length(); i++){
+ if(NWindows[i]->property(NativeWindowObject::Active).toBool()){ primary = NWindows[i]; }
}
- if(primary==0 && !WINDOWS.isEmpty()){ primary = WINDOWS[0]; } //just use the first one in the list
+ if(primary==0 && !NWindows.isEmpty()){ primary = NWindows[0]; } //just use the first one in the list
}
//Now get the current screen that the mouse cursor is over (and valid area)
QScreen *screen = screenUnderMouse();
+ if(screen==0){ return; } //should never happen (theoretically)
QRect desktopArea = screen->availableGeometry();
//qDebug() << "Arrange Windows:" << primary->geometry() << type << primaryonly << desktopArea;
//Now start filtering out all the windows that need to be ignored
- int wkspace = primary->nativeWindow()->property(NativeWindow::Workspace).toInt();
- QList<RootSubWindow*> winlist = WINDOWS;
+ int wkspace = primary->property(NativeWindowObject::Workspace).toInt();
+ QList<NativeWindowObject*> winlist = NWindows;
for(int i=0; i<winlist.length(); i++){
- if(winlist[i]->nativeWindow()->property(NativeWindow::Workspace).toInt()!=wkspace
- || !winlist[i]->nativeWindow()->property(NativeWindow::Visible).toBool()
+ if(winlist[i]->property(NativeWindowObject::Workspace).toInt()!=wkspace
+ || !winlist[i]->property(NativeWindowObject::Visible).toBool()
|| desktopArea.intersected(winlist[i]->geometry()).isNull() ){
//window is outside of the desired area or invisible - ignore it
winlist.removeAt(i);
@@ -45,17 +55,17 @@ void RootWindow::arrangeWindows(RootSubWindow *primary, QString type, bool prima
//Now apply the proper placement routine
if(type=="center"){
QPoint ct = desktopArea.center();
- winlist[i]->setGeometry( ct.x()-(geom.width()/2), ct.y()-(geom.height()/2), geom.width(), geom.height());
+ winlist[i]->setGeometryNow( QRect( ct.x()-(geom.width()/2), ct.y()-(geom.height()/2), geom.width(), geom.height()) );
}else if(type=="snap"){
}else if(type=="single_max"){
- winlist[i]->setGeometry( desktopArea.x(), desktopArea.y(), desktopArea.width(), desktopArea.height());
+ winlist[i]->setGeometryNow( QRect( desktopArea.x(), desktopArea.y(), desktopArea.width(), desktopArea.height()) );
}else if(type=="under-mouse"){
QPoint ct = QCursor::pos();
geom = QRect(ct.x()-(geom.width()/2), ct.y()-(geom.height()/2), geom.width(), geom.height() );
//Now verify that the top of the window is still contained within the desktop area
if(geom.y() < desktopArea.y() ){ geom.moveTop(desktopArea.y()); }
- winlist[i]->setGeometry(geom);
+ winlist[i]->setGeometryNow(geom);
}
//qDebug() << " - New Geometry:" << winlist[i]->geometry();
@@ -65,31 +75,31 @@ void RootWindow::arrangeWindows(RootSubWindow *primary, QString type, bool prima
// ================
// Public slots for starting the arrangement routine(s) above
// ================
-void RootWindow::ArrangeWindows(WId primary, QString type){
- RootSubWindow* win = windowForId(primary);
+void NativeWindowSystem::ArrangeWindows(WId primary, QString type){
+ NativeWindowObject* win = findWindow(primary);
if(type.isEmpty()){ type = "center"; } //grab the default arrangement format
arrangeWindows(win, type);
}
-void RootWindow::TileWindows(WId primary, QString type){
- RootSubWindow* win = windowForId(primary);
+void NativeWindowSystem::TileWindows(WId primary, QString type){
+ NativeWindowObject* win = findWindow(primary);
if(type.isEmpty()){ type = "single_max"; } //grab the default arrangement format for tiling
arrangeWindows(win, type);
}
-void RootWindow::CheckWindowPosition(WId id, bool newwindow){
+void NativeWindowSystem::CheckWindowPosition(WId id, bool newwindow){
//used after a "drop" to validate/snap/re-arrange window(s) as needed
// if "newwindow" is true, then this is the first-placement routine for a window before it initially appears
- RootSubWindow* win = windowForId(id);
+ NativeWindowObject* win = findWindow(id);
if(win==0){ return; } //invalid window
- QRect geom = win->nativeWindow()->geometry();
+ QRect geom = win->geometry();
bool changed = false;
//Make sure it is on the screen (quick check)
if(geom.x() < 0){ changed = true; geom.moveLeft(0); }
if(geom.y() < 0){ changed = true; geom.moveTop(0); }
if(geom.width() < 20){ changed = true; geom.setWidth(100); }
if(geom.height() < 20){ changed = true; geom.setHeight(100); }
- if(changed){ win->setGeometry(geom); }
+ if(changed){ win->setGeometryNow(geom); }
//Now run it through the window arrangement routine
arrangeWindows(win, newwindow ?"center" : "snap", true);
}
diff --git a/src-qt5/core/lumina-desktop-unified/src-events/events.pri b/src-qt5/core/lumina-desktop-unified/src-events/events.pri
index 3f89fdf2..3f586e8b 100644
--- a/src-qt5/core/lumina-desktop-unified/src-events/events.pri
+++ b/src-qt5/core/lumina-desktop-unified/src-events/events.pri
@@ -5,7 +5,8 @@ LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damag
SOURCES *= $${PWD}/LShortcutEvents.cpp \
$${PWD}/NativeEventFilter.cpp \
$${PWD}/NativeKeyToQt.cpp \
- $${PWD}/NativeWindowSystem.cpp
+ $${PWD}/NativeWindowSystem.cpp \
+ $${PWD}/Window-mgmt.cpp
HEADERS *= $${PWD}/LShortcutEvents.h \
diff --git a/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp b/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp
index 69ea5faa..1870eefb 100644
--- a/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp
+++ b/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp
@@ -78,19 +78,20 @@ void LBattery::updateBattery(bool force){
break;
}
}
- if(icon<iconOld && icon==0){
- //Play some audio warning chime when
- bool playaudio = sessionsettings->value("PlayBatteryLowAudio",true).toBool();
- if( playaudio ){ QString sfile = LSession::handle()->sessionSettings()->value("audiofiles/batterylow", LOS::LuminaShare()+"low-battery.ogg").toString();
+ if(icon<iconOld && icon==0){
+ //Play some audio warning chime when
+ bool playaudio = sessionsettings->value("PlayBatteryLowAudio",true).toBool();
+ if( playaudio ){
+ QString sfile = LSession::handle()->sessionSettings()->value("audiofiles/batterylow", LOS::LuminaShare()+"low-battery.ogg").toString();
LSession::handle()->playAudioFile(sfile);
- }
+ }
+ }
- if(icon==0){ label->setStyleSheet("QLabel{ background: red;}"); }
- else if(icon==14 && charge>98){ label->setStyleSheet("QLabel{ background: green;}"); }
- else{ label->setStyleSheet("QLabel{ background: transparent;}"); }
- iconOld = icon;
+ if(icon==0){ label->setStyleSheet("QLabel{ background: red;}"); }
+ else if(icon==14 && charge>98){ label->setStyleSheet("QLabel{ background: green;}"); }
+ else{ label->setStyleSheet("QLabel{ background: transparent;}"); }
+ iconOld = icon;
- }
//Now update the display
QString tt;
//Make sure the tooltip can be properly translated as necessary (Ken Moore 5/9/14)
diff --git a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp
index 91e233d0..714cfe45 100644
--- a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp
+++ b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp
@@ -114,7 +114,10 @@ void Backend::startAdd(QStringList paths, bool absolutePaths){
paths[i] = paths[i].section(parent,1,-1);
if(paths[i].startsWith("/")){ paths[i].remove(0,1); }
}
- args << "-C" << parent; }
+ args << "-C" << parent;
+ }else{
+ args << "-C" << "/";
+ }
args << paths;
if(QFile::exists(filepath)){ //append to existing
args.replaceInStrings(filepath, tmpfilepath);
diff --git a/src-qt5/desktop-utils/lumina-notify/README.md b/src-qt5/desktop-utils/lumina-notify/README.md
deleted file mode 100644
index 4772a743..00000000
--- a/src-qt5/desktop-utils/lumina-notify/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-### lumina-notify
-
-This is a simple application for launching QDialogs from shell.
-
-Use:
-
-lumina-notify arg1 arg2 arg3 arg4
-
-* arg1 = Message Text
-* arg2 = Button Text (Accept Role)
-* arg3 = Button Text (Reject Role)
-* arg4 = Window Title
-
-For multiple word arguments encapsulate them with "s
-
-***
-Example usage in shell script
-
-~~~~
-#!/bin/csh
-set a=`./lumina-notify "Did Jar Jar do anything wrong?" Yes No "Question"`
-if ($a == 1) then
-set b=`./lumina-notify "Are you sure?" Yes No "Are you Sure?"`
-if ($b == 1) then
-./lumina-notify "Please stop being a hater." Ok Ok "Haters gunna hate"
-else
-set c=`./lumina-notify "Thank you for changing your mind" OK OK "You're Awesome"`
-endif
-else
-./lumina-notify "High Five for Darth Jar Jar" Sure OK "Respect"
-endif`
-~~~~
-
-***
-
-### Library Dependencies
-
-1. Qt 5.0+ (specific modules listed below)
- * core
- * gui
- * widgets
diff --git a/src-qt5/desktop-utils/lumina-notify/lumina-notify.pro b/src-qt5/desktop-utils/lumina-notify/lumina-notify.pro
deleted file mode 100644
index 7aa09583..00000000
--- a/src-qt5/desktop-utils/lumina-notify/lumina-notify.pro
+++ /dev/null
@@ -1,19 +0,0 @@
-#-------------------------------------------------
-# Created by q5sys
-# Released under MIT License 2017-03-08
-#-------------------------------------------------
-include($${PWD}/../../OS-detect.pri)
-
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-TARGET = lumina-notify
-target.path = $${L_BINDIR}
-TEMPLATE = app
-
-DEFINES += QT_DEPRECATED_WARNINGS
-
-SOURCES += main.cpp
-
-INSTALLS += target desktop
diff --git a/src-qt5/desktop-utils/lumina-notify/main.cpp b/src-qt5/desktop-utils/lumina-notify/main.cpp
deleted file mode 100644
index 23f30b95..00000000
--- a/src-qt5/desktop-utils/lumina-notify/main.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//-------------------------------------------------
-// Created by q5sys (JT)
-// Released under MIT License 2017-03-08
-// A Simple GUI Dialog Program
-//-------------------------------------------------
-
-#include <QApplication>
-#include <QMessageBox>
-#include <QDebug>
-#include <QTextStream>
-
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
- a.setAttribute(Qt::AA_UseHighDpiPixmaps);
- int answer;
- QMessageBox *messageBox = new QMessageBox;
- messageBox->setText(argv[1]);
- QPushButton *pushButtonOk = messageBox->addButton(argv[2], QMessageBox::AcceptRole);
- QPushButton *pushButtonNo = messageBox->addButton(argv[3], QMessageBox::RejectRole);
- messageBox->QDialog::setWindowTitle(argv[4]);
- messageBox->show();
- if(messageBox->exec() == QMessageBox::AcceptRole){ answer = 0; QTextStream cout(stdout); cout << answer;}
- else { answer = 1; QTextStream cout(stdout); cout << answer;}
-}
diff --git a/src-qt5/src-cpp/framework-OSInterface-template.cpp b/src-qt5/src-cpp/framework-OSInterface-template.cpp
index 972e02e0..7921511f 100644
--- a/src-qt5/src-cpp/framework-OSInterface-template.cpp
+++ b/src-qt5/src-cpp/framework-OSInterface-template.cpp
@@ -5,23 +5,6 @@
// See the LICENSE file for full details
//===========================================
#include <framework-OSInterface.h>
-#include <QNetworkConfiguration>
-#include <QNetworkInterface>
-
-//Start/stop interface watchers/notifications
-void OSInterface::start(){
- setupMediaWatcher(); //will create/connect the filesystem watcher automatically
- setupNetworkManager();
-}
-
-void OSInterface::stop(){
- if(isRunning()){
- watcher->deleteLater();
- watcher = 0;
- }
-}
-
-bool OSInterface::isRunning(){ return (watcher!=0); } //status of the object - whether it has been started yet
// = Battery =
bool OSInterface::batteryAvailable(){ return false; }
@@ -30,39 +13,27 @@ bool OSInterface::batteryCharging(){ return false; }
double OSInterface::batterySecondsLeft(){ return -1; }
// = Volume =
-bool OSInterface::volumeAvailable(){ return false; }
+bool OSInterface::volumeSupported(){ return false; }
int OSInterface::volume(){ return -1; }
void OSInterface::setVolume(int){}
// = Network Information =
-bool OSInterface::networkAvailable(){
- if(INFO.contains("netaccess/available")){ return INFO.value("netaccess/available").toBool(); }
- return false;
-}
-
-QString OSInterface::networkType(){
- if(INFO.contains("netaccess/type")){ return INFO.value("netaccess/type").toString(); } //"wifi", "wired", or "cell"
+QString OSInterface::networkTypeFromDeviceName(QString name){
+ //Return options: wifi, wired, cell, cell-2G, cell-3G, cell-4G
return "";
}
-float OSInterface::networkStrength(){ return -1; } //percentage. ("wired" type should always be 100%)
-
-QString OSInterface::networkHostname(){
- return QHostInfo::localHostName();
-}
-
-QHostAddress OSInterface::networkAddress(){
- QString addr;
- if(INFO.contains("netaccess/address")){ addr = INFO.value("netaccess/address").toString(); }
- return QHostAddress(addr);
+float OSInterface::networkStrength(){
+ //QString device = INFO.value("netaccess/devicename");
+ return -1; //percentage. ("wired" type should always be 100%)
}
-// = Network Modification =
// = Media Shortcuts =
QStringList OSInterface::mediaDirectories(){ return QStringList() << "/media"; } //directory where XDG shortcuts are placed for interacting with media (local/remote)
QStringList OSInterface::mediaShortcuts(){ return autoHandledMediaFiles(); } //List of currently-available XDG shortcut file paths
// = Updates =
+bool OSInterface::updatesSupported(){ return false; }
bool OSInterface::updatesAvailable(){ return false; }
QString OSInterface::updateDetails(){ return QString(); } //Information about any available updates
bool OSInterface::updatesRunning(){ return false; }
@@ -71,6 +42,7 @@ bool OSInterface::updatesFinished(){ return false; }
QString OSInterface::updateResults(){ return QString(); } //Information about any finished update
void OSInterface::startUpdates(){}
bool OSInterface::updateOnlyOnReboot(){ return false; } //Should the startUpdates function be called only when rebooting the system?
+bool OSInterface::updateCausesReboot(){ return false; }
QDateTime OSInterface::lastUpdate(){ return QDateTime(); } //The date/time of the previous updates
QString OSInterface::lastUpdateResults(){ return QString(); } //Information about the previously-finished update
@@ -83,68 +55,39 @@ bool OSInterface::canSuspend(){ return false; }
void OSInterface::startSuspend(){}
// = Screen Brightness =
+bool OSInterface::brightnessSupported(){ return false; }
int OSInterface::brightness(){ return -1; } //percentage: 0-100 with -1 for errors
void OSInterface::setBrightness(int){}
// = System Status Monitoring
+bool OSInterface::cpuSupported(){ return false; }
QList<int> OSInterface::cpuPercentage(){ return QList<int>(); } // (one per CPU) percentage: 0-100 with empty list for errors
QStringList OSInterface::cpuTemperatures(){ return QStringList(); } // (one per CPU) Temperature of CPU ("50C" for example)
+
+bool OSInterface::memorySupported(){ return false; }
int OSInterface::memoryUsedPercentage(){ return -1; } //percentage: 0-100 with -1 for errors
QString OSInterface::memoryTotal(){ return QString(); } //human-readable form - does not tend to change within a session
QStringList OSInterface::diskIO(){ return QStringList(); } //Returns list of current read/write stats for each device
+
+bool OSInterface::diskSupported(){ return false; }
int OSInterface::fileSystemPercentage(QString dir){ return -1; } //percentage of capacity used: 0-100 with -1 for errors
QString OSInterface::fileSystemCapacity(QString dir){ return QString(); } //human-readable form - total capacity
// = OS-Specific Utilities =
-bool OSInterface::hasControlPanel(){ return false; }
QString OSInterface::controlPanelShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
-bool OSInterface::hasAudioMixer(){ return false; }
QString OSInterface::audioMixerShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
-bool OSInterface::hasAppStore(){ return false; }
QString OSInterface::appStoreShortcut(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
+QString OSInterface::networkManagerUtility(){ return QString(); } //relative *.desktop shortcut name (Example: "some_utility.desktop")
-//FileSystemWatcher slots
-void OSInterface::watcherFileChanged(QString){}
-void OSInterface::watcherDirChanged(QString dir){
- if(handleMediaDirChange(dir)){ return; }
+//FileSystemWatcher slots (optional - re-implement only if needed/used by this OS)
+void OSInterface::watcherFileChanged(QString){} //any additional parsing for files that are watched
+void OSInterface::watcherDirChanged(QString dir){ //any additional parsing for watched directories
+ if(handleMediaDirChange(dir)){ return; } //auto-handled media directories
}
-//IO Device slots
+//IO Device slots (optional - implement only if needed/used by this OS)
void OSInterface::iodeviceReadyRead(){}
void OSInterface::iodeviceAboutToClose(){}
-//NetworkAccessManager slots
-void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility stat){
- INFO.insert("netaccess/available", stat== QNetworkAccessManager::Accessible);
- //Update all the other network status info at the same time
- QNetworkConfiguration active = netman->activeConfiguration();
- //Type of connection
- QString type;
- switch(active.bearerTypeFamily()){
- case QNetworkConfiguration::BearerEthernet: type="wired"; break;
- case QNetworkConfiguration::BearerWLAN: type="wifi"; break;
- case QNetworkConfiguration::Bearer2G: type="cell-2G"; break;
- case QNetworkConfiguration::Bearer3G: type="cell-3G"; break;
- case QNetworkConfiguration::Bearer4G: type="cell-4G"; break;
- default: type="";
- }
- INFO.insert("netaccess/type", type);
- qDebug() << "Detected Device Status:" << active.identifier() << type << stat;
- QNetworkInterface iface = QNetworkInterface::interfaceFromName(active.name());
- qDebug() << " - Configuration: Name:" << active.name() << active.bearerTypeName() << active.identifier();
- qDebug() << " - Interface: MAC Address:" << iface.hardwareAddress() << "Name:" << iface.name() << iface.humanReadableName() << iface.isValid();
- QList<QNetworkAddressEntry> addressList = iface.addressEntries();
- QStringList address;
- //NOTE: There are often 2 addresses, IPv4 and IPv6
- for(int i=0; i<addressList.length(); i++){
- address << addressList[i].ip().toString();
- }
- qDebug() << " - IP Address:" << address;
- qDebug() << " - Hostname:" << networkHostname();
- INFO.insert("netaccess/address", address.join(", "));
- emit networkStatusChanged();
-}
-
void OSInterface::netRequestFinished(QNetworkReply*){}
void OSInterface::netSslErrors(QNetworkReply*, const QList<QSslError>&){}
-void OSInterface::timerUpdate(){}
diff --git a/src-qt5/src-cpp/framework-OSInterface.h b/src-qt5/src-cpp/framework-OSInterface.h
index a173ad5a..f8345bac 100644
--- a/src-qt5/src-cpp/framework-OSInterface.h
+++ b/src-qt5/src-cpp/framework-OSInterface.h
@@ -18,6 +18,9 @@
#include <QVariant>
#include <QHash>
#include <QTimer>
+#include <QFile>
+#include <QDir>
+#include <QVariant>
#include <QIODevice>
#include <QFileSystemWatcher>
@@ -26,6 +29,11 @@
#include <QSslError>
#include <QHostInfo>
#include <QHostAddress>
+#include <QNetworkConfiguration>
+#include <QNetworkInterface>
+
+//Lumina Utils class
+#include <LUtils.h>
class OSInterface : public QObject{
Q_OBJECT
@@ -69,22 +77,30 @@ public:
Q_INVOKABLE float batteryCharge();
Q_INVOKABLE bool batteryCharging();
Q_INVOKABLE double batterySecondsLeft();
+
// = Volume =
- Q_INVOKABLE bool volumeAvailable();
+ Q_INVOKABLE bool volumeSupported();
Q_INVOKABLE int volume();
Q_INVOKABLE void setVolume(int);
+
// = Network Information =
Q_INVOKABLE bool networkAvailable();
Q_INVOKABLE QString networkType(); //"wifi", "wired", "cell", "cell-2G", "cell-3G", "cell-4G"
+ Q_INVOKABLE QString networkTypeFromDeviceName(QString name); //wifi, wired, cell, cell-2G, cell-3G, cell-4G
Q_INVOKABLE float networkStrength(); //percentage. ("wired" type should always be 100%)
Q_INVOKABLE QString networkHostname();
Q_INVOKABLE QHostAddress networkAddress();
+
// = Network Modification =
+ Q_INVOKABLE bool hasNetworkManager();
+ Q_INVOKABLE QString networkManagerUtility(); //binary name or *.desktop filename (if registered on the system)
// = Media Shortcuts =
Q_INVOKABLE QStringList mediaDirectories(); //directory where XDG shortcuts are placed for interacting with media (local/remote)
Q_INVOKABLE QStringList mediaShortcuts(); //List of currently-available XDG shortcut file paths
+
// = Updates =
+ Q_INVOKABLE bool updatesSupported(); //is thie subsystem supported for the OS?
Q_INVOKABLE bool updatesAvailable();
Q_INVOKABLE QString updateDetails(); //Information about any available updates
Q_INVOKABLE bool updatesRunning();
@@ -93,8 +109,10 @@ public:
Q_INVOKABLE QString updateResults(); //Information about any finished update
Q_INVOKABLE void startUpdates();
Q_INVOKABLE bool updateOnlyOnReboot(); //Should the startUpdates function be called only when rebooting the system?
+ Q_INVOKABLE bool updateCausesReboot(); //Does the update power-cycle the system?
Q_INVOKABLE QDateTime lastUpdate(); //The date/time of the previous updates
Q_INVOKABLE QString lastUpdateResults(); //Information about the previously-finished update
+
// = System Power =
Q_INVOKABLE bool canReboot();
Q_INVOKABLE void startReboot();
@@ -102,17 +120,26 @@ public:
Q_INVOKABLE void startShutdown();
Q_INVOKABLE bool canSuspend();
Q_INVOKABLE void startSuspend();
+
// = Screen Brightness =
+ Q_INVOKABLE bool brightnessSupported(); //is this subsystem available for the OS?
Q_INVOKABLE int brightness(); //percentage: 0-100 with -1 for errors
Q_INVOKABLE void setBrightness(int);
+
// = System Status Monitoring
+ Q_INVOKABLE bool cpuSupported(); //is this subsystem available for the OS?
Q_INVOKABLE QList<int> cpuPercentage(); // (one per CPU) percentage: 0-100 with -1 for errors
Q_INVOKABLE QStringList cpuTemperatures(); // (one per CPU) Temperature of CPU ("50C" for example)
+
+ Q_INVOKABLE bool memorySupported(); //is this subsystem available for the OS?
Q_INVOKABLE int memoryUsedPercentage(); //percentage: 0-100 with -1 for errors
Q_INVOKABLE QString memoryTotal(); //human-readable form - does not tend to change within a session
Q_INVOKABLE QStringList diskIO(); //Returns list of current read/write stats for each device
+
+ Q_INVOKABLE bool diskSupported(); //is this subsystem available for the OS?
Q_INVOKABLE int fileSystemPercentage(QString dir); //percentage of capacity used: 0-100 with -1 for errors
Q_INVOKABLE QString fileSystemCapacity(QString dir); //human-readable form - total capacity
+
// = OS-Specific Utilities =
Q_INVOKABLE bool hasControlPanel();
Q_INVOKABLE QString controlPanelShortcut(); //relative *.desktop shortcut name (Example: "some_utility.desktop")
@@ -121,10 +148,14 @@ public:
Q_INVOKABLE bool hasAppStore();
Q_INVOKABLE QString appStoreShortcut(); //relative *.desktop shortcut name (Example: "some_utility.desktop")
+
+ // QML-Accessible properties/functions
+
private slots:
// ================
// SEMI-VIRTUAL FUNCTIONS - NEED TO BE DEFINED IN THE OS-SPECIFIC FILES
// ================
+
//FileSystemWatcher slots
void watcherFileChanged(QString);
void watcherDirChanged(QString);
@@ -136,7 +167,13 @@ private slots:
void netRequestFinished(QNetworkReply*);
void netSslErrors(QNetworkReply*, const QList<QSslError>&);
//Timer slots
- void timerUpdate();
+ void BatteryTimerUpdate();
+ void UpdateTimerUpdate();
+ void BrightnessTimerUpdate();
+ void VolumeTimerUpdate();
+ void CpuTimerUpdate();
+ void MemTimerUpdate();
+ void DiskTimerUpdate();
signals:
void batteryChargeChanged();
@@ -152,6 +189,7 @@ signals:
private:
//Internal persistant data storage, OS-specific usage implementation
QHash< QString, QVariant> INFO;
+ bool _started;
// ============
// Internal possibilities for watching the system (OS-Specific usage/implementation)
@@ -163,14 +201,16 @@ private:
//Network Access Manager (check network connectivity, etc)
QNetworkAccessManager *netman;
//Timer for regular probes/updates
- QTimer *timer;
+ QTimer *batteryTimer, *updateTimer, *brightnessTimer, *volumeTimer, *cpuTimer, *memTimer, *diskTimer;
// Internal implifications for connecting the various watcher objects to their respective slots
// (OS-agnostic - defined in the "OSInterface_private.cpp" file)
void connectWatcher(); //setup the internal connections *only*
void connectIodevice(); //setup the internal connections *only*
void connectNetman(); //setup the internal connections *only*
- void connectTimer(); //setup the internal connections *only*
+
+ //Internal simplification routines
+ bool verifyAppOrBin(QString chk);
// External Media Management (if system uses *.desktop shortcuts only)
void setupMediaWatcher();
@@ -180,6 +220,24 @@ private:
// Qt-based NetworkAccessManager usage
void setupNetworkManager();
+ // Timer-based monitors
+ void setupBatteryMonitor(int update_ms, int delay_ms);
+ void setupUpdateMonitor(int update_ms, int delay_ms);
+ void setupBrightnessMonitor(int update_ms, int delay_ms);
+ void setupVolumeMonitor(int update_ms, int delay_ms);
+ void setupCpuMonitor(int update_ms, int delay_ms);
+ void setupMemoryMonitor(int update_ms, int delay_ms);
+ void setupDiskMonitor(int update_ms, int delay_ms);
+
+ // Timer-based monitor update routines (NOTE: these are all run in a separate thread!!)
+ void syncBatteryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncUpdateInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncBrightnessInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncVolumeInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncCpuInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncMemoryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+ void syncDiskInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer);
+
public:
OSInterface(QObject *parent = 0);
~OSInterface();
diff --git a/src-qt5/src-cpp/framework-OSInterface_private.cpp b/src-qt5/src-cpp/framework-OSInterface_private.cpp
index d15d9be8..d633fe9a 100644
--- a/src-qt5/src-cpp/framework-OSInterface_private.cpp
+++ b/src-qt5/src-cpp/framework-OSInterface_private.cpp
@@ -7,9 +7,7 @@
// Internal, OS-agnostic functionality for managing the object itself
//===========================================
#include <framework-OSInterface.h>
-#include <QFile>
-#include <QDir>
-#include <QVariant>
+#include <QtConcurrent>
OSInterface::OSInterface(QObject *parent) : QObject(parent){
watcher = 0;
@@ -40,6 +38,33 @@ OSInterface* OSInterface::instance(){
return m_os_object;
}
+//Start/stop interface systems
+void OSInterface::start(){
+ if(!mediaDirectories().isEmpty()){ setupMediaWatcher(); }//will create/connect the filesystem watcher automatically
+ setupNetworkManager(); //will create/connect the network monitor automatically
+ if(batteryAvailable()){ setupBatteryMonitor(30000, 1); } //30 second updates, 1 ms init delay
+ if(brightnessSupported()){ setupBrightnessMonitor(60000, 1); } //1 minute updates, 1 ms init delay
+ if(volumeSupported()){ setupVolumeMonitor(60000, 2); } //1 minute updates, 2 ms init delay
+ if(updatesSupported()){ setupUpdateMonitor(12*60*60*1000, 5*60*1000); } //12-hour updates, 5 minute delay
+ if(cpuSupported()){ setupCpuMonitor(2000, 20); } //2 second updates, 20 ms init delay
+ if(memorySupported()){ setupMemoryMonitor(2000, 21); } //2 second updates, 21 ms init delay
+ if(diskSupported()){ setupDiskMonitor(60000, 25); } //1 minute updates, 25 ms init delay
+}
+
+void OSInterface::stop(){
+ if(watcher!=0){ watcher->deleteLater(); watcher=0; }
+ if(batteryTimer!=0){ batteryTimer->stop(); disconnect(batteryTimer); }
+ if(brightnessTimer!=0){ brightnessTimer->stop(); disconnect(brightnessTimer); }
+ if(volumeTimer!=0){ volumeTimer->stop(); disconnect(volumeTimer); }
+ if(updateTimer!=0){ updateTimer->stop(); disconnect(updateTimer); }
+ if(cpuTimer!=0){ cpuTimer->stop(); disconnect(cpuTimer); }
+ if(memTimer!=0){ memTimer->stop(); disconnect(memTimer); }
+ if(diskTimer!=0){ diskTimer->stop(); disconnect(diskTimer); }
+ if(netman!=0){ disconnect(netman); netman->deleteLater(); netman = 0; }
+}
+
+bool OSInterface::isRunning(){ return _started; } //status of the object - whether it has been started yet
+
void OSInterface::connectWatcher(){
if(watcher==0){ return; }
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(watcherFileChanged(QString)) );
@@ -58,11 +83,36 @@ void OSInterface::connectNetman(){
connect(netman, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)), this, SLOT(netSslErrors(QNetworkReply*, const QList<QSslError>&)) );
}
-void OSInterface::connectTimer(){
- if(timer==0){ return; }
- connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate()) );
+bool OSInterface::verifyAppOrBin(QString chk){
+ bool valid = !chk.isEmpty();
+ if(valid && chk.endsWith(".desktop")){
+ chk = LUtils::AppToAbsolute(chk);
+ valid = QFile::exists(chk);
+ }else if(valid){
+ valid = LUtils::isValidBinary(chk);
+ }
+ return valid;
+}
+
+// ===========================
+// OS SPECIFIC EXISTANCE CHECKS
+// ===========================
+bool OSInterface::hasControlPanel(){
+ return verifyAppOrBin(controlPanelShortcut());
+}
+
+bool OSInterface::hasAudioMixer(){
+ return verifyAppOrBin(audioMixerShortcut());
+}
+
+bool OSInterface::hasAppStore(){
+ return verifyAppOrBin(appStoreShortcut());
}
+// ========================
+// MEDIA DIRECTORIES
+// ========================
+
// External Media Management (if system uses *.desktop shortcuts)
void OSInterface::setupMediaWatcher(){
//Create/connect the watcher if needed
@@ -99,6 +149,9 @@ QStringList OSInterface::autoHandledMediaFiles(){
return files;
}
+// =============================
+// NETWORK INTERFACE FUNCTIONS
+// =============================
// Qt-based NetworkAccessManager usage
void OSInterface::setupNetworkManager(){
if(netman==0){
@@ -108,3 +161,179 @@ void OSInterface::setupNetworkManager(){
//Load the initial state of the network accessibility
netAccessChanged(netman->networkAccessible());
}
+
+bool OSInterface::networkAvailable(){
+ if(INFO.contains("netaccess/available")){ return INFO.value("netaccess/available").toBool(); }
+ return false;
+}
+
+QString OSInterface::networkType(){
+ if(INFO.contains("netaccess/type")){ return INFO.value("netaccess/type").toString(); } //"wifi", "wired", or "cell"
+ return "";
+}
+
+QString OSInterface::networkHostname(){
+ return QHostInfo::localHostName();
+}
+
+QHostAddress OSInterface::networkAddress(){
+ QString addr;
+ if(INFO.contains("netaccess/address")){ addr = INFO.value("netaccess/address").toString(); }
+ return QHostAddress(addr);
+}
+
+bool OSInterface::hasNetworkManager(){
+ return verifyAppOrBin(networkManagerUtility());
+}
+
+//NetworkAccessManager slots
+void OSInterface::netAccessChanged(QNetworkAccessManager::NetworkAccessibility stat){
+ INFO.insert("netaccess/available", stat== QNetworkAccessManager::Accessible);
+ //Update all the other network status info at the same time
+ QNetworkConfiguration active = netman->activeConfiguration();
+ //Type of connection
+ QString type;
+ switch(active.bearerTypeFamily()){
+ case QNetworkConfiguration::BearerEthernet: type="wired"; break;
+ case QNetworkConfiguration::BearerWLAN: type="wifi"; break;
+ case QNetworkConfiguration::Bearer2G: type="cell-2G"; break;
+ case QNetworkConfiguration::Bearer3G: type="cell-3G"; break;
+ case QNetworkConfiguration::Bearer4G: type="cell-4G"; break;
+ default: type=networkTypeFromDeviceName(active.name()); //could not be auto-determined - run the OS-specific routine
+ }
+ INFO.insert("netaccess/type", type);
+ //qDebug() << "Detected Device Status:" << active.identifier() << type << stat;
+ QNetworkInterface iface = QNetworkInterface::interfaceFromName(active.name());
+ //qDebug() << " - Configuration: Name:" << active.name() << active.bearerTypeName() << active.identifier();
+ //qDebug() << " - Interface: MAC Address:" << iface.hardwareAddress() << "Name:" << iface.name() << iface.humanReadableName() << iface.isValid();
+ QList<QNetworkAddressEntry> addressList = iface.addressEntries();
+ QStringList address;
+ //NOTE: There are often 2 addresses, IPv4 and IPv6
+ for(int i=0; i<addressList.length(); i++){
+ address << addressList[i].ip().toString();
+ }
+ //qDebug() << " - IP Address:" << address;
+ //qDebug() << " - Hostname:" << networkHostname();
+ INFO.insert("netaccess/address", address.join(", "));
+ emit networkStatusChanged();
+}
+
+
+// ========================
+// TIMER-BASED MONITORS
+// ========================
+//Timer slots
+void OSInterface::BatteryTimerUpdate(){
+ QtConcurrent::run(this, &OSInterface::syncBatteryInfo, this, &INFO, batteryTimer);
+}
+
+void OSInterface::UpdateTimerUpdate(){
+ QtConcurrent::run(this, &OSInterface::syncUpdateInfo, this, &INFO, updateTimer);
+}
+
+void OSInterface::BrightnessTimerUpdate(){
+ QtConcurrent::run(this, &OSInterface::syncBrightnessInfo, this, &INFO, brightnessTimer);
+}
+
+void OSInterface::VolumeTimerUpdate(){
+ QtConcurrent::run(this, &OSInterface::syncVolumeInfo, this, &INFO, volumeTimer);
+}
+
+void OSInterface::CpuTimerUpdate(){
+ QtConcurrent::run(this, &OSInterface::syncCpuInfo, this, &INFO, cpuTimer);
+}
+
+void OSInterface::MemTimerUpdate(){
+ QtConcurrent::run(this, &OSInterface::syncMemoryInfo, this, &INFO, memTimer);
+}
+
+void OSInterface::DiskTimerUpdate(){
+ QtConcurrent::run(this, &OSInterface::syncDiskInfo, this, &INFO, diskTimer);
+}
+
+// Timer Setup functions
+void OSInterface::setupBatteryMonitor(int update_ms, int delay_ms){
+ batteryTimer = new QTimer(this);
+ batteryTimer->setSingleShot(true);
+ batteryTimer->setInterval(update_ms);
+ connect(batteryTimer, SIGNAL(timeout()), this, SLOT(BatteryTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(BatteryTimerUpdate()) );
+}
+void OSInterface::setupUpdateMonitor(int update_ms, int delay_ms){
+ updateTimer = new QTimer(this);
+ updateTimer->setSingleShot(true);
+ updateTimer->setInterval(update_ms);
+ connect(updateTimer, SIGNAL(timeout()), this, SLOT(UpdateTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(UpdateTimerUpdate()) );
+}
+void OSInterface::setupBrightnessMonitor(int update_ms, int delay_ms){
+ brightnessTimer = new QTimer(this);
+ brightnessTimer->setSingleShot(true);
+ brightnessTimer->setInterval(update_ms);
+ connect(brightnessTimer, SIGNAL(timeout()), this, SLOT(BrightnessTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(BrightnessTimerUpdate()) );
+}
+void OSInterface::setupVolumeMonitor(int update_ms, int delay_ms){
+ volumeTimer = new QTimer(this);
+ volumeTimer->setSingleShot(true);
+ volumeTimer->setInterval(update_ms);
+ connect(volumeTimer, SIGNAL(timeout()), this, SLOT(VolumeTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(VolumeTimerUpdate()) );
+}
+void OSInterface::setupCpuMonitor(int update_ms, int delay_ms){
+ cpuTimer = new QTimer(this);
+ cpuTimer->setSingleShot(true);
+ cpuTimer->setInterval(update_ms);
+ connect(cpuTimer, SIGNAL(timeout()), this, SLOT(CpuTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(CpuTimerUpdate()) );
+}
+void OSInterface::setupMemoryMonitor(int update_ms, int delay_ms){
+ memTimer = new QTimer(this);
+ memTimer->setSingleShot(true);
+ memTimer->setInterval(update_ms);
+ connect(memTimer, SIGNAL(timeout()), this, SLOT(MemTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(MemTimerUpdate()) );
+}
+void OSInterface::setupDiskMonitor(int update_ms, int delay_ms){
+ diskTimer = new QTimer(this);
+ diskTimer->setSingleShot(true);
+ diskTimer->setInterval(update_ms);
+ connect(diskTimer, SIGNAL(timeout()), this, SLOT(DiskTimerUpdate()) );
+ QTimer::singleShot(delay_ms, this, SLOT(DiskTimerUpdate()) );
+}
+
+// Timer-based monitor update routines (NOTE: these are all run in a separate thread!!)
+void OSInterface::syncBatteryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncUpdateInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncBrightnessInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncVolumeInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncCpuInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncMemoryInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
+
+void OSInterface::syncDiskInfo(OSInterface *os, QHash<QString, QVariant> *hash, QTimer *timer){
+
+ QTimer::singleShot(0, timer, SLOT(start()));
+}
bgstack15