From af37fa6a5ec4c7efd3332c5abbebdb5adbfa201d Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 20 Sep 2017 08:28:37 -0400 Subject: Streamline a bit more of the new Lumina2 window embed functionality. --- src-qt5/core/libLumina/NativeEmbedWidget.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.cpp b/src-qt5/core/libLumina/NativeEmbedWidget.cpp index 876c701d..ff0f4734 100644 --- a/src-qt5/core/libLumina/NativeEmbedWidget.cpp +++ b/src-qt5/core/libLumina/NativeEmbedWidget.cpp @@ -116,7 +116,8 @@ void NativeEmbedWidget::showWindow(){ } QImage NativeEmbedWidget::windowImage(QRect geom){ - if(DISABLE_COMPOSITING){ + //if(DISABLE_COMPOSITING){ + if(!this->isVisible()){ return QImage(); } //nothing to grab yet QList screens = static_cast( QApplication::instance() )->screens(); //for(int i=0; icontains(this)){ @@ -126,7 +127,7 @@ QImage NativeEmbedWidget::windowImage(QRect geom){ //} //} return QImage(); - }else{ + /*}else{ //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); @@ -144,7 +145,7 @@ QImage NativeEmbedWidget::windowImage(QRect geom){ xcb_free_pixmap(QX11Info::connection(), pix); return img; - } + }*/ } void NativeEmbedWidget::setWinUnpaused(){ paused = false; @@ -154,6 +155,7 @@ void NativeEmbedWidget::setWinUnpaused(){ }else if(this->isVisible()){ showWindow(); } + resyncWindow(); //make sure the window knows about the new location } // ============ // PUBLIC @@ -203,6 +205,7 @@ bool NativeEmbedWidget::embedWindow(NativeWindow *window){ registerClientEvents(this->winId()); //child events get forwarded through the frame - watch this for changes too //Also use a partial-composite here - make sure the window pixmap is available even when the window is obscured xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_AUTOMATIC); + //xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //Also alert us when the window visual changes Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles); @@ -264,10 +267,10 @@ void NativeEmbedWidget::resume(){ void NativeEmbedWidget::resyncWindow(){ if(WIN==0){ return; } - syncWinSize(); - if(DISABLE_COMPOSITING){ + //syncWinSize(); + //if(DISABLE_COMPOSITING){ // Specs say to send an artificial configure event to the window if the window was reparented into the frame - QPoint loc = this->mapToGlobal( QPoint(0,0)); + QPoint loc = this->mapToGlobal( QPoint(0,0) ); //Send an artificial configureNotify event to the window with the global position/size included xcb_configure_notify_event_t *event = (xcb_configure_notify_event_t*) calloc(32,1); //always 32-byes long, even if we don't need all of it event->x = loc.x(); @@ -283,12 +286,12 @@ void NativeEmbedWidget::resyncWindow(){ xcb_send_event(QX11Info::connection(), false, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, (char *) event); xcb_flush(QX11Info::connection()); free(event); - }else{ + /*}else{ //Window is floating invisibly - make sure it is in the right place //Make sure the window size is syncronized and visual up to date //syncWinSize(); QTimer::singleShot(10, this, SLOT(repaintWindow()) ); - } + }*/ } @@ -344,7 +347,7 @@ void NativeEmbedWidget::paintEvent(QPaintEvent *ev){ QPainter P(this); P.setClipping(true); P.setClipRect(0,0,this->width(), this->height()); - if(DISABLE_COMPOSITING){ P.fillRect(geom, Qt::black); } //get weird effects when partial-compositing is enabled if you layer transparent window frames above other windows + //if(DISABLE_COMPOSITING){ P.fillRect(geom, Qt::black); } //get weird effects when partial-compositing is enabled if you layer transparent window frames above other windows //qDebug() << "Paint Embed Window:" << geom << winImage.size(); //if(winImage.size() == this->size()){ P.drawImage( geom , img, QRect(QPoint(0,0), img.size()), Qt::NoOpaqueDetection); //1-to-1 mapping -- cgit From 22387bf6f3ab740630955caa8f2170db8a1f954c Mon Sep 17 00:00:00 2001 From: Tommi Nieminen Date: Wed, 20 Sep 2017 13:41:55 +0000 Subject: Translated using Weblate (Finnish) Currently translated at 100.0% (88 of 88 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/fi/ --- .../lumina-archiver/i18n/l-archiver_fi.ts | 176 ++++++++++----------- 1 file changed, 88 insertions(+), 88 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts index eace2dca..e1832938 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts @@ -6,22 +6,22 @@ Could not read archive - + Arkistoa ei voitu lukea Archive Loaded - + Arkisto ladattu Extraction Finished - + Purku valmis Modification Finished - + Muutos valmis @@ -29,307 +29,307 @@ Archive: - + Arkisto: File - + Tiedosto Edit - + Muokkaa Burn to Disk - + Polta levylle &Open Archive - + &Avaa arkisto Open archive - + Avaa arkisto &New Archive - + &Uusi arkisto New archive - + Uusi arkisto &Quit - + &Lopeta Add File(s) - + Lisää tiedostoja Add files to archive - + Lisää arkistoon tiedostoja Remove File(s) - + Poista tiedostoja Remove selection from archive - + Poista arkistosta tiedostoja Extract All - + Pura kaikki Extract archive into a directory - + Pura arkisto kansioon Add Directory - + Lisää kansio Add directory to archive - + Lisää arkistoon kansio Extract Selection - + Pura valinta Extract Selected Items - + Pura valitut kohteet USB Image - + USB-levykuva Copy an IMG to a USB device (may require admin permission) - + Kopioi IMG-levykuva USB-laitteeseen (voi vaatia ylläpitäjän oikeuksia) Archive Manager - + Arkistonhallinta Admin Mode - + Ylläpitäjän tila CTRL+N - + Ctrl+N CTRL+O - + Ctrl+O CTRL+Q - + Ctrl+Q CTRL+E - + Ctrl+E MimeType - + MIME-tyyppi Size - + Koko Opening Archive... - + Avataan arkistoa... All Types %1 - + Kaikki tyypit %1 Uncompressed Archive (*.tar) - + Pakkaamaton arkisto (*.tar) GZip Compressed Archive (*.tar.gz *.tgz) - + GZip-pakattu arkisto (*.tar.gz *.tgz) BZip Compressed Archive (*.tar.bz *.tbz) - + BZip-pakattu arkisto (*.tar.bz *.tbz) BZip2 Compressed Archive (*.tar.bz2 *.tbz2) - + BZip2-pakattu arkisto (*.tar.bz2 *.tbz2) LMZA Compressed Archive (*.tar.lzma *.tlz) - + LMZA-pakattu arkisto (*.tar.lzma *.tlz) XZ Compressed Archive (*.tar.xz *.txz) - + XZ-pakattu arkisto (*.tar.xz *.txz) CPIO Archive (*.cpio) - + CPIO-arkisto (*.cpio) PAX Archive (*.pax) - + PAX-arkisto (*.pax) AR Archive (*.ar) - + AR-arkisto (*.ar) SHAR Archive (*.shar) - + SHAR-arkisto (*.shar) Zip Archive (*.zip) - + Zip-arkisto (*.zip) 7-Zip Archive (*.7z) - + 7-Zip-arkisto (*.7z) All Known Types %1 - + Kaikki tunnetut tyypit %1 READ-ONLY: ISO image (*.iso *.img) - + VAIN LUKU: ISO-levykuva (*.iso *.img) READ-ONLY: XAR archive (*.xar) - + VAIN LUKU: XAR-arkisto (*.xar) READ-ONLY: Java archive (*.jar) - + VAIN LUKU: Java-arkisto (*.jar) READ-ONLY: RedHat Package (*.rpm) - + VAIN LUKU: RedHat-paketti (*.rpm) Show All Files (*) - + Näytä kaikki tiedostot (*) Create Archive - + Luo arkisto Error - + Virhe Could not overwrite file: - + Ei voitu korvata tiedostoa: Open Archive - + Avaa arkisto Add to Archive - + Lisää arkistoon Adding Items... - + Lisätään kohteita... Removing Items... - + Poistetaan kohteita... Extract Into Directory - + Pura kansioon @@ -337,12 +337,12 @@ Extracting... - + Puretaan... Link To: %1 - + Linkki kohteeseen: %1 @@ -350,127 +350,127 @@ Burn IMG to device - + Polta IMG-levykuva laitteelle IMG File - + IMG-tiedosto Block Size - + Lohkokoko USB Device - + USB-laite Refresh Device List - + Virkistä laiteluettelo Wipe all extra space on device (conv = sync) - + Pyyhi laitteen kaikki ylimääräinen tila (conv=sync) Burning to USB: - + Poltetaan USB:lle: Time Elapsed: - + Aikaa kulunut: Cancel - + Peru Start - + Käynnistä Burn IMG to Device - + Polta IMG-levykuva laitteelle Admin Mode - + Ylläpitäjän tila Kilobyte(s) - + kilotavu(a) Megabyte(s) - + megatavu(a) Gigabyte(s) - + gigatavu(a) Cancel Image Burn? - + Perutaanko levykuvan poltto? Do you wish to stop the current IMG burn process? - + Haluatko pysäyttää käynnissä olevan IMG-levykuvan polton? Warning: This will leave the USB device in an inconsistent state - + Varoitus: Tämä jättää USB-laitteesi epävakaaseen tilaan Administrator Permissions Needed - + Ylläpitäjäoikeudet vaaditaan This operation requires administrator priviledges. - + Tämä toiminto vaatii ylläpitäjän oikeuksia. Would you like to enable these priviledges? - + Haluatko ottaa nämä oikeudet käyttöön? ERROR - + VIRHE The process could not be completed: - + Toimenpidettä ei saatu loppuun: SUCCESS - + ONNISTUI The image was successfully burned to the USB device - + Levykuva poltettiin ongelmitta USB-laitteelle -- cgit From c1d7a162fa79b8f1c30ef519fbd631ceaffa5261 Mon Sep 17 00:00:00 2001 From: Moo Date: Sat, 26 Aug 2017 11:23:18 +0000 Subject: Translated using Weblate (Lithuanian) Currently translated at 96.5% (85 of 88 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/lt/ --- src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts index bfe38ea6..f04b12a6 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts @@ -445,12 +445,12 @@ This operation requires administrator priviledges. - + Ši operacija reikalauja administratoriaus teisių. Would you like to enable these priviledges? - + Ar norėtumėte leisti šias teises? -- cgit From 2c91b1cb93893d427e5890092aae2a48c57cee35 Mon Sep 17 00:00:00 2001 From: Davidmp Date: Wed, 20 Sep 2017 14:55:34 +0000 Subject: Translated using Weblate (Catalan) Currently translated at 100.0% (101 of 101 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/ca/ --- .../lumina-archiver/i18n/l-archiver_ca.ts | 66 +++++++++++----------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts index 98930879..f39823f0 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts @@ -6,7 +6,7 @@ Could not read archive - No s'ha pogut llegir l'arxiu + No s'ha pogut llegir l'arxiu @@ -81,7 +81,7 @@ Add files to archive - Afegiu fitxers a l'arxiu + Afegiu fitxers a l'arxiu @@ -91,7 +91,7 @@ Remove selection from archive - Elimina la selecció de l'arxiu + Elimina la selecció de l'arxiu @@ -101,7 +101,7 @@ Extract archive into a directory - Extreu l'arxiu en un directori + Extreu l'arxiu en un directori @@ -111,7 +111,7 @@ Add directory to archive - Afegeix un directori a l'arxiu + Afegeix un directori a l'arxiu @@ -131,17 +131,17 @@ Copy an IMG to a USB device (may require admin permission) - Copia una IMG en un dispositiu USB (pot caldre permís d'administrador) + Copia una IMG en un dispositiu USB (pot caldre permís d'administrador) Archive Manager - Gestor d'arxius + Gestor d'arxius Admin Mode - Mode d'administrador + Mode d'administrador @@ -179,7 +179,7 @@ Opening Archive... - S'obre l'arxiu... + S'obre l'arxiu... @@ -301,7 +301,7 @@ Could not overwrite file: - No s'ha pogut sobreescriure el fitxer: + No s'ha pogut sobreescriure el fitxer: @@ -312,18 +312,18 @@ Add to Archive - Afegeix a l'arxiu + Afegeix a l'arxiu Adding Items... - S'afegeixen elements... + S'afegeixen elements... Removing Items... - S'eliminen elements... + S'eliminen elements... @@ -337,7 +337,7 @@ Extracting... - S'extreu... + S'extreu... @@ -350,67 +350,67 @@ Multimedia - + Multimèdia Development - + Desenvolupament Education - + Educació Games - + Jocs Graphics - + Gràfics Network - + Xarxa Office - + Oficina Science - + Ciència Settings - + Configuració System - + Sistema Utility - + Utilitat Wine - + Wine Unsorted - + Sense classificar @@ -443,7 +443,7 @@ Wipe all extra space on device (conv = sync) - Neteja tot l'espai extra al dispositiu (conv = sync) + Neteja tot l'espai extra al dispositiu (conv = sync) @@ -473,7 +473,7 @@ Admin Mode - Mode d'administrador + Mode d'administrador @@ -508,12 +508,12 @@ Administrator Permissions Needed - Calen permisos d'administrador + Calen permisos d'administrador This operation requires administrator priviledges. - Aquesta operació requereix privilegis d'administrador. + Aquesta operació requereix privilegis d'administrador. @@ -528,7 +528,7 @@ The process could not be completed: - El procés no s'ha pogut completar: + El procés no s'ha pogut completar: @@ -538,7 +538,7 @@ The image was successfully burned to the USB device - La imatge s'ha gravat correctament al dispositiu USB. + La imatge s'ha gravat correctament al dispositiu USB. -- cgit From d098890ae7793ee6031a7a1f2cea852f301905df Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 20 Sep 2017 11:15:21 -0400 Subject: Cleanup a bit more of the embed stuff. --- src-qt5/core/libLumina/NativeEmbedWidget.cpp | 23 +++++------------------ src-qt5/core/libLumina/RootSubWindow.cpp | 18 ++++++++++++++---- src-qt5/core/libLumina/RootSubWindow.h | 1 + 3 files changed, 20 insertions(+), 22 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.cpp b/src-qt5/core/libLumina/NativeEmbedWidget.cpp index ff0f4734..57b6edde 100644 --- a/src-qt5/core/libLumina/NativeEmbedWidget.cpp +++ b/src-qt5/core/libLumina/NativeEmbedWidget.cpp @@ -331,11 +331,13 @@ void NativeEmbedWidget::hideEvent(QHideEvent *ev){ } void NativeEmbedWidget::paintEvent(QPaintEvent *ev){ + QPainter P(this); + P.setClipping(true); + P.setClipRect(0,0,this->width(), this->height()); + P.fillRect(ev->rect(), Qt::transparent); if(WIN==0){ return; } QRect geom = ev->rect(); //atomic updates //qDebug() << "Paint Rect:" << geom; - //geom.adjust(-10,-10,10,10); //add an additional few pixels in each direction to be painted - //geom = geom.intersected(QRect(0,0,this->width(), this->height())); //ensure intersection with actual window QImage img; if(!paused){ img = windowImage(geom); } else if(!winImage.isNull()){ @@ -343,23 +345,8 @@ void NativeEmbedWidget::paintEvent(QPaintEvent *ev){ else{ img = winImage.scaled(geom.size()); } //this is a fast transformation - might be slightly distorted } //Need to paint the image from the window onto the widget as an overlay + P.drawImage( geom , img, QRect(QPoint(0,0), img.size()), Qt::NoOpaqueDetection); //1-to-1 mapping - QPainter P(this); - P.setClipping(true); - P.setClipRect(0,0,this->width(), this->height()); - //if(DISABLE_COMPOSITING){ P.fillRect(geom, Qt::black); } //get weird effects when partial-compositing is enabled if you layer transparent window frames above other windows - //qDebug() << "Paint Embed Window:" << geom << winImage.size(); - //if(winImage.size() == this->size()){ - P.drawImage( geom , img, QRect(QPoint(0,0), img.size()), Qt::NoOpaqueDetection); //1-to-1 mapping - //Note: Qt::NoOpaqueDetection Speeds up the paint by bypassing the checks to see if there are [semi-]transparent pixels - // Since this is an embedded image - we fully expect there to be transparency all/most of the time. - // }else{ - //P.drawImage( geom , winImage); //auto-scale it to fit (transforming a static image while paused?) - // } - //else{ QImage scaled = winImage.scaled(geom.size()); P.drawImage(geom, scaled); } - //P.drawImage( geom , winImage, geom, Qt::NoOpaqueDetection); //1-to-1 mapping - //Note: Qt::NoOpaqueDetection Speeds up the paint by bypassing the checks to see if there are [semi-]transparent pixels - // Since this is an embedded image - we fully expect there to be transparency all/most of the time. } diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp index 5fb8ece4..5040f2f9 100644 --- a/src-qt5/core/libLumina/RootSubWindow.cpp +++ b/src-qt5/core/libLumina/RootSubWindow.cpp @@ -242,6 +242,16 @@ void RootSubWindow::enableFrame(bool on){ WIN->setProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList >(extents) ); //save to structure now } +void RootSubWindow::enableFrame(QList types){ + static QList noframe; + if(noframe.isEmpty()){ noframe << NativeWindow::T_DESKTOP << NativeWindow::T_DOCK << NativeWindow::T_TOOLBAR << NativeWindow::T_MENU << NativeWindow::T_SPLASH << NativeWindow::T_DROPDOWN_MENU << NativeWindow::T_POPUP_MENU << NativeWindow::T_TOOLTIP << NativeWindow::T_NOTIFICATION << NativeWindow::T_COMBO << NativeWindow::T_DND; } + for(int i=0; i list){ QList vals; //Always ensure that visibility changes are evaluated last @@ -370,7 +380,7 @@ void RootSubWindow::propertiesChanged(QList props, QList switch(props[i]){ case NativeWindow::Visible: if(!WinWidget->isPaused() && (this->isVisible()!=vals[i].toBool()) && activeState==Normal ){ - qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry(); + //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry(); if(vals[i].toBool()){ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/appear", "random").toString(), NativeWindow::Visible, vals[i]); } else{ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/disappear", "random").toString(), NativeWindow::Visible, vals[i]); } } @@ -397,7 +407,7 @@ void RootSubWindow::propertiesChanged(QList props, QList i--; }else if(!WinWidget->isPaused() && activeState==Normal){ if(WIN->property(NativeWindow::Size).toSize() != WinWidget->size()){ - qDebug() << "Got Direct Geometry Change:" << WIN->geometry(); + //qDebug() << "Got Direct Geometry Change:" << WIN->geometry(); this->setGeometry( QRect(this->geometry().topLeft(), WIN->geometry().size()) ); WinWidget->resyncWindow(); } @@ -434,8 +444,8 @@ void RootSubWindow::propertiesChanged(QList props, QList mainLayout->setContentsMargins( vals[i].value< QList >().at(0),vals[i].value< QList >().at(2) - titleLabel->height(),vals[i].value< QList >().at(1),vals[i].value< QList >().at(3)); break;*/ case NativeWindow::WinTypes: - qDebug() << "Got Window Types:" << vals[i].value< QList >(); - enableFrame(vals[i].value< QList >().contains(NativeWindow::T_NORMAL) ); + //qDebug() << "Got Window Types:" << vals[i].value< QList >(); + enableFrame(vals[i].value< QList >() ); break; default: qDebug() << "Window Property Unused:" << props[i] << vals[i]; diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/RootSubWindow.h index c1964724..67798140 100644 --- a/src-qt5/core/libLumina/RootSubWindow.h +++ b/src-qt5/core/libLumina/RootSubWindow.h @@ -59,6 +59,7 @@ private: void initWindowFrame(); void enableFrame(bool); + void enableFrame(QList types); void LoadProperties( QList< NativeWindow::Property> list); -- cgit From 5a3d2fb042e341be62864ffd1f06ad278514fd7d Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 20 Sep 2017 11:52:41 -0400 Subject: Get window type detection/usage all implemented. Now the window frame will get disabled/ignored for particular types of windows. --- src-qt5/core/libLumina/NativeWindowSystem.cpp | 22 +++++++++++++++++++++- src-qt5/core/libLumina/RootSubWindow.h | 1 + src-qt5/core/libLumina/RootWindow.cpp | 2 ++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/NativeWindowSystem.cpp b/src-qt5/core/libLumina/NativeWindowSystem.cpp index 0ee65929..e8e9655a 100644 --- a/src-qt5/core/libLumina/NativeWindowSystem.cpp +++ b/src-qt5/core/libLumina/NativeWindowSystem.cpp @@ -492,7 +492,27 @@ void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< Native } if(props.contains(NativeWindow::WinTypes)){ QList< NativeWindow::Type> types; - types << NativeWindow::T_NORMAL; //make this load appropriately later + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type_unchecked(&obj->EWMH, win->id()); + xcb_ewmh_get_atoms_reply_t reply; + if(1==xcb_ewmh_get_wm_window_type_reply(&obj->EWMH, cookie, &reply, NULL) ){ + for(unsigned int i=0; iEWMH._NET_WM_WINDOW_TYPE_DESKTOP){ types << NativeWindow::T_DESKTOP; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DOCK){ types << NativeWindow::T_DOCK; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR){ types << NativeWindow::T_TOOLBAR; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_MENU){ types << NativeWindow::T_MENU; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY){ types << NativeWindow::T_UTILITY; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH){ types << NativeWindow::T_SPLASH; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG){ types << NativeWindow::T_DIALOG; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU){ types << NativeWindow::T_DROPDOWN_MENU; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU){ types << NativeWindow::T_POPUP_MENU; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP){ types << NativeWindow::T_TOOLTIP; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION){ types << NativeWindow::T_NOTIFICATION; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_COMBO){ types << NativeWindow::T_COMBO; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DND){ types << NativeWindow::T_DND; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL){ types << NativeWindow::T_NORMAL; } + } + } + if(types.isEmpty()){ types << NativeWindow::T_NORMAL; } win->setProperty(NativeWindow::WinTypes, QVariant::fromValue< QList >(types) ); } } diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/RootSubWindow.h index 67798140..598298e2 100644 --- a/src-qt5/core/libLumina/RootSubWindow.h +++ b/src-qt5/core/libLumina/RootSubWindow.h @@ -66,6 +66,7 @@ private: static QStringList validAnimations(NativeWindow::Property); public slots: + void ensureVisible(){ WIN->setProperty(NativeWindow::Visible, true); } void giveMouseFocus(){ WinWidget->raiseWindow(); } void removeMouseFocus(){ WinWidget->lowerWindow(); } void giveKeyboardFocus(){ WIN->requestProperty(NativeWindow::Active, true, true); } diff --git a/src-qt5/core/libLumina/RootWindow.cpp b/src-qt5/core/libLumina/RootWindow.cpp index fdbc1eb8..705297be 100644 --- a/src-qt5/core/libLumina/RootWindow.cpp +++ b/src-qt5/core/libLumina/RootWindow.cpp @@ -239,7 +239,9 @@ void RootWindow::NewWindow(NativeWindow *win){ connect(subwin, SIGNAL(windowAnimFinished()), this, SLOT(checkMouseFocus()) ); WINDOWS << subwin; } + //QApplication::processEvents(); CheckWindowPosition(win->id(), true); //first-time run + //QTimer::singleShot(300, subwin, SLOT(ensureVisible())); win->setProperty(NativeWindow::Visible, true); //win->requestProperty( NativeWindow::Active, true); //win->requestProperties(QList() << NativeWindow::Visible << NativeWindow::Active, QList() << true << true, true); -- cgit From c0920fa4f8d8750259c3fa1e0687fa5ba2bd2f6f Mon Sep 17 00:00:00 2001 From: q5sys Date: Wed, 20 Sep 2017 12:09:00 -0400 Subject: fix tab order for text replacement --- src-qt5/desktop-utils/lumina-fm-dev/main.cpp | 3 +++ src-qt5/desktop-utils/lumina-fm-dev/widgets/DirWidget2.cpp | 4 ++++ src-qt5/desktop-utils/lumina-textedit/MainUI.ui | 7 ++++++- 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm-dev/main.cpp b/src-qt5/desktop-utils/lumina-fm-dev/main.cpp index 61d2dc95..a4a6244e 100644 --- a/src-qt5/desktop-utils/lumina-fm-dev/main.cpp +++ b/src-qt5/desktop-utils/lumina-fm-dev/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "MainUI.h" #include @@ -10,6 +11,7 @@ #include #include "BrowserWidget.h" +QElapsedTimer* timer = 0; int main(int argc, char ** argv) { @@ -27,6 +29,7 @@ int main(int argc, char ** argv) MainUI w; QObject::connect(&a, SIGNAL(InputsAvailable(QStringList)), &w, SLOT(slotSingleInstance(QStringList)) ); //QObject::connect(&themes, SIGNAL(updateIcons()), &w, SLOT(setupIcons()) ); + timer = new QElapsedTimer(); timer->start(); qDebug() << " - Init:" << timer->elapsed(); w.OpenDirs(in); w.show(); diff --git a/src-qt5/desktop-utils/lumina-fm-dev/widgets/DirWidget2.cpp b/src-qt5/desktop-utils/lumina-fm-dev/widgets/DirWidget2.cpp index 3790d145..2e837cfd 100644 --- a/src-qt5/desktop-utils/lumina-fm-dev/widgets/DirWidget2.cpp +++ b/src-qt5/desktop-utils/lumina-fm-dev/widgets/DirWidget2.cpp @@ -28,6 +28,8 @@ #define DEBUG 0 +extern QElapsedTimer* timer; + DirWidget::DirWidget(QString objID, QWidget *parent) : QWidget(parent), ui(new Ui::DirWidget){ ui->setupUi(this); //load the designer file ID = objID; @@ -90,6 +92,8 @@ DirWidget::DirWidget(QString objID, QWidget *parent) : QWidget(parent), ui(new U createShortcuts(); createMenus(); line_dir->setCompleter(new QCompleter(dirtreeModel, this)); + qDebug() << " - Fini:" << timer->elapsed(); + } DirWidget::~DirWidget(){ diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.ui b/src-qt5/desktop-utils/lumina-textedit/MainUI.ui index de5c1ee1..fec94a21 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.ui @@ -182,7 +182,7 @@ 0 0 505 - 21 + 28 @@ -437,6 +437,11 @@ + + line_find + line_replace + tool_hideReplaceGroup + -- cgit From 6a574b439adb7836822643c0362cf9a0653e8e58 Mon Sep 17 00:00:00 2001 From: q5sys Date: Wed, 20 Sep 2017 12:17:47 -0400 Subject: set LTE unsaved changes close dialog to follow the industry standard --- src-qt5/desktop-utils/lumina-textedit/MainUI.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp index 52a29c01..4c2ce0bd 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp @@ -496,11 +496,11 @@ void MainUI::closeEvent(QCloseEvent *ev){ unsaved << tmp->currentFile(); } } - bool quitnow = unsaved.isEmpty(); - if(!quitnow && !ui->actionShow_Popups->isChecked()){ quitnow = true; } - if(!quitnow){ - quitnow = (QMessageBox::Yes == QMessageBox::question(this, tr("Lose Unsaved Changes?"), QString(tr("There are unsaved changes.\nDo you want to close the editor anyway?\n\n%1")).arg(unsaved.join("\n")), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ); - } - if(quitnow){ QMainWindow::closeEvent(ev); } - else{ ev->ignore(); } + bool savenow = unsaved.isEmpty(); + if(!savenow && !ui->actionShow_Popups->isChecked()){ savenow = true; } + if(!savenow){ + savenow = (QMessageBox::Yes == QMessageBox::question(this, tr("Save Changes before closing?"), QString(tr("There are unsaved changes.\nDo you want save them before you close the editor?\n\n%1")).arg(unsaved.join("\n")), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ); + } + if(!savenow){ QMainWindow::closeEvent(ev); } + else{ ev->ignore(); SaveFile(); } } -- cgit From 87b64504cec8f071e51a51b853b0bce0cafebb78 Mon Sep 17 00:00:00 2001 From: scootergrisen Date: Wed, 20 Sep 2017 21:24:28 +0000 Subject: Translated using Weblate (Danish) Currently translated at 100.0% (101 of 101 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/da/ --- .../lumina-archiver/i18n/l-archiver_da.ts | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_da.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_da.ts index de00be03..ad4de0bd 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_da.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_da.ts @@ -350,67 +350,67 @@ Multimedia - + Multimedie Development - + Udvikling Education - + Uddannelse Games - + Spil Graphics - + Grafik Network - + Netværk Office - + Kontor Science - + Videnskab Settings - + Indstillinger System - + System Utility - + Hjælpeværktøj Wine - + Wine Unsorted - + Usorteret -- cgit From 04cac79681e1b585b31cbdf24f9c58c1195988a0 Mon Sep 17 00:00:00 2001 From: Davidmp Date: Wed, 20 Sep 2017 14:58:11 +0000 Subject: Translated using Weblate (Catalan) Currently translated at 100.0% (101 of 101 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/ca/ --- src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts index f39823f0..9e347a2a 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_ca.ts @@ -390,7 +390,7 @@ Settings - Configuració + Paràmetres -- cgit From 44d9434c1ebaed00834dcb9ba0aeb8f5af2c41cb Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 21 Sep 2017 13:13:27 -0400 Subject: Add a few quick safety checks to ensure that lumina-xconfig never disables the last active screen. --- src-qt5/core-utils/lumina-xconfig/ScreenSettings.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src-qt5') diff --git a/src-qt5/core-utils/lumina-xconfig/ScreenSettings.cpp b/src-qt5/core-utils/lumina-xconfig/ScreenSettings.cpp index 3c0edc76..a9d40554 100644 --- a/src-qt5/core-utils/lumina-xconfig/ScreenSettings.cpp +++ b/src-qt5/core-utils/lumina-xconfig/ScreenSettings.cpp @@ -13,6 +13,7 @@ void RRSettings::ApplyPrevious(){ QList screens; QSettings set("lumina-desktop","lumina-xconfig"); + if(set.allKeys().isEmpty()){ return; } QString profile = set.value("default_profile","").toString(); if(profile.isEmpty() || !savedProfiles().contains(profile) ){ screens = PreviousSettings(); } else{ screens = PreviousSettings(profile); } @@ -167,6 +168,13 @@ bool RRSettings::SaveScreens(QList screens, QString profile){ //Apply screen configuration void RRSettings::Apply(QList screens){ + //Verify that there is at least 1 active/enabled monitor first + bool foundactive = false; + for(int i=0; i Date: Thu, 21 Sep 2017 13:45:33 -0400 Subject: Fix up the application of theme settings from the system config file. --- src-qt5/core/libLumina/LDesktopUtils.cpp | 13 ++--- src-qt5/core/libLumina/LuminaThemes.cpp | 56 +++++++++++----------- src-qt5/core/libLumina/LuminaThemes.h | 8 ++-- .../defaults/luminaDesktop-TrueOS.conf | 2 +- .../lumina-desktop/defaults/luminaDesktop.conf | 2 +- 5 files changed, 38 insertions(+), 43 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index 54e660e6..9b7ee6d0 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -401,7 +401,7 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ QStringList syscolors = LTHEME::availableSystemColors(); //theme file //qDebug() << "Detected Themes/colors:" << systhemes << syscolors; - if( !themesettings[0].startsWith("/") || !QFile::exists(themesettings[0]) || !themesettings[0].endsWith(".qss.template")){ + if( !themesettings[0].startsWith("/") || !QFile::exists(themesettings[0]) || !themesettings[0].endsWith(".qss")){ themesettings[0] = themesettings[0].section(".qss",0,0).simplified(); for(int i=0; i::::] - list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]); + list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]); } return list; } QStringList LTHEME::availableLocalThemes(){ //returns: [name::::path] for each item - QDir dir( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themes"); - QStringList list = dir.entryList(QStringList() <<"*.qss.template", QDir::Files, QDir::Name); + QDir dir( QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/desktop_qss"); + QStringList list = dir.entryList(QStringList() <<"*.qss", QDir::Files, QDir::Name); for(int i=0; i::::] - list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]); + list[i] = list[i].section(".qss",0,0)+"::::"+dir.absoluteFilePath(list[i]); } return list; } QStringList LTHEME::availableSystemColors(){ //returns: [name::::path] for each item //returns: [name::::path] for each item - QDir dir(LOS::LuminaShare()+"colors"); - QStringList list = dir.entryList(QStringList() <<"*.qss.colors", QDir::Files, QDir::Name); + QDir dir(LOS::LuminaShare()+"../lthemeengine/colors"); + QStringList list = dir.entryList(QStringList() <<"*.conf", QDir::Files, QDir::Name); for(int i=0; i::::] - list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]); + list[i] = list[i].section(".conf",0,0)+"::::"+dir.absoluteFilePath(list[i]); } return list; } QStringList LTHEME::availableLocalColors(){ //returns: [name::::path] for each item - QDir dir(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/colors"); - QStringList list = dir.entryList(QStringList() <<"*.qss.colors", QDir::Files, QDir::Name); + QDir dir(QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/colors"); + QStringList list = dir.entryList(QStringList() <<"*.conf", QDir::Files, QDir::Name); for(int i=0; i::::] - list[i] = list[i].section(".qss.",0,0)+"::::"+dir.absoluteFilePath(list[i]); + list[i] = list[i].section(".conf",0,0)+"::::"+dir.absoluteFilePath(list[i]); } return list; } @@ -122,15 +122,17 @@ QStringList LTHEME::availableSystemCursors(){ //returns: [name] for each item //Save a new theme/color file bool LTHEME::saveLocalTheme(QString name, QStringList contents){ - QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themes/"; - if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); } - return LUtils::writeFile(localdir+name+".qss.template", contents, true); + return false; //old format - do not use!! + //QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themes/"; + //if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); } + //return LUtils::writeFile(localdir+name+".qss.template", contents, true); } bool LTHEME::saveLocalColors(QString name, QStringList contents){ - QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/colors/"; - if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); } - return LUtils::writeFile(localdir+name+".qss.colors", contents, true); + return false; //old format - do not use!! + // QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/colors/"; + //if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); } + //return LUtils::writeFile(localdir+name+".qss.colors", contents, true); } //Return the currently selected Theme/Colors/Icons @@ -181,22 +183,22 @@ QString LTHEME::currentCursor(){ //Change the current Theme/Colors/Icons bool LTHEME::setCurrentSettings(QString themepath, QString colorpath, QString iconname, QString font, QString fontsize){ //QIcon::setThemeName(iconname); + //Save these settings into the theme engine settings QSettings engineset("lthemeengine","lthemeengine"); engineset.setValue("Appearance/icon_theme", iconname); - //engineset.setValue("Appearance/color_scheme_path", colorpath); //re-enable this once the color scheme has been synced with lthemeengine - //Need to add theme path saving here too later - - + engineset.setValue("Appearance/custom_palette", QFile::exists(colorpath) ); + engineset.setValue("Appearance/color_scheme_path", colorpath); + engineset.setValue("Interface/desktop_stylesheets", QStringList() << themepath); + return true; //Now save the theme settings file - QStringList contents; + /*QStringList contents; contents << "THEMEFILE="+themepath; contents << "COLORFILE="+colorpath; contents << "ICONTHEME="+iconname; contents << "FONTFAMILY="+font; contents << "FONTSIZE="+fontsize; bool ok = LUtils::writeFile(QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themesettings.cfg", contents, true); - - return ok; + return ok;*/ } //Change the current Cursor Theme @@ -299,13 +301,13 @@ QStringList LTHEME::cursorInformation(QString name){ } } return out; -} +} QStringList LTHEME::CustomEnvSettings(bool useronly){ //view all the key=value settings QStringList newinfo; if(!useronly){ QStringList sysfiles; sysfiles << L_ETCDIR+"/lumina_environment.conf" << LOS::LuminaShare()+"lumina_environment.conf"; - for(int i=0; i%) ) diff --git a/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf b/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf index 1327f148..40ece4f0 100644 --- a/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf +++ b/src-qt5/core/lumina-desktop/defaults/luminaDesktop.conf @@ -51,7 +51,7 @@ mime_default_application/x-shellscript=lumina-textedit.desktop #THEME SETTINGS theme_themefile=DarkGlass #Name of the theme to use (disable for Lumina-Default) -theme_colorfile=Black #Name of the color spec file to use for theming +theme_colorfile=darker #Name of the color spec file to use for theming theme_iconset=material-design-dark #Name of the icon theme to use theme_font=Arial #Name of the font family to use theme_fontsize=10pt #Default size of the fonts to use on the desktop (can also use a percentage of the screen height (%) ) -- cgit From 3f9e6a1de6bcc9b35f88c0216cb7d50d0241b119 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 21 Sep 2017 15:10:03 -0400 Subject: Fix up the loading of the theme settings before the session is started in Lumina 1, and also fix the pkg plist so it includes the qss files. --- src-qt5/core/lumina-desktop/LSession.cpp | 5 +++-- src-qt5/core/lumina-desktop/LSession.h | 31 ++++++++++++++++--------------- src-qt5/core/lumina-desktop/main.cpp | 1 + 3 files changed, 20 insertions(+), 17 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index 2a1ec783..44f657c0 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -387,11 +387,12 @@ void LSession::checkWindowGeoms(){ void LSession::checkUserFiles(){ //internal version conversion examples: // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] - QString OVS = sessionsettings->value("DesktopVersion","0").toString(); //Old Version String + QSettings sset("lumina-desktop", "sessionsettings"); + QString OVS = sset.value("DesktopVersion","0").toString(); //Old Version String bool changed = LDesktopUtils::checkUserFiles(OVS); if(changed){ //Save the current version of the session to the settings file (for next time) - sessionsettings->setValue("DesktopVersion", this->applicationVersion()); + sset.setValue("DesktopVersion", LDesktopUtils::LuminaDesktopVersion()); } } diff --git a/src-qt5/core/lumina-desktop/LSession.h b/src-qt5/core/lumina-desktop/LSession.h index 0d69df84..43cddac7 100644 --- a/src-qt5/core/lumina-desktop/LSession.h +++ b/src-qt5/core/lumina-desktop/LSession.h @@ -39,7 +39,7 @@ #define SYSTEM_TRAY_CANCEL_MESSAGE 2 /*class MenuProxyStyle : public QProxyStyle{ -public: +public: int pixelMetric(PixelMetric metric, const QStyleOption *option=0, const QWidget *widget=0) const{ if(metric==PM_SmallIconSize){ return 22; } //override QMenu icon size (make it larger) else{ return QProxyStyle::pixelMetric(metric, option, widget); } //use the current style for everything else @@ -51,6 +51,8 @@ class LSession : public LSingleApplication{ public: LSession(int &argc, char **argv); ~LSession(); + + static void checkUserFiles(); //Functions to be called during startup void setupSession(); @@ -63,7 +65,7 @@ public: bool registerStartButton(QString ID); void unregisterStartButton(QString ID); - //Special functions for XCB event filter parsing only + //Special functions for XCB event filter parsing only // (DO NOT USE MANUALLY) void RootSizeChange(); void WindowPropertyEvent(); @@ -73,37 +75,37 @@ public: void WindowConfigureEvent(WId); void WindowDamageEvent(WId); void WindowSelectionClearEvent(WId); - + //System Access //Return a pointer to the current session static LSession* handle(){ return static_cast(LSession::instance()); } - + static void LaunchApplication(QString cmd); QFileInfoList DesktopFiles(); - + QRect screenGeom(int num); - + AppMenu* applicationMenu(); void systemWindow(); SettingsMenu* settingsMenu(); LXCB *XCB; //class for XCB usage - + QSettings* sessionSettings(); QSettings* DesktopPluginSettings(); - + //Keep track of which non-desktop window should be treated as active WId activeWindow(); //This will return the last active window if a desktop element is currently active - + //Temporarily change the session locale (nothing saved between sessions) void switchLocale(QString localeCode); - + //Play System Audio void playAudioFile(QString filepath); //Window Adjustment Routine (due to Fluxbox not respecting _NET_WM_STRUT) void adjustWindowGeom(WId win, bool maximize = false); - + private: //WMProcess *WM; QList DESKTOPS; @@ -136,9 +138,9 @@ private: QFileInfoList desktopFiles; void CleanupSession(); - + int VersionStringToNumber(QString version); - + public slots: void StartLogout(); void StartShutdown(bool skipupdates = false); @@ -161,7 +163,6 @@ private slots: void removeTrayWindow(WId); //Internal simplification functions - void checkUserFiles(); void refreshWindowManager(); void updateDesktops(); void registerDesktopWindows(); @@ -189,7 +190,7 @@ signals: void DesktopFilesChanged(); void MediaFilesChanged(); void WorkspaceChanged(); - + }; #endif diff --git a/src-qt5/core/lumina-desktop/main.cpp b/src-qt5/core/lumina-desktop/main.cpp index b2bfa9be..c272f263 100644 --- a/src-qt5/core/lumina-desktop/main.cpp +++ b/src-qt5/core/lumina-desktop/main.cpp @@ -76,6 +76,7 @@ int main(int argc, char ** argv) setenv("QT_QPA_PLATFORMTHEME", "lthemeengine", 1); unsetenv("QT_AUTO_SCREEN_SCALE_FACTOR"); //causes pixel-specific scaling issues with the desktop - turn this on after-the-fact for other apps //Startup the session + LSession::checkUserFiles(); //make sure to create any config files before creating the QApplication LSession a(argc, argv); if(!a.isPrimaryProcess()){ return 0; } //Setup the log file -- cgit From 56d7717d8181974dc3c5cb35eb2436668bf2c6ce Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 21 Sep 2017 15:13:36 -0400 Subject: Make sure we don't run the checkUserFiles() function a second time --- src-qt5/core/lumina-desktop/LSession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index 44f657c0..feb3c95c 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -120,7 +120,7 @@ void LSession::setupSession(){ //Setup the user's lumina settings directory as necessary splash.showScreen("user"); if(DEBUG){ qDebug() << " - Init User Files:" << timer->elapsed();} - checkUserFiles(); //adds these files to the watcher as well + //checkUserFiles(); //adds these files to the watcher as well //Initialize the internal variables DESKTOPS.clear(); -- cgit From ca75f41432756e1a2796c046787474514277012e Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 21 Sep 2017 15:23:09 -0400 Subject: Oops - need to make sure that status function does not access any global QApplication instance. --- src-qt5/core/libLumina/LDesktopUtils.cpp | 4 ++-- src-qt5/core/libLumina/LDesktopUtils.h | 2 +- src-qt5/core/lumina-desktop/LSession.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index 9b7ee6d0..6c0543c0 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -456,12 +456,12 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ } -bool LDesktopUtils::checkUserFiles(QString lastversion){ +bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ //internal version conversion examples: // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] //returns true if something changed int oldversion = LDesktopUtils::VersionStringToNumber(lastversion); - int nversion = LDesktopUtils::VersionStringToNumber(QApplication::applicationVersion()); + int nversion = LDesktopUtils::VersionStringToNumber(currentversion); bool newversion = ( oldversion < nversion ); //increasing version number bool newrelease = ( lastversion.contains("-devel", Qt::CaseInsensitive) && QApplication::applicationVersion().contains("-release", Qt::CaseInsensitive) ); //Moving from devel to release diff --git a/src-qt5/core/libLumina/LDesktopUtils.h b/src-qt5/core/libLumina/LDesktopUtils.h index a9b44c67..b0ce6ba5 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.h +++ b/src-qt5/core/libLumina/LDesktopUtils.h @@ -43,7 +43,7 @@ public: //Load the default setup for the system static void LoadSystemDefaults(bool skipOS = false); - static bool checkUserFiles(QString lastversion); //returns true if something changed + static bool checkUserFiles(QString lastversion, QString currentversion); //returns true if something changed static int VersionStringToNumber(QString version); //convert the lumina version string to a number for comparisons //Migrating desktop settings from one ID to another diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index feb3c95c..99b20194 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -389,7 +389,7 @@ void LSession::checkUserFiles(){ // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] QSettings sset("lumina-desktop", "sessionsettings"); QString OVS = sset.value("DesktopVersion","0").toString(); //Old Version String - bool changed = LDesktopUtils::checkUserFiles(OVS); + bool changed = LDesktopUtils::checkUserFiles(OVS, LDesktopUtils::LuminaDesktopVersion()); if(changed){ //Save the current version of the session to the settings file (for next time) sset.setValue("DesktopVersion", LDesktopUtils::LuminaDesktopVersion()); -- cgit From 836dd026ae707965df8faf556debfde7a007b5d1 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 21 Sep 2017 16:04:22 -0400 Subject: Quick fix to ensure the status checkUserFiles function truly is static --- src-qt5/core/libLumina/LDesktopUtils.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index 6c0543c0..a5c1bd77 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -481,7 +481,10 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ //Convert from the old desktop numbering system to the new one (change occured with 1.0.1) if(oldversion<=1000001){ QStringList DS = LUtils::readFile(dset); - QList screens = QApplication::screens(); + char *tmp; + int tmpN = 0; + QApplication A(tmpN, &tmp); + QList screens = A.screens(); for(int i=0; i Date: Thu, 21 Sep 2017 16:13:28 -0400 Subject: Urg - more fixes... --- src-qt5/core/libLumina/LDesktopUtils.cpp | 6 +++--- src-qt5/core/lumina-desktop/LSession.cpp | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index a5c1bd77..262bf47b 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -155,8 +155,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ if(sysDefaults.isEmpty()){ sysDefaults = LUtils::readFile(LOS::LuminaShare()+"luminaDesktop.conf"); } //Find the number of the left-most desktop screen QString screen = "0"; - QDesktopWidget *desk =QApplication::desktop(); QRect screenGeom; + QDesktopWidget *desk =QApplication::desktop(); for(int i=0; iscreenCount(); i++){ if(desk->screenGeometry(i).x()==0){ screen = QString::number(i); @@ -479,7 +479,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ LDesktopUtils::upgradeFavorites(oldversion); } //Convert from the old desktop numbering system to the new one (change occured with 1.0.1) - if(oldversion<=1000001){ + /*if(oldversion<=1000001){ QStringList DS = LUtils::readFile(dset); char *tmp; int tmpN = 0; @@ -505,7 +505,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ } } LUtils::writeFile(dset, DS, true); - } + }*/ //Check the fluxbox configuration files dset = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/"; diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index 99b20194..d1d6588e 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -389,6 +389,9 @@ void LSession::checkUserFiles(){ // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] QSettings sset("lumina-desktop", "sessionsettings"); QString OVS = sset.value("DesktopVersion","0").toString(); //Old Version String + char *tmp; + int tmpN = 0; + QApplication A(tmpN, &tmp); bool changed = LDesktopUtils::checkUserFiles(OVS, LDesktopUtils::LuminaDesktopVersion()); if(changed){ //Save the current version of the session to the settings file (for next time) -- cgit From a27815312eaac620881d67e8776c743595975b38 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 21 Sep 2017 16:15:49 -0400 Subject: Final fix - re-enable some backwards-compatible code and put a big warning at the top of the function --- src-qt5/core/libLumina/LDesktopUtils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index 262bf47b..fb13a2a3 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -457,6 +457,8 @@ void LDesktopUtils::LoadSystemDefaults(bool skipOS){ } bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ + //WARNING: Make sure you create a QApplication instance before calling this function!!! + //internal version conversion examples: // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] //returns true if something changed @@ -479,7 +481,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ LDesktopUtils::upgradeFavorites(oldversion); } //Convert from the old desktop numbering system to the new one (change occured with 1.0.1) - /*if(oldversion<=1000001){ + if(oldversion<=1000001){ QStringList DS = LUtils::readFile(dset); char *tmp; int tmpN = 0; @@ -505,7 +507,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ } } LUtils::writeFile(dset, DS, true); - }*/ + } //Check the fluxbox configuration files dset = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/"; -- cgit From a3092fb02a1905345e1311b2e64f4796acdb9f34 Mon Sep 17 00:00:00 2001 From: q5sys Date: Sun, 24 Sep 2017 19:58:16 -0400 Subject: rework video thumbnail code --- .../desktop-utils/lumina-fm/widgets/vidnail.cpp | 33 ++++++++++++++++++++++ src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h | 25 ++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp create mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp new file mode 100644 index 00000000..ee7fb9e3 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp @@ -0,0 +1,33 @@ +#include "vidnail.h" +vidnail::vidnail(QWidget *parent) : QMainWindow(parent), mplayer(parent, QMediaPlayer::VideoSurface){ //there is no UI, so not sure how to alter the constructor +} + +vidnail::~vidnail() +{ + +vidnail::grabvideothumbnail(){ + vsurface = new QAbstractVideoSurface(); + mplayer.setVideoOutput(vsurface); + mplayer.setMedia($file); // video file to get thumbnail of + imageCaptured = QPixmap(); + mplayer.setPosition(2000); // time in milliseconds + mplayer.setMuted(true); // just to make sure no sound is emited + mplayer.play(); + + currentFrame = frame; + const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); + const QSize size = format.frameSize(); + + this->imageFormat = imageFormat; + QAbstractVideoSurface::start(format); + QImage image( currentFrame.bits(), currentFrame.width(), currentFrame.height(), currentFrame.bytesPerLine(), imageFormat); + imageCaptured = QPixmap::fromImage(image.copy(image.rect())); + +// Now do scaling with regular thumbnail process to make proper size + + mplayer.stop(); + vsurface.stop(); +} + + + diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h new file mode 100644 index 00000000..ad565749 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h @@ -0,0 +1,25 @@ +#ifndef VIDNAIL_H +#define VIDNAIL_H + +#include +#include +#include "videowidgetsurface.h" +#include +#include +#include +#include +#include + +public: + + void grabvideothumbnail(); + +private: + + QAbstractVideoSurface *vsurface; + QImage::Format imageFormat; + QPixmap imageCaptured; + + +#endif // VIDNAIL_H + -- cgit From e92185222ea652436d0f5a36de25cbbd66347ea1 Mon Sep 17 00:00:00 2001 From: q5sys Date: Sun, 24 Sep 2017 20:25:21 -0400 Subject: prototype webdav functionality for lumina-fm --- .../desktop-utils/lumina-fm/widgets/fmwebdav.cpp | 23 ++++++++++++++ src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.h | 36 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp create mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.h (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp new file mode 100644 index 00000000..9c82aa3e --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp @@ -0,0 +1,23 @@ +#include "fmwebdav.h" + +fmwebdav::fmwebdav(QObject *parent) : QNetworkAccessManager(parent) ,wdRootPath(), wdUsername(), wdUassword(), wdBaseUrl(), wdCurrentConnectionType(QWebdav::HTTP){ +// typical Qnetwork connection stuff goes here +// probably ssl parts too +} + +fmwebdav::~fmwebdav(){ +} + +QString fmwebdav::hostname() const{ return wdBaseUrl.host(); } + +int fmwebdav::port() const{ return wdBaseUrl.port(); } + +QString fmwebdav::rootPath() const{ return wdRootPath;} + +QString fmwebdav::username() const{ return wdUsername; } + +QString fmwebdav::password() const{ return wdPassword; } + +fmwebdav::QWebdavConnectionType : fmwebdav::connectionType() const{ return wdCurrentConnectionType; } + +bool fmwebdav::isSSL() const{ return (wdCurrentConnectionType==QWebdav::HTTPS); } diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.h b/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.h new file mode 100644 index 00000000..04d29e3b --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.h @@ -0,0 +1,36 @@ +#ifndef FMWEBDAV_H +#define FMWEBDAV_H + +#include +#include +#include + +public: + + enum QWebdavConnectionType {HTTP = 1, HTTPS}; + + QString hostname() const; + int port() const; + QString rootPath() const; + QString username() const; + QString password() const; + QWebdavConnectionType connectionType() const; + bool isSSL() const; + + void setConnectionSettings( const QWebdavConnectionType connectionType, const QString *hostname, const QString *rootPath = "/", const QString *username = "", const QString *password = "", int *port = 0; + + +private: + + QString wdRootPath; + QString wdUsername; + QString wdPassword; + QUrl wdBaseUrl; + QWebdavConnectionType wdCurrentConnectionType; + + + + + + +#endif // FMWEBDAV -- cgit From fb13a95bcb1c88028e74a525c998d419984c3b28 Mon Sep 17 00:00:00 2001 From: q5sys Date: Sun, 24 Sep 2017 20:33:20 -0400 Subject: oops hadn't saved all my changes yet --- src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp index 9c82aa3e..6e65ebaf 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/fmwebdav.cpp @@ -21,3 +21,16 @@ QString fmwebdav::password() const{ return wdPassword; } fmwebdav::QWebdavConnectionType : fmwebdav::connectionType() const{ return wdCurrentConnectionType; } bool fmwebdav::isSSL() const{ return (wdCurrentConnectionType==QWebdav::HTTPS); } + +void QWebdav::setConnectionSettings(const QWebdavConnectionType connectionType, const QString *hostname, const QString *rootPath, const QString *username, const QString *password, int *port){ + wdRootPath = rootPath; + if ((wdRootPath.endsWith("/")){ wdRootPath.chop(1); } + wdCurrentConnectionType = connectionType; + wdBaseUrl.setScheme(); + wdBaseUrl.setHost(hostname); + wdBaseUrl.setPath(rootPath); + if (port != 0) { // use user-defined port number if not 80 or 443 + if ( ! ( ( (port == 80) && (wdCurrentConnectionType==QWebdav::HTTP) ) || ( (port == 443) && (wdCurrentConnectionType==QWebdav::HTTPS) ) ) ){ wdBaseUrl.setPort(port); } + wdUsername = username; + wdPassword = password; +} -- cgit From bf7e372df336263ccdc9d0ab22554fb1ff6f629a Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 26 Sep 2017 13:42:19 -0400 Subject: Add a bunch of new files specifically for providing a new OpenGL-backed basis for doing visuals within Qt/Lumina. --- src-qt5/src-glwidgets/gltest/colorchange.h | 35 +++++++++++++ src-qt5/src-glwidgets/gltest/main.cpp | 26 ++++++++++ src-qt5/src-glwidgets/gltest/test | Bin 0 -> 50927 bytes src-qt5/src-glwidgets/gltest/test.pro | 9 ++++ src-qt5/src-glwidgets/glw-base.cpp | 63 ++++++++++++++++++++++++ src-qt5/src-glwidgets/glw-base.h | 43 ++++++++++++++++ src-qt5/src-glwidgets/glw-widget.cpp | 76 +++++++++++++++++++++++++++++ src-qt5/src-glwidgets/glw-widget.h | 50 +++++++++++++++++++ src-qt5/src-glwidgets/glwidgets.pri | 7 +++ 9 files changed, 309 insertions(+) create mode 100644 src-qt5/src-glwidgets/gltest/colorchange.h create mode 100644 src-qt5/src-glwidgets/gltest/main.cpp create mode 100755 src-qt5/src-glwidgets/gltest/test create mode 100644 src-qt5/src-glwidgets/gltest/test.pro create mode 100644 src-qt5/src-glwidgets/glw-base.cpp create mode 100644 src-qt5/src-glwidgets/glw-base.h create mode 100644 src-qt5/src-glwidgets/glw-widget.cpp create mode 100644 src-qt5/src-glwidgets/glw-widget.h create mode 100644 src-qt5/src-glwidgets/glwidgets.pri (limited to 'src-qt5') diff --git a/src-qt5/src-glwidgets/gltest/colorchange.h b/src-qt5/src-glwidgets/gltest/colorchange.h new file mode 100644 index 00000000..d62fcd5c --- /dev/null +++ b/src-qt5/src-glwidgets/gltest/colorchange.h @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +#include "../glw-base.h" + +class colorchange : public QObject{ + Q_OBJECT +private: + GLW_Base *base; + QTimer *timer; + +public slots: + void toggle(){ + static int current = 0; + if(current==0){ + base->setBackgroundColor(QColor(Qt::red)); + }else{ + base->setBackgroundColor(QColor(Qt::blue)); + current = -1; + } + current++; + } + +public: + colorchange(GLW_Base *parent) : QObject(){ + base = parent; + timer = new QTimer(this); + timer->setInterval(5000); + connect(timer, SIGNAL(timeout()), this, SLOT(toggle()) ); + timer->start(); + } + +}; diff --git a/src-qt5/src-glwidgets/gltest/main.cpp b/src-qt5/src-glwidgets/gltest/main.cpp new file mode 100644 index 00000000..041ee5ff --- /dev/null +++ b/src-qt5/src-glwidgets/gltest/main.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +#include "../glw-base.h" +#include "../glw-widget.h" + +#include "colorchange.h" + +int main(int argc, char** argv){ + QApplication A(argc,argv); + qDebug() << "Creating base widget"; + GLW_Base base; + qDebug() << "Resize base widget"; + base.resize(200,200); + qDebug() << "Create colorchange"; + GLW_Widget wgt(&base); + wgt.setGLBase(&base); + wgt.setGeometry(50,50,50,50); + colorchange CC(&base); + qDebug() << "Start Event loop"; + base.show(); + A.exec(); + qDebug() << " - Finished"; +} diff --git a/src-qt5/src-glwidgets/gltest/test b/src-qt5/src-glwidgets/gltest/test new file mode 100755 index 00000000..5a69b0c3 Binary files /dev/null and b/src-qt5/src-glwidgets/gltest/test differ diff --git a/src-qt5/src-glwidgets/gltest/test.pro b/src-qt5/src-glwidgets/gltest/test.pro new file mode 100644 index 00000000..cba315c3 --- /dev/null +++ b/src-qt5/src-glwidgets/gltest/test.pro @@ -0,0 +1,9 @@ +QT = core gui widgets + +TARGET = test + +SOURCES += main.cpp + +HEADERS += colorchange.h + +include(../glwidgets.pri); diff --git a/src-qt5/src-glwidgets/glw-base.cpp b/src-qt5/src-glwidgets/glw-base.cpp new file mode 100644 index 00000000..e828df7f --- /dev/null +++ b/src-qt5/src-glwidgets/glw-base.cpp @@ -0,0 +1,63 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "glw-base.h" +#include "glw-widget.h" + +GLW_Base::GLW_Base(QWidget *parent, Qt::WindowFlags f) : QOpenGLWidget(parent,f){ + bg_color = QColor(Qt::black); +} + +GLW_Base::~GLW_Base(){ + +} + +// --- PUBLIC SLOTS --- +void GLW_Base::setBackgroundColor(QColor color){ + bg_color = color; + this->update(); //repaint the entire widget (just in case you can see through the image) + +} + +void GLW_Base::setBackground(QRect geom, QImage img){ + QPainter P(&bg_img); + P.drawImage(geom, img); + this->update(); +} + +void GLW_Base::repaintArea(QRect rect){ + paintEvent(new QPaintEvent(rect)); +} + +// --- PROTECTED --- +void GLW_Base::resizeEvent(QResizeEvent *ev){ + QOpenGLWidget::resizeEvent(ev); + if(!bg_img.isNull()){ + bg_img = bg_img.scaled(ev->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + emit BaseResized(); +} + +void GLW_Base::paintEvent(QPaintEvent *ev){ + QStylePainter painter(this); + painter.setClipRegion(ev->rect()); + //Fill in the background color first + painter.fillRect(ev->rect(), bg_color); + //Now paint any background image over that + painter.drawImage(ev->rect(), bg_img, ev->rect(), Qt::AutoColor | Qt::PreferDither | Qt::NoOpaqueDetection); + //Now find any children widgets and paint them if they are in that area + QObjectList child = this->children(); //Note: This is returned in stacking order (lowest -> highest) + for(int i=0; iisWidgetType() ){ continue; } //not a widget + GLW_Widget *glww = qobject_cast(child[i]); + if(glww!=0){ + if(ev->rect().contains(glww->widgetRect())){ + glww->paintYourself(&painter, ev); + glww->paintChildren(&painter,ev); + } + } + } +} diff --git a/src-qt5/src-glwidgets/glw-base.h b/src-qt5/src-glwidgets/glw-base.h new file mode 100644 index 00000000..729aa68e --- /dev/null +++ b/src-qt5/src-glwidgets/glw-base.h @@ -0,0 +1,43 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_OPENGL_WIDGETS_BASE_H +#define _LUMINA_OPENGL_WIDGETS_BASE_H + +#include +#include +#include +#include +#include +#include + +class GLW_Base : public QOpenGLWidget{ + Q_OBJECT +private: + QColor bg_color; + QImage bg_img; + +public: + GLW_Base(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + ~GLW_Base(); + + +private slots: + +public slots: + void setBackgroundColor(QColor color); + void setBackground(QRect geom, QImage img); + void repaintArea(QRect); + +signals: + void BaseResized(); + +protected: + void resizeEvent(QResizeEvent *ev); + void paintEvent(QPaintEvent *ev); +}; + +#endif diff --git a/src-qt5/src-glwidgets/glw-widget.cpp b/src-qt5/src-glwidgets/glw-widget.cpp new file mode 100644 index 00000000..e24d8166 --- /dev/null +++ b/src-qt5/src-glwidgets/glw-widget.cpp @@ -0,0 +1,76 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "glw-widget.h" +#include + +// --- PUBLIC --- +GLW_Widget::GLW_Widget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f){ + glw_base = 0; + this->setMouseTracking(true); +} + +GLW_Widget::~GLW_Widget(){ + +} + +QRect GLW_Widget::widgetRect(){ + QPoint pos = this->mapTo(glw_base, QPoint(0,0)); + return QRect(pos, this->size()); +} + +bool GLW_Widget::mouseOverWidget(){ + QPoint pos = this->mapFromGlobal(QCursor::pos()); + QRect geom(QPoint(0,0), this->size()); + return geom.contains(pos); + +} + +void GLW_Widget::setGLBase(GLW_Base *base){ + if(glw_base!=0){ this->disconnect(glw_base, SLOT(repaintArea(QRect))); } + glw_base=base; + connect(this, SIGNAL(repaintArea(QRect)), glw_base, SLOT(repaintArea(QRect)) ); +} + +void GLW_Widget::paintYourself(QStylePainter *painter, QPaintEvent *ev){ + QRect rect = widgetRect(); + rect = rect.intersected(ev->rect()); + QColor color( mouseOverWidget() ? Qt::gray : Qt::yellow); + color.setAlpha(125); + painter->fillRect(rect, color); +} + +void GLW_Widget::paintChildren(QStylePainter *painter, QPaintEvent *ev){ + QObjectList child = this->children(); //Note: This is returned in stacking order (lowest -> highest) + for(int i=0; iisWidgetType() ){ continue; } //not a widget + GLW_Widget *glww = qobject_cast(child[i]); + if(glww!=0){ + if(ev->rect().contains(glww->widgetRect())){ + glww->paintYourself(painter, ev); + glww->paintChildren(painter,ev); + } + } + } +} + + +// --- PROTECTED --- +void GLW_Widget::resizeEvent(QResizeEvent *ev){ + if(glw_base==0){ return; } + QPoint pos = this->mapTo(glw_base, QPoint(0,0)); + QSize sz = ev->oldSize(); + if(ev->size().width() > sz.width()){ sz.setWidth(ev->size().width()); } + if(ev->size().height() > sz.height()){ sz.setHeight(ev->size().height()); } + emit repaintArea(QRect(pos, sz)); +} + +void GLW_Widget::paintEvent(QPaintEvent *ev){ + //qDebug() << "Got paint event:" << ev->rect(); + QPoint pos = this->mapTo(glw_base, ev->rect().topLeft()); + emit repaintArea(QRect(pos, ev->rect().size()) ); + return; +} diff --git a/src-qt5/src-glwidgets/glw-widget.h b/src-qt5/src-glwidgets/glw-widget.h new file mode 100644 index 00000000..1d6caa77 --- /dev/null +++ b/src-qt5/src-glwidgets/glw-widget.h @@ -0,0 +1,50 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_OPENGL_WIDGETS_WIDGET_H +#define _LUMINA_OPENGL_WIDGETS_WIDGET_H + +#include +#include +#include +#include +#include + +#include "glw-base.h" + +class GLW_Widget : public QWidget{ + Q_OBJECT +private: + GLW_Base *glw_base; + +public: + GLW_Widget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); + ~GLW_Widget(); + + QRect widgetRect(); //converts to the coordinate scheme of the base widget + bool mouseOverWidget(); + + void setGLBase(GLW_Base *base); + + virtual void paintYourself(QStylePainter *painter, QPaintEvent *ev); + void paintChildren(QStylePainter *painter, QPaintEvent *ev); + +private slots: + +public slots: + +protected: + void enterEvent(QEvent*){ this->update(); } + void leaveEvent(QEvent*){ this->update(); } + void resizeEvent(QResizeEvent *ev); + void paintEvent(QPaintEvent *ev); + +signals: + void repaintArea(QRect); +}; + +Q_DECLARE_INTERFACE(GLW_Widget, "GLW_Widget"); +#endif diff --git a/src-qt5/src-glwidgets/glwidgets.pri b/src-qt5/src-glwidgets/glwidgets.pri new file mode 100644 index 00000000..e391aef0 --- /dev/null +++ b/src-qt5/src-glwidgets/glwidgets.pri @@ -0,0 +1,7 @@ +QT *= widgets + +SOURCES *= $${PWD}/glw-base.cpp \ + $${PWD}/glw-widget.cpp + +HEADERS *= $${PWD}/glw-base.h \ + $${PWD}/glw-widget.h -- cgit From ebdfec8604b7cf308475c8907d9e70e6b13aeed9 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 26 Sep 2017 14:03:24 -0400 Subject: Fix up the close event handling in lumina-textedit. Now it will actually close when there are no changes to be saved. --- src-qt5/desktop-utils/lumina-textedit/MainUI.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp index 4c2ce0bd..9e4ce499 100644 --- a/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/MainUI.cpp @@ -496,11 +496,14 @@ void MainUI::closeEvent(QCloseEvent *ev){ unsaved << tmp->currentFile(); } } - bool savenow = unsaved.isEmpty(); + if(unsaved.isEmpty()){ QMainWindow::closeEvent(ev); return; } + bool savenow = false; if(!savenow && !ui->actionShow_Popups->isChecked()){ savenow = true; } if(!savenow){ - savenow = (QMessageBox::Yes == QMessageBox::question(this, tr("Save Changes before closing?"), QString(tr("There are unsaved changes.\nDo you want save them before you close the editor?\n\n%1")).arg(unsaved.join("\n")), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ); + QMessageBox::StandardButton but = QMessageBox::question(this, tr("Save Changes before closing?"), QString(tr("There are unsaved changes.\nDo you want save them before you close the editor?\n\n%1")).arg(unsaved.join("\n")), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No); + savenow = (but == QMessageBox::Yes); + if(but == QMessageBox::Cancel){ ev->ignore(); return; } } - if(!savenow){ QMainWindow::closeEvent(ev); } - else{ ev->ignore(); SaveFile(); } + if(savenow){ SaveFile(); } + QMainWindow::closeEvent(ev); } -- cgit From 04069af07a667fb6b677f1655978853c42410b2f Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 26 Sep 2017 23:18:34 -0400 Subject: Update some more of the GL widget set and the test Get the generic widget draggable (optional). Verify that QPropertyAnimations work property on widgets in the test. --- src-qt5/src-glwidgets/gltest/main.cpp | 25 ++++++++++++++++++++--- src-qt5/src-glwidgets/gltest/test | Bin 50927 -> 56367 bytes src-qt5/src-glwidgets/glw-base.cpp | 7 +++++-- src-qt5/src-glwidgets/glw-widget.cpp | 36 ++++++++++++++++++++++++++++++++-- src-qt5/src-glwidgets/glw-widget.h | 21 ++++++++++++++++---- 5 files changed, 78 insertions(+), 11 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/src-glwidgets/gltest/main.cpp b/src-qt5/src-glwidgets/gltest/main.cpp index 041ee5ff..c3edd088 100644 --- a/src-qt5/src-glwidgets/gltest/main.cpp +++ b/src-qt5/src-glwidgets/gltest/main.cpp @@ -2,7 +2,8 @@ #include #include #include - +#include +#include #include "../glw-base.h" #include "../glw-widget.h" @@ -14,10 +15,28 @@ int main(int argc, char** argv){ GLW_Base base; qDebug() << "Resize base widget"; base.resize(200,200); - qDebug() << "Create colorchange"; + qDebug() << "Create Other widgets"; + GLW_Widget wgt1(&base); + wgt1.setGLBase(&base); + wgt1.setGeometry(50,50,50,50); + wgt1.setDraggable(true); GLW_Widget wgt(&base); wgt.setGLBase(&base); - wgt.setGeometry(50,50,50,50); + wgt.setGeometry(75,50,50,50); + QPropertyAnimation anim(&wgt); + anim.setTargetObject(&wgt); + anim.setPropertyName("geometry"); + //anim.setStartValue(QRect(-50,-50,50,50)); + //anim.setEndValue(QRect(200,200,50,50)); + anim.setStartValue(QRect(100,100,0,0)); + anim.setEndValue(QRect(0,0,200,200)); + anim.setDuration(1500); + anim.setLoopCount(-1); + anim.start(); + /*QPushButton but(&base); + but.setText("button"); + but.setGeometry(100,100,50,50); + but.setStyleSheet("background: rgba(0,150,0,125)");*/ colorchange CC(&base); qDebug() << "Start Event loop"; base.show(); diff --git a/src-qt5/src-glwidgets/gltest/test b/src-qt5/src-glwidgets/gltest/test index 5a69b0c3..cb8fe872 100755 Binary files a/src-qt5/src-glwidgets/gltest/test and b/src-qt5/src-glwidgets/gltest/test differ diff --git a/src-qt5/src-glwidgets/glw-base.cpp b/src-qt5/src-glwidgets/glw-base.cpp index e828df7f..8841743d 100644 --- a/src-qt5/src-glwidgets/glw-base.cpp +++ b/src-qt5/src-glwidgets/glw-base.cpp @@ -54,10 +54,13 @@ void GLW_Base::paintEvent(QPaintEvent *ev){ if( !child[i]->isWidgetType() ){ continue; } //not a widget GLW_Widget *glww = qobject_cast(child[i]); if(glww!=0){ - if(ev->rect().contains(glww->widgetRect())){ + if(!ev->rect().intersected(glww->widgetRect()).isNull()){ glww->paintYourself(&painter, ev); glww->paintChildren(&painter,ev); } - } + }/*else{ + QWidget *widg = qobject_cast(child[i]); + widg->render(&painter, widg->geometry().topLeft()); + }*/ } } diff --git a/src-qt5/src-glwidgets/glw-widget.cpp b/src-qt5/src-glwidgets/glw-widget.cpp index e24d8166..d07c0431 100644 --- a/src-qt5/src-glwidgets/glw-widget.cpp +++ b/src-qt5/src-glwidgets/glw-widget.cpp @@ -11,6 +11,8 @@ GLW_Widget::GLW_Widget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f){ glw_base = 0; this->setMouseTracking(true); + draggable = false; + drag_offset = QPoint(); } GLW_Widget::~GLW_Widget(){ @@ -25,7 +27,7 @@ QRect GLW_Widget::widgetRect(){ bool GLW_Widget::mouseOverWidget(){ QPoint pos = this->mapFromGlobal(QCursor::pos()); QRect geom(QPoint(0,0), this->size()); - return geom.contains(pos); + return geom.contains(pos) || (draggable && !drag_offset.isNull()); } @@ -39,7 +41,9 @@ void GLW_Widget::paintYourself(QStylePainter *painter, QPaintEvent *ev){ QRect rect = widgetRect(); rect = rect.intersected(ev->rect()); QColor color( mouseOverWidget() ? Qt::gray : Qt::yellow); - color.setAlpha(125); + //if(this->windowOpacity()!=1.0){ qDebug() << "Opacity:" << this->windowOpacity(); } + //color.setAlpha( qRound(this->windowOpacity()*255) ); + color.setAlpha( 125); painter->fillRect(rect, color); } @@ -59,6 +63,34 @@ void GLW_Widget::paintChildren(QStylePainter *painter, QPaintEvent *ev){ // --- PROTECTED --- +void GLW_Widget::mousePressEvent(QMouseEvent *ev){ + if(!draggable){ QWidget::mousePressEvent(ev); return; } + if(ev->button()==Qt::LeftButton){ + drag_offset = ev->pos(); + } +} + +void GLW_Widget::mouseReleaseEvent(QMouseEvent *ev){ + if(!draggable){ QWidget::mouseReleaseEvent(ev); return; } + if(ev->button()==Qt::LeftButton){ + if(drag_offset!=ev->pos()){ emit doneDragging(); } + drag_offset = QPoint(); } //reset offset +} + +void GLW_Widget::mouseMoveEvent(QMouseEvent *ev){ + if(!draggable){ QWidget::mouseMoveEvent(ev); return; } + if(!drag_offset.isNull()){ + this->move( this->mapTo(glw_base, ev->pos()-drag_offset) ); + } +} + + +void GLW_Widget::moveEvent(QMoveEvent *ev){ + QRect oldgeom = QRect(ev->oldPos(), this->size()); + QRect newgeom = QRect(ev->pos(), this->size()); + emit repaintArea( oldgeom.united(newgeom) ); +} + void GLW_Widget::resizeEvent(QResizeEvent *ev){ if(glw_base==0){ return; } QPoint pos = this->mapTo(glw_base, QPoint(0,0)); diff --git a/src-qt5/src-glwidgets/glw-widget.h b/src-qt5/src-glwidgets/glw-widget.h index 1d6caa77..91a1ae69 100644 --- a/src-qt5/src-glwidgets/glw-widget.h +++ b/src-qt5/src-glwidgets/glw-widget.h @@ -19,6 +19,8 @@ class GLW_Widget : public QWidget{ Q_OBJECT private: GLW_Base *glw_base; + QPoint drag_offset; + bool draggable; public: GLW_Widget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); @@ -32,18 +34,29 @@ public: virtual void paintYourself(QStylePainter *painter, QPaintEvent *ev); void paintChildren(QStylePainter *painter, QPaintEvent *ev); + //Properties + bool isDraggable(){ return draggable; } + private slots: public slots: + void setDraggable(bool drag){ draggable = drag; } + protected: - void enterEvent(QEvent*){ this->update(); } - void leaveEvent(QEvent*){ this->update(); } - void resizeEvent(QResizeEvent *ev); - void paintEvent(QPaintEvent *ev); + virtual void enterEvent(QEvent*){ this->update(); } + virtual void leaveEvent(QEvent*){ this->update(); } + + virtual void mousePressEvent(QMouseEvent *ev); + virtual void mouseReleaseEvent(QMouseEvent *ev); + virtual void mouseMoveEvent(QMouseEvent *ev); + virtual void moveEvent(QMoveEvent *ev); + virtual void resizeEvent(QResizeEvent *ev); + virtual void paintEvent(QPaintEvent *ev); signals: void repaintArea(QRect); + void doneDragging(); }; Q_DECLARE_INTERFACE(GLW_Widget, "GLW_Widget"); -- cgit From 823e3aa950cf52eb4902a70e606f073af3c92795 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 26 Sep 2017 23:50:24 -0400 Subject: More updates for the GL widget set. Now all the mouse tracking/hovering is working - with one exception: All the mouse hover detection is based around mouse **movement** - so programmatic changes to a window will not detect the change in what is directly under the mouse without manual intervention in the code. --- src-qt5/src-glwidgets/gltest/main.cpp | 2 +- src-qt5/src-glwidgets/gltest/test | Bin 56367 -> 58021 bytes src-qt5/src-glwidgets/glw-base.cpp | 14 ++++++++++++++ src-qt5/src-glwidgets/glw-base.h | 4 ++++ src-qt5/src-glwidgets/glw-widget.cpp | 17 ++++++++++++----- src-qt5/src-glwidgets/glw-widget.h | 4 ++-- 6 files changed, 33 insertions(+), 8 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/src-glwidgets/gltest/main.cpp b/src-qt5/src-glwidgets/gltest/main.cpp index c3edd088..972c4225 100644 --- a/src-qt5/src-glwidgets/gltest/main.cpp +++ b/src-qt5/src-glwidgets/gltest/main.cpp @@ -32,7 +32,7 @@ int main(int argc, char** argv){ anim.setEndValue(QRect(0,0,200,200)); anim.setDuration(1500); anim.setLoopCount(-1); - anim.start(); + //anim.start(); /*QPushButton but(&base); but.setText("button"); but.setGeometry(100,100,50,50); diff --git a/src-qt5/src-glwidgets/gltest/test b/src-qt5/src-glwidgets/gltest/test index cb8fe872..cf9d2c31 100755 Binary files a/src-qt5/src-glwidgets/gltest/test and b/src-qt5/src-glwidgets/gltest/test differ diff --git a/src-qt5/src-glwidgets/glw-base.cpp b/src-qt5/src-glwidgets/glw-base.cpp index 8841743d..d4279c61 100644 --- a/src-qt5/src-glwidgets/glw-base.cpp +++ b/src-qt5/src-glwidgets/glw-base.cpp @@ -9,12 +9,17 @@ GLW_Base::GLW_Base(QWidget *parent, Qt::WindowFlags f) : QOpenGLWidget(parent,f){ bg_color = QColor(Qt::black); + mouse_over_child = 0; } GLW_Base::~GLW_Base(){ } +QWidget * GLW_Base::mouseOverWidget(){ + return mouse_over_child; +} + // --- PUBLIC SLOTS --- void GLW_Base::setBackgroundColor(QColor color){ bg_color = color; @@ -32,7 +37,16 @@ void GLW_Base::repaintArea(QRect rect){ paintEvent(new QPaintEvent(rect)); } +void GLW_Base::setMouseOverWidget(QWidget *child){ + mouse_over_child = child; +} + // --- PROTECTED --- +void GLW_Base::mouseMoveEvent(QMouseEvent *ev){ + mouse_over_child = 0; //reset this flag - mouse is over the base right now + QWidget::mouseMoveEvent(ev); +} + void GLW_Base::resizeEvent(QResizeEvent *ev){ QOpenGLWidget::resizeEvent(ev); if(!bg_img.isNull()){ diff --git a/src-qt5/src-glwidgets/glw-base.h b/src-qt5/src-glwidgets/glw-base.h index 729aa68e..3c3d1d4e 100644 --- a/src-qt5/src-glwidgets/glw-base.h +++ b/src-qt5/src-glwidgets/glw-base.h @@ -19,11 +19,13 @@ class GLW_Base : public QOpenGLWidget{ private: QColor bg_color; QImage bg_img; + QWidget *mouse_over_child; public: GLW_Base(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); ~GLW_Base(); + QWidget * mouseOverWidget(); private slots: @@ -31,11 +33,13 @@ public slots: void setBackgroundColor(QColor color); void setBackground(QRect geom, QImage img); void repaintArea(QRect); + void setMouseOverWidget(QWidget*); signals: void BaseResized(); protected: + void mouseMoveEvent(QMouseEvent *ev); void resizeEvent(QResizeEvent *ev); void paintEvent(QPaintEvent *ev); }; diff --git a/src-qt5/src-glwidgets/glw-widget.cpp b/src-qt5/src-glwidgets/glw-widget.cpp index d07c0431..e6c98d74 100644 --- a/src-qt5/src-glwidgets/glw-widget.cpp +++ b/src-qt5/src-glwidgets/glw-widget.cpp @@ -10,7 +10,6 @@ // --- PUBLIC --- GLW_Widget::GLW_Widget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f){ glw_base = 0; - this->setMouseTracking(true); draggable = false; drag_offset = QPoint(); } @@ -25,10 +24,7 @@ QRect GLW_Widget::widgetRect(){ } bool GLW_Widget::mouseOverWidget(){ - QPoint pos = this->mapFromGlobal(QCursor::pos()); - QRect geom(QPoint(0,0), this->size()); - return geom.contains(pos) || (draggable && !drag_offset.isNull()); - + return (glw_base->mouseOverWidget()==this); } void GLW_Widget::setGLBase(GLW_Base *base){ @@ -63,6 +59,16 @@ void GLW_Widget::paintChildren(QStylePainter *painter, QPaintEvent *ev){ // --- PROTECTED --- +void GLW_Widget::enterEvent(QEvent*){ + if(!mouseOverWidget()){ glw_base->setMouseOverWidget(this); } + this->update(); +} + +void GLW_Widget::leaveEvent(QEvent*){ + if(mouseOverWidget()){ glw_base->setMouseOverWidget(0); } + this->update(); +} + void GLW_Widget::mousePressEvent(QMouseEvent *ev){ if(!draggable){ QWidget::mousePressEvent(ev); return; } if(ev->button()==Qt::LeftButton){ @@ -78,6 +84,7 @@ void GLW_Widget::mouseReleaseEvent(QMouseEvent *ev){ } void GLW_Widget::mouseMoveEvent(QMouseEvent *ev){ + if(!mouseOverWidget()){ glw_base->setMouseOverWidget(this); } if(!draggable){ QWidget::mouseMoveEvent(ev); return; } if(!drag_offset.isNull()){ this->move( this->mapTo(glw_base, ev->pos()-drag_offset) ); diff --git a/src-qt5/src-glwidgets/glw-widget.h b/src-qt5/src-glwidgets/glw-widget.h index 91a1ae69..e4d7aa37 100644 --- a/src-qt5/src-glwidgets/glw-widget.h +++ b/src-qt5/src-glwidgets/glw-widget.h @@ -44,8 +44,8 @@ public slots: protected: - virtual void enterEvent(QEvent*){ this->update(); } - virtual void leaveEvent(QEvent*){ this->update(); } + virtual void enterEvent(QEvent*); + virtual void leaveEvent(QEvent*); virtual void mousePressEvent(QMouseEvent *ev); virtual void mouseReleaseEvent(QMouseEvent *ev); -- cgit From ff558814658470aaa24c5ca0f5cc8d687ffe7c74 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 27 Sep 2017 11:51:40 -0400 Subject: Commit some minor updates/tests to the GL widgets. need to avoid QPainter if we want GPU accelleration. --- src-qt5/src-glwidgets/gltest/main.cpp | 16 ++++++---- src-qt5/src-glwidgets/gltest/test | Bin 58021 -> 59456 bytes src-qt5/src-glwidgets/glw-base.cpp | 55 +++++++++++++++++++++++++--------- src-qt5/src-glwidgets/glw-base.h | 4 ++- src-qt5/src-glwidgets/glw-widget.cpp | 12 ++++---- src-qt5/src-glwidgets/glw-widget.h | 4 +-- 6 files changed, 63 insertions(+), 28 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/src-glwidgets/gltest/main.cpp b/src-qt5/src-glwidgets/gltest/main.cpp index 972c4225..b303cb6b 100644 --- a/src-qt5/src-glwidgets/gltest/main.cpp +++ b/src-qt5/src-glwidgets/gltest/main.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include "../glw-base.h" #include "../glw-widget.h" @@ -10,11 +9,18 @@ #include "colorchange.h" int main(int argc, char** argv){ + + QSurfaceFormat fmt; + fmt.setRenderableType(QSurfaceFormat::OpenGL); //OpenGL, OpenGLES, OpenVG + fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + QSurfaceFormat::setDefaultFormat(fmt); + QApplication A(argc,argv); + qDebug() << "Creating base widget"; GLW_Base base; qDebug() << "Resize base widget"; - base.resize(200,200); + base.resize(1024,768); qDebug() << "Create Other widgets"; GLW_Widget wgt1(&base); wgt1.setGLBase(&base); @@ -28,11 +34,11 @@ int main(int argc, char** argv){ anim.setPropertyName("geometry"); //anim.setStartValue(QRect(-50,-50,50,50)); //anim.setEndValue(QRect(200,200,50,50)); - anim.setStartValue(QRect(100,100,0,0)); - anim.setEndValue(QRect(0,0,200,200)); + anim.setStartValue(QRect(base.width()/2,base.height()/2,0,0)); + anim.setEndValue(QRect(0,0,base.width(),base.height())); anim.setDuration(1500); anim.setLoopCount(-1); - //anim.start(); + anim.start(); /*QPushButton but(&base); but.setText("button"); but.setGeometry(100,100,50,50); diff --git a/src-qt5/src-glwidgets/gltest/test b/src-qt5/src-glwidgets/gltest/test index cf9d2c31..85760654 100755 Binary files a/src-qt5/src-glwidgets/gltest/test and b/src-qt5/src-glwidgets/gltest/test differ diff --git a/src-qt5/src-glwidgets/glw-base.cpp b/src-qt5/src-glwidgets/glw-base.cpp index d4279c61..ef54606b 100644 --- a/src-qt5/src-glwidgets/glw-base.cpp +++ b/src-qt5/src-glwidgets/glw-base.cpp @@ -6,10 +6,17 @@ //=========================================== #include "glw-base.h" #include "glw-widget.h" +#include +#include +#include +#include +#include GLW_Base::GLW_Base(QWidget *parent, Qt::WindowFlags f) : QOpenGLWidget(parent,f){ bg_color = QColor(Qt::black); mouse_over_child = 0; + qDebug() << "Canvas supports threaded OpenGL:" << this->context()->supportsThreadedOpenGL(); + qDebug() << " - globally:" << QOpenGLContext::globalShareContext()->supportsThreadedOpenGL(); } GLW_Base::~GLW_Base(){ @@ -30,11 +37,11 @@ void GLW_Base::setBackgroundColor(QColor color){ void GLW_Base::setBackground(QRect geom, QImage img){ QPainter P(&bg_img); P.drawImage(geom, img); - this->update(); + this->update(geom); } void GLW_Base::repaintArea(QRect rect){ - paintEvent(new QPaintEvent(rect)); + this->update(rect); } void GLW_Base::setMouseOverWidget(QWidget *child){ @@ -55,26 +62,46 @@ void GLW_Base::resizeEvent(QResizeEvent *ev){ emit BaseResized(); } -void GLW_Base::paintEvent(QPaintEvent *ev){ - QStylePainter painter(this); - painter.setClipRegion(ev->rect()); +/*void GLW_Base::paintEvent(QPaintEvent *ev){ + QOpenGLWidget::paintEvent(ev); +}*/ + +void GLW_Base::paintGL(){ + //Setup the OpenGL stuff + QRect rect = QRect(QPoint(0,0), this->size()); + //Prepare the image to be painted + QImage img(this->size(), QImage::Format_RGBA8888); + QPainter painter; + painter.begin(&img); + painter.fillRect(rect, bg_color); + painter.end(); + QOpenGLFunctions *f = this->context()->functions(); + //f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + //do native OpenGL commands here + glDrawPixels(bg_img.width(), bg_img.height(), GL_RGBA, GL_UNSIGNED_BYTE, bg_img.bits()); + + //Now do any QPainter drawing + /*QOpenGLPaintDevice device(rect.size()); + QStylePainter painter; + painter.begin(&device, this); + //qDebug() << "Paint Engine type:" << painter.paintEngine()->type(); + painter.setClipRegion(rect); //Fill in the background color first - painter.fillRect(ev->rect(), bg_color); + painter.fillRect(rect, bg_color); //Now paint any background image over that - painter.drawImage(ev->rect(), bg_img, ev->rect(), Qt::AutoColor | Qt::PreferDither | Qt::NoOpaqueDetection); + painter.drawImage(rect, bg_img, rect, Qt::AutoColor | Qt::PreferDither | Qt::NoOpaqueDetection); //Now find any children widgets and paint them if they are in that area QObjectList child = this->children(); //Note: This is returned in stacking order (lowest -> highest) for(int i=0; iisWidgetType() ){ continue; } //not a widget GLW_Widget *glww = qobject_cast(child[i]); if(glww!=0){ - if(!ev->rect().intersected(glww->widgetRect()).isNull()){ - glww->paintYourself(&painter, ev); - glww->paintChildren(&painter,ev); + if(!rect.intersected(glww->widgetRect()).isNull()){ + glww->paintYourself(&painter, &rect); + glww->paintChildren(&painter,&rect); } - }/*else{ - QWidget *widg = qobject_cast(child[i]); - widg->render(&painter, widg->geometry().topLeft()); - }*/ + } } + painter.end(); + update();*/ } diff --git a/src-qt5/src-glwidgets/glw-base.h b/src-qt5/src-glwidgets/glw-base.h index 3c3d1d4e..ecc5bc3a 100644 --- a/src-qt5/src-glwidgets/glw-base.h +++ b/src-qt5/src-glwidgets/glw-base.h @@ -41,7 +41,9 @@ signals: protected: void mouseMoveEvent(QMouseEvent *ev); void resizeEvent(QResizeEvent *ev); - void paintEvent(QPaintEvent *ev); + //void paintEvent(QPaintEvent *ev); + //void initializeGL(); + void paintGL(); }; #endif diff --git a/src-qt5/src-glwidgets/glw-widget.cpp b/src-qt5/src-glwidgets/glw-widget.cpp index e6c98d74..e8d255b9 100644 --- a/src-qt5/src-glwidgets/glw-widget.cpp +++ b/src-qt5/src-glwidgets/glw-widget.cpp @@ -33,9 +33,9 @@ void GLW_Widget::setGLBase(GLW_Base *base){ connect(this, SIGNAL(repaintArea(QRect)), glw_base, SLOT(repaintArea(QRect)) ); } -void GLW_Widget::paintYourself(QStylePainter *painter, QPaintEvent *ev){ +void GLW_Widget::paintYourself(QStylePainter *painter, const QRect *prect){ QRect rect = widgetRect(); - rect = rect.intersected(ev->rect()); + rect = prect->intersected(rect); QColor color( mouseOverWidget() ? Qt::gray : Qt::yellow); //if(this->windowOpacity()!=1.0){ qDebug() << "Opacity:" << this->windowOpacity(); } //color.setAlpha( qRound(this->windowOpacity()*255) ); @@ -43,15 +43,15 @@ void GLW_Widget::paintYourself(QStylePainter *painter, QPaintEvent *ev){ painter->fillRect(rect, color); } -void GLW_Widget::paintChildren(QStylePainter *painter, QPaintEvent *ev){ +void GLW_Widget::paintChildren(QStylePainter *painter, const QRect *prect){ QObjectList child = this->children(); //Note: This is returned in stacking order (lowest -> highest) for(int i=0; iisWidgetType() ){ continue; } //not a widget GLW_Widget *glww = qobject_cast(child[i]); if(glww!=0){ - if(ev->rect().contains(glww->widgetRect())){ - glww->paintYourself(painter, ev); - glww->paintChildren(painter,ev); + if( !prect->intersected(glww->widgetRect()).isNull() ){ + glww->paintYourself(painter, prect); + glww->paintChildren(painter,prect); } } } diff --git a/src-qt5/src-glwidgets/glw-widget.h b/src-qt5/src-glwidgets/glw-widget.h index e4d7aa37..69d3515d 100644 --- a/src-qt5/src-glwidgets/glw-widget.h +++ b/src-qt5/src-glwidgets/glw-widget.h @@ -31,8 +31,8 @@ public: void setGLBase(GLW_Base *base); - virtual void paintYourself(QStylePainter *painter, QPaintEvent *ev); - void paintChildren(QStylePainter *painter, QPaintEvent *ev); + virtual void paintYourself(QStylePainter *painter, const QRect *prect); + void paintChildren(QStylePainter *painter, const QRect *prect); //Properties bool isDraggable(){ return draggable; } -- cgit From f98507eb3fef50e900c9ceb3606e4cdea78fbd64 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 2 Oct 2017 05:14:40 -0400 Subject: Add a "copy" button to the QSS page for copying files to make changes. --- .../src/lthemeengine/qsspage.cpp | 33 +++++++++++++++++ .../lumina-theme-engine/src/lthemeengine/qsspage.h | 1 + .../src/lthemeengine/qsspage.ui | 41 ++++++++++++++++++++-- 3 files changed, 73 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp index cd88fb56..6377016c 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp @@ -31,6 +31,7 @@ QSSPage::QSSPage(QWidget *parent, bool desktop) : TabPage(parent), m_ui(new Ui:: m_ui->removeButton->setIcon(QIcon::fromTheme("edit-delete")); m_ui->tool_enable->setEnabled(false); m_ui->tool_disable->setEnabled(false); + m_ui->copyButton->setEnabled(false); } QSSPage::~QSSPage(){ @@ -56,6 +57,7 @@ void QSSPage::on_qssListWidget_currentItemChanged(QListWidgetItem *current, QLis } //qDebug() << "Got Current Item Changed"; m_ui->tool_disable->setEnabled(current!=0); + m_ui->copyButton->setEnabled(current!=0); if(current){ m_ui->editButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool()); m_ui->removeButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool()); @@ -76,6 +78,7 @@ void QSSPage::on_list_disabled_currentItemChanged(QListWidgetItem *current, QLis } //qDebug() << "Got Current Item Changed"; m_ui->tool_enable->setEnabled(current!=0); + m_ui->copyButton->setEnabled(current!=0); if(current){ m_ui->editButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool()); m_ui->removeButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool()); @@ -127,6 +130,36 @@ void QSSPage::on_editButton_clicked(){ } } +void QSSPage::on_copyButton_clicked(){ + QListWidgetItem *sel = currentSelection(); + if(sel==0){ return; } + QString name = QInputDialog::getText(this, tr("Enter Style Sheet Name"), tr("File name:"), QLineEdit::Normal, sel->text().section(".qss",0,0)+"_copy"); + if(name.isEmpty()){ return; } + if(!name.endsWith(".qss", Qt::CaseInsensitive)){ name.append(".qss"); } + QString filePath; + if(desktop_qss){ filePath = lthemeengine::userDesktopStyleSheetPath() + name; } + else{ filePath = lthemeengine::userStyleSheetPath() + name; } + if(QFile::exists(filePath)){ + QMessageBox::warning(this, tr("Error"), tr("The file \"%1\" already exists").arg(filePath)); + return; + } + // Make sure the directory exists + QString dir = filePath.section("/",0,-2); + if(!QFile::exists(dir)){ + QDir D(dir); + D.mkpath(dir); + } + //Copy the file over + QFile::copy(sel->data(QSS_FULL_PATH_ROLE).toString(), filePath); + //creating item + QFileInfo info(filePath); + QListWidgetItem *item = new QListWidgetItem(info.fileName(), m_ui->list_disabled); + item->setToolTip(info.filePath()); + item->setData(QSS_FULL_PATH_ROLE, info.filePath()); + item->setData(QSS_WRITABLE_ROLE, info.isWritable()); + m_ui->list_disabled->setCurrentRow(m_ui->list_disabled->count()-1); +} + void QSSPage::on_removeButton_clicked(){ QListWidgetItem *item = currentSelection(); if(!item){ return; } diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h index 5b0025c5..07df4ac2 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h @@ -24,6 +24,7 @@ private slots: void on_qssListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *); void on_list_disabled_currentItemChanged(QListWidgetItem *current, QListWidgetItem *); void on_createButton_clicked(); + void on_copyButton_clicked(); void on_editButton_clicked(); void on_removeButton_clicked(); void on_renameButton_clicked(); diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui index f9a980f3..def99dd0 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui @@ -63,7 +63,7 @@ - + 0 0 @@ -168,7 +168,7 @@ - + 0 0 @@ -222,16 +222,41 @@ true + + + 0 + 0 + + Create + + + + + 0 + 0 + + + + Copy + + + false + + + 0 + 0 + + Edit @@ -242,6 +267,12 @@ false + + + 0 + 0 + + Rename @@ -252,6 +283,12 @@ false + + + 0 + 0 + + Remove -- cgit From 63269d970b014f2475a6906a1afeba8d7920e16e Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 2 Oct 2017 05:20:41 -0400 Subject: Remove the "ok" button, and change the "cancel" button to "close". --- src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp | 2 +- src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp index d4544c7b..28a5e558 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp @@ -55,7 +55,7 @@ void MainWindow::on_buttonBox_clicked(QAbstractButton *button){ if(p) { p->writeSettings(); } } } - if(id == QDialogButtonBox::Ok || id == QDialogButtonBox::Cancel){ + if(id == QDialogButtonBox::Ok || id == QDialogButtonBox::Cancel || id== QDialogButtonBox::Close){ close(); qApp->quit(); } diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui index dd676c37..0dc3245d 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui @@ -293,7 +293,7 @@ Styles - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Apply|QDialogButtonBox::Close -- cgit From cf4afae359c39fc8adf767fe52538311656501ab Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 2 Oct 2017 06:06:18 -0400 Subject: Add a couple more "simple" stylesheets for sliders and tooltips. --- .../lumina-theme-engine/qss/sliders-simple.qss | 70 ++++++++++++++++++++++ .../lumina-theme-engine/qss/tooltip-simple.qss | 7 +++ 2 files changed, 77 insertions(+) create mode 100644 src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss create mode 100644 src-qt5/core/lumina-theme-engine/qss/tooltip-simple.qss (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss b/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss new file mode 100644 index 00000000..e8311e92 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss @@ -0,0 +1,70 @@ +/* SLIDERS */ +QSlider::groove:horizontal { +border: 1px solid transparent; +background: palette(alternate-window); +height: 10px; +border-radius: 3px; +} +QSlider::groove:vertical { +border: 1px solid transparent; +background: palette(alternate-window); +width: 10px; +border-radius: 3px; +} +QSlider::sub-page:horizontal { +background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, + stop: 0 palette(highlight), stop: 1 palette(window)); +border: 1px solid transparent; +height: 10px; +border-radius: 3px; +} +QSlider::sub-page:vertical { +background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, + stop: 0 palette(highlight), stop: 1 palette(window)); +border: 1px solid transparent; +width: 10px; +border-radius: 3px; +} +QSlider::add-page:horizontal{ +background: palette(alternate-window); +border: 1px solid transparent; +height: 10px; +border-radius: 3px; +} +QSlider::add-page:vertical{ +background: palette(alternate-window); +border: 1px solid transparent; +width: 10px; +border-radius: 3px; +} +QSlider::handle:horizontal{ +background: palette(mid); +border: 1px solid palette(mid); +width: 1em; +border-radius: 1px; +} +QSlider::handle:vertical{ +background: palette(mid); +border: 1px solid palette(mid); +height: 1em; +border-radius: 1px; +} +QSlider::handle:horizontal:hover, QSlider::handle:vertical:hover{ +border: 1px solid palette(highlight); +background: palette(highlight); +} + +QSlider::sub-page:horizontal:disabled { +background: palette(highlight); +border-color: palette(highlight); +} + +QSlider::add-page:horizontal:disabled { +background: palette(highlight); +border-color: palette(highlight); +} + +QSlider::handle:horizontal:disabled { +background: palette(alternate-window); +border: 1px solid palette(highlight); +} diff --git a/src-qt5/core/lumina-theme-engine/qss/tooltip-simple.qss b/src-qt5/core/lumina-theme-engine/qss/tooltip-simple.qss new file mode 100644 index 00000000..9bee3e08 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/qss/tooltip-simple.qss @@ -0,0 +1,7 @@ +QToolTip{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 palette(window), stop: 1 palette(alternate-window)); + border-radius: 3px; + border: 1px solid palette(highlight); + padding: 1px; + color: palette(text); +} -- cgit From a5e2dc9b732363c3b5d99aaa01f35c268d6aecbe Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 2 Oct 2017 06:11:01 -0400 Subject: Adjust the border on the simple scrollbar style, and update the pkg-plist. --- src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss b/src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss index 265ff20c..d0c9b448 100644 --- a/src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss +++ b/src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss @@ -11,7 +11,7 @@ QScrollBar:vertical{ QScrollBar::handle{ background: palette(base); border: 1px solid transparent; - border-radius: 7px; + border-radius: 1px; } QScrollBar::handle:hover, QScrollBar::add-line:hover, QScrollBar::sub-line:hover{ background: palette(highlight); -- cgit From 711b219a001d0c4fdd61367903696fa1c6ff1a3d Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Tue, 3 Oct 2017 15:24:26 -0400 Subject: Added experimental video thumbnails in lumina-fm and fileinfo --- src-qt5/core/libLumina/LVideoSurface.cpp | 32 +++++++++++ src-qt5/core/libLumina/LVideoSurface.h | 20 +++++++ src-qt5/core/libLumina/LVideoSurface.pri | 9 +++ src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 25 ++++++++- src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 9 ++- .../lumina-fileinfo/lumina-fileinfo.pro | 3 +- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 62 +++++++++++++++++---- src-qt5/desktop-utils/lumina-fm/Browser.h | 10 +++- src-qt5/desktop-utils/lumina-fm/lumina-fm.pro | 1 + src-qt5/src-glwidgets/gltest/colorchange.h | 11 +--- src-qt5/src-glwidgets/gltest/main.cpp | 13 +++-- src-qt5/src-glwidgets/gltest/test | Bin 59456 -> 58272 bytes src-qt5/src-glwidgets/glw-base.cpp | 21 +++++-- 13 files changed, 179 insertions(+), 37 deletions(-) create mode 100644 src-qt5/core/libLumina/LVideoSurface.cpp create mode 100644 src-qt5/core/libLumina/LVideoSurface.h create mode 100644 src-qt5/core/libLumina/LVideoSurface.pri (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoSurface.cpp b/src-qt5/core/libLumina/LVideoSurface.cpp new file mode 100644 index 00000000..6adec5d2 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoSurface.cpp @@ -0,0 +1,32 @@ +#include "LVideoSurface.h" +#include + +LVideoSurface::LVideoSurface() : QAbstractVideoSurface() { + recording = 0; + frameImage = QImage(); +} + +QImage LVideoSurface::currentFrame() { + return frameImage; +} + +bool LVideoSurface::present(const QVideoFrame &frame) { + if(frame.isValid()) { + qDebug() << "Recording Frame" << frame.pixelFormat(); + QVideoFrame icon(frame); + icon.map(QAbstractVideoBuffer::ReadOnly); + frameImage = QImage(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QImage::Format_ARGB32_Premultiplied); + icon.unmap(); + emit frameReceived(frameImage); + if(recording++ == 2) ready = true; + return true; + } + ready = false; + return false; +} + +QList LVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const { + Q_UNUSED(type); + return QList() << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_RGB32 << QVideoFrame::Format_RGB24 + << QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB555 << QVideoFrame::Format_BGRA32 << QVideoFrame::Format_BGR32; +} diff --git a/src-qt5/core/libLumina/LVideoSurface.h b/src-qt5/core/libLumina/LVideoSurface.h new file mode 100644 index 00000000..adb4611d --- /dev/null +++ b/src-qt5/core/libLumina/LVideoSurface.h @@ -0,0 +1,20 @@ +#include +#include +#include + +class LVideoSurface : public QAbstractVideoSurface { + Q_OBJECT + + public: + LVideoSurface(); + virtual bool present(const QVideoFrame&); + virtual QList supportedPixelFormats(QAbstractVideoBuffer::HandleType) const; + QImage currentFrame(); + bool frameReady(); + signals: + void frameReceived(QImage); + private: + int recording; + QImage frameImage; + bool ready; +}; diff --git a/src-qt5/core/libLumina/LVideoSurface.pri b/src-qt5/core/libLumina/LVideoSurface.pri new file mode 100644 index 00000000..469b8c93 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoSurface.pri @@ -0,0 +1,9 @@ +QT *= multimedia + +HEADERS *= $${PWD}/LVideoSurface.h +SOURCES *= $${PWD}/LVideoSurface.cpp + +INCLUDEPATH *= ${PWD} + +#Now the other dependendies of it +#include(LUtils.pri) diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index d82f09ce..4d695ab4 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -8,6 +8,7 @@ #include "MainUI.h" #include "ui_MainUI.h" +#include #include #include @@ -22,12 +23,17 @@ MainUI::MainUI() : QDialog(), ui(new Ui::MainUI){ terminate_thread = false; UpdateIcons(); //Set all the icons in the dialog SetupConnections(); + player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); + surface = new LVideoSurface(); + player->setVideoOutput(surface); INFO = 0; } MainUI::~MainUI(){ terminate_thread = true; this->close(); + delete surface; + delete player; } //============= @@ -86,7 +92,15 @@ void MainUI::LoadFile(QString path, QString type){ ui->label_file_icon->setPixmap( pix.scaledToHeight(64) ); ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); //qDebug() << " - done with image"; - }else{ + }/*else if(INFO->isVideo()){ + player->setMedia(QUrl("file://"+INFO->absoluteFilePath())); + player->play(); + player->setPosition(player->duration() / 2); + connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(stopVideo(QImage))); + //Pixmap set when video is loaded in stopVideo + //ui->label_file_icon->setPixmap( QPixmap::fromImage(surface->frameImage()).scaledToHeight(64) ); + //ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); + }*/else{ ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); } //Now verify the tab is available in the widget @@ -103,7 +117,7 @@ void MainUI::LoadFile(QString path, QString type){ } //Now load the special XDG desktop info qDebug() << "Check XDG Info:" << type; - //qDebug() << INFO->isDesktopFile() << type; + qDebug() << INFO->isDesktopFile() << type; if(INFO->isDesktopFile() || !type.isEmpty()){ if(INFO->XDG()->type == XDGDesktop::APP){ @@ -296,6 +310,13 @@ void MainUI::getXdgCommand(QString prev){ xdgvaluechanged(); } +/*void MainUI::stopVideo(QImage img) { + static bool flag = true; + if(flag) { player->setPosition(player->duration() / 2); flag = false;} + player->pause(); + ui->label_file_icon->setPixmap( QPixmap::fromImage( img.scaledToHeight(64) )); +}*/ + void MainUI::on_tool_xdg_getDir_clicked(){ //Find a directory QString dir = ui->line_xdg_wdir->text(); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index cbe23d9e..e1f37425 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -14,11 +14,11 @@ #define _LUMINA_FILE_INFO_MAIN_UI_H #include - +#include #include +#include -namespace Ui{ - class MainUI; +namespace Ui{ class MainUI; }; class MainUI : public QDialog{ @@ -35,6 +35,8 @@ public slots: private: Ui::MainUI *ui; LFileInfo *INFO; + LVideoSurface *surface; + QMediaPlayer *player; bool canwrite; bool terminate_thread; //flag for terminating the GetDirSize task @@ -51,6 +53,7 @@ private slots: //UI Buttons void on_push_close_clicked(); void on_push_save_clicked(); + //void stopVideo(QImage); void getXdgCommand(QString prev = ""); //void on_tool_xdg_getCommand_clicked(QString prev = ""); void on_tool_xdg_getDir_clicked(); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro index bbaf842e..b53d8cba 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro +++ b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro @@ -1,7 +1,7 @@ include("$${PWD}/../../OS-detect.pri") QT += core gui -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets concurrent +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets concurrent multimedia TARGET = lumina-fileinfo @@ -13,6 +13,7 @@ target.path = $${L_BINDIR} include(../../core/libLumina/LUtils.pri) #includes LUtils include(../../core/libLumina/LuminaXDG.pri) #include(../../core/libLumina/LuminaSingleApplication.pri) +include(../../core/libLumina/LVideoSurface.pri) include(../../core/libLumina/LuminaThemes.pri) SOURCES += main.cpp\ diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index f2bdc178..e57b6aed 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -16,10 +16,13 @@ Browser::Browser(QObject *parent) : QObject(parent){ watcher = new QFileSystemWatcher(this); connect(watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(fileChanged(QString)) ); - connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(dirChanged(QString)) ); + connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(dirChanged(QString)) ); showHidden = false; showThumbs = false; imageFormats = LUtils::imageExtensions(false); //lowercase suffixes + videoFormats = LUtils::videoExtensions(); //lowercase suffixes + //connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(captureFrame(QImage))); + //connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); connect(this, SIGNAL(threadDone(QString, QImage)), this, SLOT(futureFinished(QString, QImage))); //will always be between different threads } @@ -60,12 +63,11 @@ void Browser::loadItem(QString info, Browser *obj){ file.close(); pix.loadFromData(bytes); if(pix.width() > 256 || pix.height() > 256 ){ - pix = pix.scaled(256,256, Qt::KeepAspectRatio, Qt::SmoothTransformation); + pix = pix.scaled(256,256, Qt::KeepAspectRatio); } } } - - //qDebug() << " - done with item:" << info; + qDebug() << " - done with item:" << info; obj->emit threadDone(info, pix); } @@ -92,22 +94,60 @@ void Browser::dirChanged(QString dir){ else if(dir.startsWith(currentDir)){ QtConcurrent::run(this, &Browser::loadItem, dir, this ); } } +/*void Browser::stopVideo(QMediaPlayer *player, QMediaPlayer::MediaStatus status) { + qDebug() << status; + if(status == QMediaPlayer::BufferedMedia) { + qDebug() << "stoppingVideo" << player << player->currentMedia().canonicalUrl(); + player->setPosition(player->duration() / 2); + player->pause(); + } +} + +void Browser::captureFrame(QImage pix) { + qDebug() << "grabbing frame"; + videoFrame = pix.scaledToHeight(64); + emit frameChanged(); +}*/ + void Browser::futureFinished(QString name, QImage icon){ //Note: this will be called once for every item that loads QIcon ico; - //LFileInfo info(name); LFileInfo *info = new LFileInfo(name); if(!icon.isNull() && showThumbs){ - //qDebug() << " -- Data:"; QPixmap pix = QPixmap::fromImage(icon); ico.addPixmap(pix); - //}else if(info->isDir()){ - //qDebug() << " -- Folder:"; - //ico = loadIcon("folder"); } if(ico.isNull()){ - //qDebug() << " -- MimeType:" << info.fileName() << info.mimetype(); - ico = loadIcon(info->iconfile()); + if(videoFormats.contains(name.section(".",-1).toLower())) { + qDebug() << "Loading Video for" << name; + qDebug() << "VIDEO" << info; + //qDebug() << obj << this << QThread::currentThread(); + QMediaPlayer *player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); + qDebug() << " - created player"; + LVideoSurface *surface = new LVideoSurface(); + qDebug() << " - Create objects"; + //connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(captureFrame(QImage))); + //connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); + player->setVideoOutput(surface); + player->setVolume(0); + player->setMedia(QUrl("file://"+info->absoluteFilePath())); + player->play(); + qDebug() << "Wait for buffer"; + while(player->mediaStatus()!=QMediaPlayer::BufferedMedia){ + QCoreApplication::processEvents(); + } + player->pause(); + player->setPosition(player->duration()/2); + while(!surface->frameReady()) { + QCoreApplication::processEvents(); + } + qDebug() << "Load Frame"; + ico.addPixmap(QPixmap::fromImage(surface->currentFrame())); + delete player; + delete surface; + }else { + ico = loadIcon(info->iconfile()); + } } this->emit itemDataAvailable( ico, info); //qDebug() << " -- done:" << name; diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.h b/src-qt5/desktop-utils/lumina-fm/Browser.h index 94f6ba3f..7ccb5199 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.h +++ b/src-qt5/desktop-utils/lumina-fm/Browser.h @@ -15,6 +15,8 @@ #include //#include +#include +#include #include /*class FileItem{ public: @@ -43,8 +45,9 @@ public: private: QString currentDir; QFileSystemWatcher *watcher; + //QImage videoFrame; bool showHidden, showThumbs; - QStringList imageFormats, oldFiles; + QStringList imageFormats, videoFormats, oldFiles; QHash mimeIcons; //cache for quickly re-using QIcons void loadItem(QString info, Browser *obj); //this is the main loader class - multiple instances each run in a separate thread @@ -53,7 +56,8 @@ private: private slots: void fileChanged(QString); //tied into the watcher - for file change notifications void dirChanged(QString); // tied into the watcher - for new/removed files in the current dir - + //void captureFrame(QImage); + //void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); void futureFinished(QString, QImage); public slots: @@ -70,6 +74,8 @@ signals: //Internal signal for the alternate threads void threadDone(QString, QImage); + + //void frameChanged(); }; #endif diff --git a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro index 6c340e14..6cb4a537 100644 --- a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro +++ b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro @@ -15,6 +15,7 @@ include(../../core/libLumina/LuminaXDG.pri) include(../../core/libLumina/LuminaSingleApplication.pri) include(../../core/libLumina/LuminaThemes.pri) include(../../core/libLumina/ExternalProcess.pri) +include(../../core/libLumina/LVideoSurface.pri) SOURCES += main.cpp \ MainUI.cpp \ diff --git a/src-qt5/src-glwidgets/gltest/colorchange.h b/src-qt5/src-glwidgets/gltest/colorchange.h index d62fcd5c..aad01f05 100644 --- a/src-qt5/src-glwidgets/gltest/colorchange.h +++ b/src-qt5/src-glwidgets/gltest/colorchange.h @@ -13,14 +13,9 @@ private: public slots: void toggle(){ - static int current = 0; - if(current==0){ - base->setBackgroundColor(QColor(Qt::red)); - }else{ - base->setBackgroundColor(QColor(Qt::blue)); - current = -1; - } - current++; + static bool current = false; + base->setBackgroundColor( current ? QColor(Qt::blue) : QColor(Qt::red)); + current = !current; } public: diff --git a/src-qt5/src-glwidgets/gltest/main.cpp b/src-qt5/src-glwidgets/gltest/main.cpp index b303cb6b..efcebea1 100644 --- a/src-qt5/src-glwidgets/gltest/main.cpp +++ b/src-qt5/src-glwidgets/gltest/main.cpp @@ -10,14 +10,14 @@ int main(int argc, char** argv){ - QSurfaceFormat fmt; + QSurfaceFormat fmt; fmt.setRenderableType(QSurfaceFormat::OpenGL); //OpenGL, OpenGLES, OpenVG fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - QSurfaceFormat::setDefaultFormat(fmt); + QSurfaceFormat::setDefaultFormat(fmt); QApplication A(argc,argv); - qDebug() << "Creating base widget"; + qDebug() << "Creating base widget"; GLW_Base base; qDebug() << "Resize base widget"; base.resize(1024,768); @@ -29,7 +29,7 @@ int main(int argc, char** argv){ GLW_Widget wgt(&base); wgt.setGLBase(&base); wgt.setGeometry(75,50,50,50); - QPropertyAnimation anim(&wgt); + QPropertyAnimation anim(&wgt); anim.setTargetObject(&wgt); anim.setPropertyName("geometry"); //anim.setStartValue(QRect(-50,-50,50,50)); @@ -46,6 +46,7 @@ int main(int argc, char** argv){ colorchange CC(&base); qDebug() << "Start Event loop"; base.show(); - A.exec(); - qDebug() << " - Finished"; + int ret = A.exec(); + qDebug() << " - Finished"; + return ret; } diff --git a/src-qt5/src-glwidgets/gltest/test b/src-qt5/src-glwidgets/gltest/test index 85760654..3ba6f8db 100755 Binary files a/src-qt5/src-glwidgets/gltest/test and b/src-qt5/src-glwidgets/gltest/test differ diff --git a/src-qt5/src-glwidgets/glw-base.cpp b/src-qt5/src-glwidgets/glw-base.cpp index ef54606b..4065f70f 100644 --- a/src-qt5/src-glwidgets/glw-base.cpp +++ b/src-qt5/src-glwidgets/glw-base.cpp @@ -67,7 +67,24 @@ void GLW_Base::resizeEvent(QResizeEvent *ev){ }*/ void GLW_Base::paintGL(){ + //Setup the OpenGL stuff + QOpenGLFunctions *f = this->context()->functions(); + f->glViewport(0, 0, width(), height()); + f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + GLfloat vertices[] = { + 0.0f, 0.707f, + -0.5f, -0.5f, + 0.5f, -0.5f + }; + + f->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); + f->glEnableVertexAttribArray(0); + f->glDrawArrays(GL_TRIANGLES, 0, 3); + f->glDisableVertexAttribArray(0); + glDrawPixels(bg_img.width(), bg_img.height(), GL_RGBA, GL_UNSIGNED_BYTE, bg_img.bits()); + QRect rect = QRect(QPoint(0,0), this->size()); //Prepare the image to be painted QImage img(this->size(), QImage::Format_RGBA8888); @@ -75,10 +92,6 @@ void GLW_Base::paintGL(){ painter.begin(&img); painter.fillRect(rect, bg_color); painter.end(); - QOpenGLFunctions *f = this->context()->functions(); - //f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //do native OpenGL commands here - glDrawPixels(bg_img.width(), bg_img.height(), GL_RGBA, GL_UNSIGNED_BYTE, bg_img.bits()); //Now do any QPainter drawing /*QOpenGLPaintDevice device(rect.size()); -- cgit From 2f6d29bf06e77b45daa742a5c6c65a5ed0624dab Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 3 Oct 2017 15:25:46 -0400 Subject: Revert "rework video thumbnail code" This reverts commit a3092fb02a1905345e1311b2e64f4796acdb9f34. --- .../desktop-utils/lumina-fm/widgets/vidnail.cpp | 33 ---------------------- src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h | 25 ---------------- 2 files changed, 58 deletions(-) delete mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp delete mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp deleted file mode 100644 index ee7fb9e3..00000000 --- a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "vidnail.h" -vidnail::vidnail(QWidget *parent) : QMainWindow(parent), mplayer(parent, QMediaPlayer::VideoSurface){ //there is no UI, so not sure how to alter the constructor -} - -vidnail::~vidnail() -{ - -vidnail::grabvideothumbnail(){ - vsurface = new QAbstractVideoSurface(); - mplayer.setVideoOutput(vsurface); - mplayer.setMedia($file); // video file to get thumbnail of - imageCaptured = QPixmap(); - mplayer.setPosition(2000); // time in milliseconds - mplayer.setMuted(true); // just to make sure no sound is emited - mplayer.play(); - - currentFrame = frame; - const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); - const QSize size = format.frameSize(); - - this->imageFormat = imageFormat; - QAbstractVideoSurface::start(format); - QImage image( currentFrame.bits(), currentFrame.width(), currentFrame.height(), currentFrame.bytesPerLine(), imageFormat); - imageCaptured = QPixmap::fromImage(image.copy(image.rect())); - -// Now do scaling with regular thumbnail process to make proper size - - mplayer.stop(); - vsurface.stop(); -} - - - diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h deleted file mode 100644 index ad565749..00000000 --- a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef VIDNAIL_H -#define VIDNAIL_H - -#include -#include -#include "videowidgetsurface.h" -#include -#include -#include -#include -#include - -public: - - void grabvideothumbnail(); - -private: - - QAbstractVideoSurface *vsurface; - QImage::Format imageFormat; - QPixmap imageCaptured; - - -#endif // VIDNAIL_H - -- cgit From 62805a2e99df692201c8a0885e8b8e785949b634 Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 3 Oct 2017 15:29:19 -0400 Subject: add libav video thumbnail code back to project --- .../desktop-utils/lumina-fm/widgets/vidnail.cpp | 61 ++++++++++++++++++++++ src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h | 13 +++++ 2 files changed, 74 insertions(+) create mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp create mode 100644 src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp new file mode 100644 index 00000000..ee76a8dc --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp @@ -0,0 +1,61 @@ +#ifndef VIDNAIL_H +#define VIDNAIL_H + +extern "C" { +#include +#include +} + +class VidNail; + +struct vFrame { + vFrame() : *width(0), *height(0) {} + vFrame(int *width, int *height : width(width), height(height) {} + int *width; + int *height; +}; + +public: + + QString getCodec(); + void goto(int timeInSeconds); + void readVideoFrame(); + void getScaledVideoFrame(int scaledSize, vFrame& vFrame); + + int getWidth(); + int getHeight(); + int getLength(); + + void makeThumbnail(const QString& videoFile, QImage &image); + void setThumbnailSize(int size); + void setPercentage(int percent); + void setTime(const QString& Time); + + void writeVidNail(vFrame& frame, QImage& image); + + + private: + + bool readVideoPacket(); + bool getVideoPacket(); + void scaleVideo(int scaledSize, int& scaledWidth, int& scaledHeight); + void createVFrame(AVFrame *vFrame, quint8 *frameBuffer, int width, int height); + void calculateDimensions(int size); + void generateThumbnail(const QString& videoFile, ImageWriter& imageWriter, QImage& +image); + QString getMimeType(const QString& videoFile); + QString getExtension(const QString& videoFilename); + + + private: + int videoStream; + AVFormatContext *inputVideoFormatContext; + AVCodecContext *inputvideoCodecContext; + AVCodec *inputVideoCodec; + AVStream *inputVideoStream; + AVFrame *inputVideoFrame; + quint8 *inputFrameBuffer; + AVPacket *videoPacket; + + +#endif // VIDNAIL_H diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h new file mode 100644 index 00000000..e13894e1 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.h @@ -0,0 +1,13 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, q5sys +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "vidnail.h" + +VidNail::VidNail(QObject *parent) : QObject(parent){ +} + +VidNail::~VidNail(){ +} -- cgit From 3005f7ab6b19cabf423b85ec7c3845d840c7cb18 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Tue, 3 Oct 2017 18:36:51 -0400 Subject: Reworked the VideoSurface subclass --- src-qt5/core/libLumina/LVideoSurface.cpp | 46 +++++++++++++++++----- src-qt5/core/libLumina/LVideoSurface.h | 15 +++---- src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 37 +++++++++-------- src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 4 +- .../desktop-utils/lumina-fm/widgets/vidnail.cpp | 6 +-- 5 files changed, 70 insertions(+), 38 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoSurface.cpp b/src-qt5/core/libLumina/LVideoSurface.cpp index 6adec5d2..895a3a32 100644 --- a/src-qt5/core/libLumina/LVideoSurface.cpp +++ b/src-qt5/core/libLumina/LVideoSurface.cpp @@ -1,27 +1,29 @@ #include "LVideoSurface.h" #include -LVideoSurface::LVideoSurface() : QAbstractVideoSurface() { - recording = 0; - frameImage = QImage(); -} - -QImage LVideoSurface::currentFrame() { - return frameImage; +LVideoSurface::LVideoSurface(QObject *parent) : QAbstractVideoSurface(parent) { + frameImage = QPixmap(); } bool LVideoSurface::present(const QVideoFrame &frame) { + if(!frameImage.isNull()) { + emit frameReceived(frameImage); + return true; + } + if(frame.isValid()) { qDebug() << "Recording Frame" << frame.pixelFormat(); QVideoFrame icon(frame); icon.map(QAbstractVideoBuffer::ReadOnly); - frameImage = QImage(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QImage::Format_ARGB32_Premultiplied); + QImage img(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat())); + + if(frameImage.isNull()) + frameImage = QPixmap::fromImage(img.copy(img.rect())); + icon.unmap(); emit frameReceived(frameImage); - if(recording++ == 2) ready = true; return true; } - ready = false; return false; } @@ -30,3 +32,27 @@ QList LVideoSurface::supportedPixelFormats(QAbstractVi return QList() << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_RGB32 << QVideoFrame::Format_RGB24 << QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB555 << QVideoFrame::Format_BGRA32 << QVideoFrame::Format_BGR32; } + +/*bool VideoSurface::isFormatSupported(const QVideoSurfaceFormat &format) const { + const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); + const QSize size = format.frameSize(); + + return imageFormat != QImage::Format_Invalid && !size.isEmpty() && format.handleType() == QAbstractVideoBuffer::NoHandle; +} + +void VideoSurface::stop() { + QAbstractVideoSurface::stop(); +} + +bool VideoSurface::start(const QVideoSurfaceFormat &format) { + const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); + const QSize size = format.frameSize(); + + if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) { + this->imageFormat = imageFormat; + QAbstractVideoSurface::start(format); + return true; + } else { + return false; + } +}*/ diff --git a/src-qt5/core/libLumina/LVideoSurface.h b/src-qt5/core/libLumina/LVideoSurface.h index adb4611d..42a140d9 100644 --- a/src-qt5/core/libLumina/LVideoSurface.h +++ b/src-qt5/core/libLumina/LVideoSurface.h @@ -1,20 +1,21 @@ #include #include +#include #include class LVideoSurface : public QAbstractVideoSurface { Q_OBJECT public: - LVideoSurface(); + LVideoSurface(QObject *parent=0); virtual bool present(const QVideoFrame&); virtual QList supportedPixelFormats(QAbstractVideoBuffer::HandleType) const; - QImage currentFrame(); - bool frameReady(); + /*virtual QListsetVideoOutput(surface); + player->setMuted(true); + connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus))); + connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(stopVideo(QPixmap))); INFO = 0; } MainUI::~MainUI(){ terminate_thread = true; + surface->deleteLater(); + player->deleteLater(); this->close(); - delete surface; - delete player; } //============= @@ -92,15 +95,12 @@ void MainUI::LoadFile(QString path, QString type){ ui->label_file_icon->setPixmap( pix.scaledToHeight(64) ); ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); //qDebug() << " - done with image"; - }/*else if(INFO->isVideo()){ + }else if(INFO->isVideo()){ player->setMedia(QUrl("file://"+INFO->absoluteFilePath())); player->play(); - player->setPosition(player->duration() / 2); - connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(stopVideo(QImage))); + player->pause(); //Pixmap set when video is loaded in stopVideo - //ui->label_file_icon->setPixmap( QPixmap::fromImage(surface->frameImage()).scaledToHeight(64) ); - //ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); - }*/else{ + }else{ ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); } //Now verify the tab is available in the widget @@ -117,7 +117,7 @@ void MainUI::LoadFile(QString path, QString type){ } //Now load the special XDG desktop info qDebug() << "Check XDG Info:" << type; - qDebug() << INFO->isDesktopFile() << type; + //qDebug() << INFO->isDesktopFile() << type; if(INFO->isDesktopFile() || !type.isEmpty()){ if(INFO->XDG()->type == XDGDesktop::APP){ @@ -310,12 +310,17 @@ void MainUI::getXdgCommand(QString prev){ xdgvaluechanged(); } -/*void MainUI::stopVideo(QImage img) { - static bool flag = true; - if(flag) { player->setPosition(player->duration() / 2); flag = false;} +void MainUI::stopVideo(QPixmap img) { + ui->label_file_icon->setPixmap( img.scaledToHeight(64) ); player->pause(); - ui->label_file_icon->setPixmap( QPixmap::fromImage( img.scaledToHeight(64) )); -}*/ +} + +void MainUI::setDuration(QMediaPlayer::MediaStatus status) { + if(status == QMediaPlayer::BufferedMedia) { + player->setPosition(player->duration() / 2); + player->play(); + } +} void MainUI::on_tool_xdg_getDir_clicked(){ //Find a directory diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index e1f37425..5ce7b01a 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -37,6 +37,7 @@ private: LFileInfo *INFO; LVideoSurface *surface; QMediaPlayer *player; + bool flag; bool canwrite; bool terminate_thread; //flag for terminating the GetDirSize task @@ -53,7 +54,8 @@ private slots: //UI Buttons void on_push_close_clicked(); void on_push_save_clicked(); - //void stopVideo(QImage); + void stopVideo(QPixmap); + void setDuration(QMediaPlayer::MediaStatus); void getXdgCommand(QString prev = ""); //void on_tool_xdg_getCommand_clicked(QString prev = ""); void on_tool_xdg_getDir_clicked(); diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp index ee76a8dc..d0ecdecf 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/vidnail.cpp @@ -18,7 +18,7 @@ struct vFrame { public: QString getCodec(); - void goto(int timeInSeconds); + void skipTo(int timeInSeconds); void readVideoFrame(); void getScaledVideoFrame(int scaledSize, vFrame& vFrame); @@ -35,14 +35,12 @@ public: private: - bool readVideoPacket(); bool getVideoPacket(); void scaleVideo(int scaledSize, int& scaledWidth, int& scaledHeight); void createVFrame(AVFrame *vFrame, quint8 *frameBuffer, int width, int height); void calculateDimensions(int size); - void generateThumbnail(const QString& videoFile, ImageWriter& imageWriter, QImage& -image); + void generateThumbnail(const QString& videoFile, ImageWriter& imageWriter, QImage& image); QString getMimeType(const QString& videoFile); QString getExtension(const QString& videoFilename); -- cgit From 2a9d6daa5afa326cc9769d23a64345efeb891ea7 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Tue, 3 Oct 2017 18:44:22 -0400 Subject: Reworked the video thumnail system with lumina-fm --- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 29 ++++++++++------------------- src-qt5/desktop-utils/lumina-fm/Browser.h | 9 ++++----- 2 files changed, 14 insertions(+), 24 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index e57b6aed..bebb92e7 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -94,8 +94,8 @@ void Browser::dirChanged(QString dir){ else if(dir.startsWith(currentDir)){ QtConcurrent::run(this, &Browser::loadItem, dir, this ); } } -/*void Browser::stopVideo(QMediaPlayer *player, QMediaPlayer::MediaStatus status) { - qDebug() << status; +void Browser::stopVideo(QMediaPlayer *player, QMediaPlayer::MediaStatus status) { + //qDebug() << status; if(status == QMediaPlayer::BufferedMedia) { qDebug() << "stoppingVideo" << player << player->currentMedia().canonicalUrl(); player->setPosition(player->duration() / 2); @@ -103,11 +103,11 @@ void Browser::dirChanged(QString dir){ } } -void Browser::captureFrame(QImage pix) { +void Browser::captureFrame(QPixmap pix) { qDebug() << "grabbing frame"; videoFrame = pix.scaledToHeight(64); emit frameChanged(); -}*/ +} void Browser::futureFinished(QString name, QImage icon){ //Note: this will be called once for every item that loads @@ -120,29 +120,20 @@ void Browser::futureFinished(QString name, QImage icon){ if(ico.isNull()){ if(videoFormats.contains(name.section(".",-1).toLower())) { qDebug() << "Loading Video for" << name; - qDebug() << "VIDEO" << info; - //qDebug() << obj << this << QThread::currentThread(); + //qDebug() << "VIDEO" << info; QMediaPlayer *player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); qDebug() << " - created player"; LVideoSurface *surface = new LVideoSurface(); qDebug() << " - Create objects"; - //connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(captureFrame(QImage))); - //connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); + connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(captureFrame(QPixmap))); + connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); player->setVideoOutput(surface); - player->setVolume(0); + player->setMuted(true); player->setMedia(QUrl("file://"+info->absoluteFilePath())); player->play(); - qDebug() << "Wait for buffer"; - while(player->mediaStatus()!=QMediaPlayer::BufferedMedia){ - QCoreApplication::processEvents(); - } player->pause(); - player->setPosition(player->duration()/2); - while(!surface->frameReady()) { - QCoreApplication::processEvents(); - } - qDebug() << "Load Frame"; - ico.addPixmap(QPixmap::fromImage(surface->currentFrame())); + //ico.addPixmap(videoFrame); + ico = loadIcon(info->iconfile()); delete player; delete surface; }else { diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.h b/src-qt5/desktop-utils/lumina-fm/Browser.h index 7ccb5199..2dfae0be 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.h +++ b/src-qt5/desktop-utils/lumina-fm/Browser.h @@ -45,7 +45,7 @@ public: private: QString currentDir; QFileSystemWatcher *watcher; - //QImage videoFrame; + QPixmap videoFrame; bool showHidden, showThumbs; QStringList imageFormats, videoFormats, oldFiles; QHash mimeIcons; //cache for quickly re-using QIcons @@ -56,13 +56,12 @@ private: private slots: void fileChanged(QString); //tied into the watcher - for file change notifications void dirChanged(QString); // tied into the watcher - for new/removed files in the current dir - //void captureFrame(QImage); - //void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); + void captureFrame(QPixmap); + void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); void futureFinished(QString, QImage); public slots: void loadDirectory(QString dir = ""); - signals: //Main Signals void itemRemoved(QString item); //emitted if a file was removed from the underlying @@ -75,7 +74,7 @@ signals: //Internal signal for the alternate threads void threadDone(QString, QImage); - //void frameChanged(); + void frameChanged(); }; #endif -- cgit From 7de2db7ab54f9c82eaa8b2a494a745c37923f4db Mon Sep 17 00:00:00 2001 From: Coupon Date: Tue, 3 Oct 2017 20:45:30 -0400 Subject: Further lumina-fm changes for video thumbnails --- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 27 ++++++++++++++++----------- src-qt5/desktop-utils/lumina-fm/Browser.h | 4 ++-- 2 files changed, 18 insertions(+), 13 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index bebb92e7..211ef8d0 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -71,12 +71,12 @@ void Browser::loadItem(QString info, Browser *obj){ obj->emit threadDone(info, pix); } -QIcon Browser::loadIcon(QString icon){ +QIcon* Browser::loadIcon(QString icon){ if(!mimeIcons.contains(icon)){ mimeIcons.insert(icon, LXDG::findIcon(icon, "unknown")); } - return mimeIcons[icon]; + return &mimeIcons[icon]; } @@ -103,21 +103,21 @@ void Browser::stopVideo(QMediaPlayer *player, QMediaPlayer::MediaStatus status) } } -void Browser::captureFrame(QPixmap pix) { +void Browser::captureFrame(QPixmap pix, QIcon *ico) { qDebug() << "grabbing frame"; - videoFrame = pix.scaledToHeight(64); + *ico = pix.scaledToHeight(64); emit frameChanged(); } void Browser::futureFinished(QString name, QImage icon){ //Note: this will be called once for every item that loads - QIcon ico; + QIcon *ico = new QIcon(); LFileInfo *info = new LFileInfo(name); if(!icon.isNull() && showThumbs){ QPixmap pix = QPixmap::fromImage(icon); - ico.addPixmap(pix); + ico->addPixmap(pix); } - if(ico.isNull()){ + if(ico->isNull()){ if(videoFormats.contains(name.section(".",-1).toLower())) { qDebug() << "Loading Video for" << name; //qDebug() << "VIDEO" << info; @@ -125,22 +125,27 @@ void Browser::futureFinished(QString name, QImage icon){ qDebug() << " - created player"; LVideoSurface *surface = new LVideoSurface(); qDebug() << " - Create objects"; - connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(captureFrame(QPixmap))); + connect(surface, &LVideoSurface::frameReceived, this, [&] (QPixmap pix) { captureFrame(pix, ico); }); connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); player->setVideoOutput(surface); player->setMuted(true); player->setMedia(QUrl("file://"+info->absoluteFilePath())); player->play(); player->pause(); - //ico.addPixmap(videoFrame); - ico = loadIcon(info->iconfile()); + + QEventLoop loop; + connect(this, SIGNAL(frameChanged()), &loop, SLOT(quit())); + loop.exec(); + + ico->addPixmap(videoFrame); + //ico = loadIcon(info->iconfile()); delete player; delete surface; }else { ico = loadIcon(info->iconfile()); } } - this->emit itemDataAvailable( ico, info); + this->emit itemDataAvailable( *ico, info); //qDebug() << " -- done:" << name; } diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.h b/src-qt5/desktop-utils/lumina-fm/Browser.h index 2dfae0be..379753ab 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.h +++ b/src-qt5/desktop-utils/lumina-fm/Browser.h @@ -51,12 +51,12 @@ private: QHash mimeIcons; //cache for quickly re-using QIcons void loadItem(QString info, Browser *obj); //this is the main loader class - multiple instances each run in a separate thread - QIcon loadIcon(QString icon); //simplification for using/populating the mimIcons cache + QIcon* loadIcon(QString icon); //simplification for using/populating the mimIcons cache private slots: void fileChanged(QString); //tied into the watcher - for file change notifications void dirChanged(QString); // tied into the watcher - for new/removed files in the current dir - void captureFrame(QPixmap); + void captureFrame(QPixmap, QIcon*); void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); void futureFinished(QString, QImage); -- cgit From d731985427420c462d845b4279b14238e5527cae Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 4 Oct 2017 09:51:31 -0400 Subject: Finish up the auto archive/extract within lumina-archiver (with JT) --- src-qt5/desktop-utils/lumina-archiver/MainUI.cpp | 75 ++++++++++++++-------- src-qt5/desktop-utils/lumina-archiver/MainUI.h | 17 ++--- .../desktop-utils/lumina-archiver/TarBackend.cpp | 5 +- src-qt5/desktop-utils/lumina-archiver/TarBackend.h | 2 +- 4 files changed, 59 insertions(+), 40 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp index 9d220824..215fc64e 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp @@ -20,7 +20,11 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ ui->setupUi(this); - auto_extract_close = false; + delayClose = new QTimer(this); + delayClose->setInterval(500); + delayClose->setSingleShot(true); + connect(delayClose, SIGNAL(timeout()), this, SLOT(close()) ); + QString title = tr("Archive Manager"); if( getuid()==0){ title.append(" ("+tr("Admin Mode")+")"); } this->setWindowTitle(title); @@ -70,33 +74,34 @@ MainUI::~MainUI(){ } void MainUI::LoadArguments(QStringList args){ - bool burnIMG = false; - bool autoExtract = false; - //bool autoArchive = false; + int action = -1; // 0: burnIMG, 1: autoExtract, 2: autoArchive + QStringList files; for(int i=0; ilabel_progress->setText(tr("Opening Archive...")); - if(autoExtract){ - connect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); - connect(BACKEND, SIGNAL(ExtractSuccessful()), this, SLOT(close()) ); - } - BACKEND->loadFile(args[i]); - ui->actionUSB_Image->setEnabled(args[i].simplified().endsWith(".img")); - if(burnIMG){ BurnImgToUSB(); } //Go ahead and launch the burn dialog right away - break; + if(args[i].startsWith("--") ){ + if(action>=0){ break; } + else if(args[i]=="--burn-img"){ action = 0; continue; } + else if(args[i]=="--ax"){ action = 1; continue; } + else if(args[i]=="--aa"){ action = 2; continue; } + }else{ + files << args[i]; } - //if(autoArchive){ - //get rest of arguments - //for(int i=1; ilabel_progress->setText(tr("Opening Archive...")); + if(action==1){ + connect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); + connect(BACKEND, SIGNAL(ExtractSuccessful()), delayClose, SLOT(start()) ); + }else if(action==2){ + aaFileList.clear(); + for(int j=1; jloadFile(files[0]); + ui->actionUSB_Image->setEnabled(files[0].simplified().endsWith(".img")); + if(action==0){ BurnImgToUSB(); } //Go ahead and launch the burn dialog right away + } void MainUI::loadIcons(){ @@ -258,13 +263,27 @@ void MainUI::autoextractFiles(){ disconnect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); QString dir = BACKEND->currentFile().section("/",0,-2); //parent directory of the archive if(dir.isEmpty()){ return; } + QDir tmp(dir); + QString name = BACKEND->currentFile().section("/",-1).section(".",0,0); + if(QFile::exists(dir+"/"+name)){ + int num = 1; + while( QFile::exists(dir+"/"+name+"_"+QString::number(num))){ num++; } + name = name+"_"+QString::number(num); + } + if(tmp.mkdir(name) ){ + dir.append("/"+name); //created sub directory + } ui->label_progress->setText(tr("Extracting...")); BACKEND->startExtract(dir, true); } -/* -void MainUI::autoArchiveFiles(aaFileList){ -*/ + +void MainUI::autoArchiveFiles(){ + qDebug() << "Auto Archive Files:" << aaFileList; + ui->label_progress->setText(tr("Adding Items...")); + BACKEND->startAdd(aaFileList); +} + void MainUI::extractSelection(){ if(ui->tree_contents->currentItem()==0){ return; } //nothing selected diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.h b/src-qt5/desktop-utils/lumina-archiver/MainUI.h index a2687895..a16d5862 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.h +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "TarBackend.h" @@ -24,20 +25,20 @@ public: ~MainUI(); void LoadArguments(QStringList); - void loadIcons(); - //QStringList aaFileList; + void loadIcons(); private: Ui::MainUI *ui; Backend *BACKEND; - bool auto_extract_close; + QStringList aaFileList; + QTimer *delayClose; QTreeWidgetItem* findItem(QString path, QTreeWidgetItem *start = 0); bool cleanItems(QStringList list, QTreeWidgetItem *start = 0); //returns true if anything gets cleaned //Functions for setting the valid file extensions ("tar" limitations) QString CreateFileTypes(); - QString OpenFileTypes(); + QString OpenFileTypes(); private slots: void NewArchive(); @@ -45,14 +46,14 @@ private slots: void addFiles(); void addDirs(); void remFiles(); - void extractFiles(); - void autoextractFiles(); - //void autoArchiveFiles(QStringList aaFileList); + void extractFiles(); + void autoextractFiles(); + void autoArchiveFiles(); void extractSelection(); void ViewFile(QTreeWidgetItem *it); void UpdateTree(); - void BurnImgToUSB(); + void BurnImgToUSB(); //Backend Handling void ProcStarting(); diff --git a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp index e0b802a4..f110624b 100644 --- a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp @@ -36,7 +36,7 @@ void Backend::loadFile(QString path){ flags.clear(); flags << "-f" << filepath; //add the actual archive path if(QFile::exists(path)){ startList(); qDebug () << "BACKEND LOAD startList has started";} - else{ contents.clear(); emit ProcessFinished(true, ""); } + else{ contents.clear(); emit FileLoaded(); emit ProcessFinished(true, ""); } } bool Backend::canModify(){ @@ -262,8 +262,7 @@ void Backend::procFinished(int retcode, QProcess::ExitStatus){ } } if(args.contains("-x")){ result = tr("Extraction Finished"); emit ExtractSuccessful(); } - //if(args.contains("-aa")){ result = tr("Archival Finished"); emit ArchivalSuccessful(); } - else if(args.contains("-c")){ result = tr("Modification Finished"); } + else if(args.contains("-c")){ result = tr("Modification Finished"); emit ArchivalSuccessful(); } if(needupdate){ startList(); } else{ emit ProcessFinished(retcode==0, result); result.clear(); } } diff --git a/src-qt5/desktop-utils/lumina-archiver/TarBackend.h b/src-qt5/desktop-utils/lumina-archiver/TarBackend.h index d86ecf7c..183cb610 100644 --- a/src-qt5/desktop-utils/lumina-archiver/TarBackend.h +++ b/src-qt5/desktop-utils/lumina-archiver/TarBackend.h @@ -64,7 +64,7 @@ signals: void ProcessStarting(); void ProgressUpdate(int, QString); //percentage, text void ProcessFinished(bool, QString); //success, text - //void ArchivalSuccessful(); + void ArchivalSuccessful(); }; #endif -- cgit From 79fbc99707377264761434b44147281457189691 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Thu, 5 Oct 2017 17:06:58 -0400 Subject: Finished video thumnails for lumina-fm and lumina-fileinfo --- src-qt5/core/libLumina/LVideoSurface.cpp | 2 +- src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 9 ++- src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 2 + src-qt5/desktop-utils/lumina-fm/Browser.cpp | 97 ++++++++++++++---------- src-qt5/desktop-utils/lumina-fm/Browser.h | 2 +- 5 files changed, 70 insertions(+), 42 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoSurface.cpp b/src-qt5/core/libLumina/LVideoSurface.cpp index 895a3a32..bd6b2c95 100644 --- a/src-qt5/core/libLumina/LVideoSurface.cpp +++ b/src-qt5/core/libLumina/LVideoSurface.cpp @@ -12,7 +12,7 @@ bool LVideoSurface::present(const QVideoFrame &frame) { } if(frame.isValid()) { - qDebug() << "Recording Frame" << frame.pixelFormat(); + //qDebug() << "Recording Frame" << frame.pixelFormat(); QVideoFrame icon(frame); icon.map(QAbstractVideoBuffer::ReadOnly); QImage img(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat())); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index 40d2d544..0fb736d3 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -25,6 +25,7 @@ MainUI::MainUI() : QDialog(), ui(new Ui::MainUI){ SetupConnections(); player = new QMediaPlayer(this, QMediaPlayer::VideoSurface); surface = new LVideoSurface(this); + qDebug() << surface->surfaceFormat(); player->setVideoOutput(surface); player->setMuted(true); connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus))); @@ -96,7 +97,11 @@ void MainUI::LoadFile(QString path, QString type){ ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); //qDebug() << " - done with image"; }else if(INFO->isVideo()){ - player->setMedia(QUrl("file://"+INFO->absoluteFilePath())); + timer.start(); + QMediaResource video = QMediaResource(QUrl("file://"+INFO->absoluteFilePath())); + video.setResolution(64,64); + player->setMedia(video); + //player->setMedia(QUrl("file://"+INFO->absoluteFilePath())); player->play(); player->pause(); //Pixmap set when video is loaded in stopVideo @@ -313,6 +318,8 @@ void MainUI::getXdgCommand(QString prev){ void MainUI::stopVideo(QPixmap img) { ui->label_file_icon->setPixmap( img.scaledToHeight(64) ); player->pause(); + qDebug() << timer.elapsed(); + qDebug() << player->media().canonicalResource().resolution(); } void MainUI::setDuration(QMediaPlayer::MediaStatus status) { diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index 5ce7b01a..3bc85aae 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Ui{ class MainUI; }; @@ -38,6 +39,7 @@ private: LVideoSurface *surface; QMediaPlayer *player; bool flag; + QElapsedTimer timer; bool canwrite; bool terminate_thread; //flag for terminating the GetDirSize task diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index 211ef8d0..e0e79d04 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -66,6 +66,8 @@ void Browser::loadItem(QString info, Browser *obj){ pix = pix.scaled(256,256, Qt::KeepAspectRatio); } } + }else if(videoFormats.contains(info.section(".",-1).toLower()) ){ + videoList.push_back(info); } qDebug() << " - done with item:" << info; obj->emit threadDone(info, pix); @@ -97,60 +99,77 @@ void Browser::dirChanged(QString dir){ void Browser::stopVideo(QMediaPlayer *player, QMediaPlayer::MediaStatus status) { //qDebug() << status; if(status == QMediaPlayer::BufferedMedia) { - qDebug() << "stoppingVideo" << player << player->currentMedia().canonicalUrl(); + //qDebug() << "stoppingVideo" << player << player->currentMedia().canonicalUrl(); player->setPosition(player->duration() / 2); player->pause(); } } void Browser::captureFrame(QPixmap pix, QIcon *ico) { - qDebug() << "grabbing frame"; - *ico = pix.scaledToHeight(64); - emit frameChanged(); + static int received = 0; + //qDebug() << "grabbing frame" << received+1; + *ico = pix/*.scaledToHeight(64)*/; + if(++received == videoList.size()) { + emit frameChanged(); + received = 0; + } } void Browser::futureFinished(QString name, QImage icon){ //Note: this will be called once for every item that loads - QIcon *ico = new QIcon(); - LFileInfo *info = new LFileInfo(name); - if(!icon.isNull() && showThumbs){ - QPixmap pix = QPixmap::fromImage(icon); - ico->addPixmap(pix); - } - if(ico->isNull()){ - if(videoFormats.contains(name.section(".",-1).toLower())) { - qDebug() << "Loading Video for" << name; - //qDebug() << "VIDEO" << info; - QMediaPlayer *player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); - qDebug() << " - created player"; - LVideoSurface *surface = new LVideoSurface(); - qDebug() << " - Create objects"; - connect(surface, &LVideoSurface::frameReceived, this, [&] (QPixmap pix) { captureFrame(pix, ico); }); - connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); - player->setVideoOutput(surface); - player->setMuted(true); - player->setMedia(QUrl("file://"+info->absoluteFilePath())); - player->play(); - player->pause(); - - QEventLoop loop; - connect(this, SIGNAL(frameChanged()), &loop, SLOT(quit())); - loop.exec(); - - ico->addPixmap(videoFrame); - //ico = loadIcon(info->iconfile()); - delete player; - delete surface; - }else { - ico = loadIcon(info->iconfile()); - } + QIcon *ico = new QIcon(); + LFileInfo *info = new LFileInfo(name); + if(!icon.isNull() && showThumbs){ + QPixmap pix = QPixmap::fromImage(icon); + ico->addPixmap(pix); + } + if(ico->isNull()){ + if(videoFormats.contains(name.section(".",-1).toLower())) { + QElapsedTimer loadingTime; + //qDebug() << videoList; + //videoList.add(name); + //qDebug() << "Loading Video for" << name; + //qDebug() << "VIDEO" << info; + QMediaPlayer *player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); + //qDebug() << " - created player" << player; + LVideoSurface *surface = new LVideoSurface(); + //qDebug() << " - Create objects"; + connect(surface, &LVideoSurface::frameReceived, this, [&] (QPixmap pix) { captureFrame(pix, ico); }); + connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); + player->setVideoOutput(surface); + player->setMuted(true); + QMediaResource video = QMediaResource(QUrl("file://"+info->absoluteFilePath())); + video.setResolution(QSize(64, 64)); + player->setMedia(video); + //player->setMedia(QUrl("file://"+info->absoluteFilePath())); + player->play(); + player->pause(); + + //qDebug() << "Started loop"; + loadingTime.start(); + QTimer timeout; + timeout.setSingleShot(true); + timeout.setInterval(5000); + QEventLoop loop; + connect(this, SIGNAL(frameChanged()), &loop, SLOT(quit()), Qt::DirectConnection); + connect(&timeout, SIGNAL(timeout()), &loop, SLOT(quit())); + loop.exec(); + //qDebug() << "Exited loop"; + + qDebug() << loadingTime.elapsed(); + delete player; + delete surface; + }else { + ico = loadIcon(info->iconfile()); } - this->emit itemDataAvailable( *ico, info); - //qDebug() << " -- done:" << name; + } + this->emit itemDataAvailable( *ico, info); + //qDebug() << " -- done:" << name; } // PUBLIC SLOTS void Browser::loadDirectory(QString dir){ + videoList.clear(); if(dir.isEmpty()){ dir = currentDir; } //reload current directory if(dir.isEmpty()){ return; } //nothing to do - nothing previously loaded //qDebug() << "Load Directory" << dir; diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.h b/src-qt5/desktop-utils/lumina-fm/Browser.h index 379753ab..004bf046 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.h +++ b/src-qt5/desktop-utils/lumina-fm/Browser.h @@ -45,7 +45,7 @@ public: private: QString currentDir; QFileSystemWatcher *watcher; - QPixmap videoFrame; + QList videoList; bool showHidden, showThumbs; QStringList imageFormats, videoFormats, oldFiles; QHash mimeIcons; //cache for quickly re-using QIcons -- cgit From 7c986120915920c18a85397cd81c73df65a1eafb Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 6 Oct 2017 09:23:11 -0400 Subject: Try to ensure that the transient QApplication for user file checks/updates is completely deleted. --- src-qt5/core/lumina-desktop/LSession.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index d1d6588e..0acd7303 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -391,12 +391,13 @@ void LSession::checkUserFiles(){ QString OVS = sset.value("DesktopVersion","0").toString(); //Old Version String char *tmp; int tmpN = 0; - QApplication A(tmpN, &tmp); + QApplication *A = new QApplication(tmpN, &tmp); bool changed = LDesktopUtils::checkUserFiles(OVS, LDesktopUtils::LuminaDesktopVersion()); if(changed){ //Save the current version of the session to the settings file (for next time) sset.setValue("DesktopVersion", LDesktopUtils::LuminaDesktopVersion()); } + delete A; } void LSession::refreshWindowManager(){ -- cgit From 93b24e060f223126fdb1facdd39177ba8a726828 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 6 Oct 2017 09:55:43 -0400 Subject: Add a new testing utility for trying out QML files --- src-qt5/src-qml/test/main.cpp | 27 +++++++++++++++++++++++++++ src-qt5/src-qml/test/test.pro | 5 +++++ 2 files changed, 32 insertions(+) create mode 100644 src-qt5/src-qml/test/main.cpp create mode 100644 src-qt5/src-qml/test/test.pro (limited to 'src-qt5') diff --git a/src-qt5/src-qml/test/main.cpp b/src-qt5/src-qml/test/main.cpp new file mode 100644 index 00000000..eabe7dc5 --- /dev/null +++ b/src-qt5/src-qml/test/main.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +int main(int argc, char** argv){ + QString QMLFile; + for(int i=1; i Date: Mon, 9 Oct 2017 10:53:54 -0400 Subject: Add a few test QML files which work to the src-qml directory. --- src-qt5/src-qml/CPUGaugeStyle.qml | 156 ++++++++++++++++++++++++++++++++++++++ src-qt5/src-qml/Clock.qml | 101 ++++++++++++++++++++++++ src-qt5/src-qml/test-basic.qml | 48 ++++++++++++ src-qt5/src-qml/test-cpugauge.qml | 108 ++++++++++++++++++++++++++ src-qt5/src-qml/test/test.pro | 2 +- 5 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 src-qt5/src-qml/CPUGaugeStyle.qml create mode 100644 src-qt5/src-qml/Clock.qml create mode 100644 src-qt5/src-qml/test-basic.qml create mode 100644 src-qt5/src-qml/test-cpugauge.qml (limited to 'src-qt5') diff --git a/src-qt5/src-qml/CPUGaugeStyle.qml b/src-qt5/src-qml/CPUGaugeStyle.qml new file mode 100644 index 00000000..4728d136 --- /dev/null +++ b/src-qt5/src-qml/CPUGaugeStyle.qml @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls.Styles 1.4 + +CircularGaugeStyle { + id: cpugauge + tickmarkInset: toPixels(0.04) + minorTickmarkInset: tickmarkInset + labelStepSize: 20 + labelInset: toPixels(0.23) + + property real xCenter: outerRadius + property real yCenter: outerRadius + property real needleLength: outerRadius - tickmarkInset * 1.25 + property real needleTipWidth: toPixels(0.02) + property real needleBaseWidth: toPixels(0.06) + property bool halfGauge: false + + function toPixels(percentage) { + return percentage * outerRadius; + } + + function degToRad(degrees) { + return degrees * (Math.PI / 180); + } + + function radToDeg(radians) { + return radians * (180 / Math.PI); + } + + function paintBackground(ctx) { + if (halfGauge) { + ctx.beginPath(); + ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height / 2); + ctx.clip(); + } + + ctx.beginPath(); + ctx.fillStyle = "black"; + ctx.ellipse(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.fill(); + + ctx.beginPath(); + ctx.lineWidth = tickmarkInset; + ctx.strokeStyle = "black"; + ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); + ctx.stroke(); + + ctx.beginPath(); + ctx.lineWidth = tickmarkInset / 2; + ctx.strokeStyle = "#222"; + ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); + ctx.stroke(); + + ctx.beginPath(); + var gradient = ctx.createRadialGradient(xCenter, yCenter, outerRadius * 0.8, xCenter, yCenter, outerRadius); + gradient.addColorStop(0, Qt.rgba(1, 1, 1, 0)); + gradient.addColorStop(0.7, Qt.rgba(1, 1, 1, 0.13)); + gradient.addColorStop(1, Qt.rgba(1, 1, 1, 1)); + ctx.fillStyle = gradient; + ctx.arc(xCenter, yCenter, outerRadius - tickmarkInset, outerRadius - tickmarkInset, 0, Math.PI * 2); + ctx.fill(); + } + + background: Canvas { + onPaint: { + var ctx = getContext("2d"); + ctx.reset(); + paintBackground(ctx); + } + + } + + needle: Canvas { + implicitWidth: needleBaseWidth + implicitHeight: needleLength + + property real xCenter: width / 2 + property real yCenter: height / 2 + + onPaint: { + var ctx = getContext("2d"); + ctx.reset(); + + ctx.beginPath(); + ctx.moveTo(xCenter, height); + ctx.lineTo(xCenter - needleBaseWidth / 2, height - needleBaseWidth / 2); + ctx.lineTo(xCenter - needleTipWidth / 2, 0); + ctx.lineTo(xCenter, yCenter - needleLength); + ctx.lineTo(xCenter, 0); + ctx.closePath(); + ctx.fillStyle = Qt.rgba(0.66, 0, 0, 0.66); + ctx.fill(); + + ctx.beginPath(); + ctx.moveTo(xCenter, height) + ctx.lineTo(width, height - needleBaseWidth / 2); + ctx.lineTo(xCenter + needleTipWidth / 2, 0); + ctx.lineTo(xCenter, 0); + ctx.closePath(); + ctx.fillStyle = Qt.lighter(Qt.rgba(0.66, 0, 0, 0.66)); + ctx.fill(); + } + } + + foreground: null +} diff --git a/src-qt5/src-qml/Clock.qml b/src-qt5/src-qml/Clock.qml new file mode 100644 index 00000000..685346cb --- /dev/null +++ b/src-qt5/src-qml/Clock.qml @@ -0,0 +1,101 @@ +import QtQuick 2.0 +import QtGraphicalEffects 1.0 + +Item { + id : clock + width: { + if (ListView.view && ListView.view.width >= 400) + return ListView.view.width / Math.floor(ListView.view.width / 400.0); + else + return 400; + } + + height: { + if (ListView.view && ListView.view.height >= 440) + return ListView.view.height; + else + return 440; + } + + property alias city: cityLabel.text + property int hours + property int minutes + property int seconds + property real shift + property bool night: false + property bool internationalTime: true //Unset for local time + + function timeChanged() { + var date = new Date; + hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours() + night = ( hours < 7 || hours > 19 ) + minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes() + seconds = date.getUTCSeconds(); + } + + Timer { + interval: 100; running: true; repeat: true; + onTriggered: clock.timeChanged() + } + + Item { + anchors.centerIn: parent + width: 200; height: 240 + Rectangle { anchors.fill: parent; color: "#80ff0000"; border.color: "red"; } + + Image { id: background; source: "clock.png"; visible: clock.night == false } + Image { source: "clock-night.png"; visible: clock.night == true } + + Image { + x: 92.5; y: 27 + source: "hour.png" + transform: Rotation { + id: hourRotation + origin.x: 7.5; origin.y: 73; + angle: (clock.hours * 30) + (clock.minutes * 0.5) + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + x: 93.5; y: 17 + source: "minute.png" + transform: Rotation { + id: minuteRotation + origin.x: 6.5; origin.y: 83; + angle: clock.minutes * 6 + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + x: 97.5; y: 20 + source: "second.png" + transform: Rotation { + id: secondRotation + origin.x: 2.5; origin.y: 80; + angle: clock.seconds * 6 + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + anchors.centerIn: background; source: "center.png" + } + + Text { + id: cityLabel + y: 210; anchors.horizontalCenter: parent.horizontalCenter + color: "white" + font.family: "Helvetica" + font.bold: true; font.pixelSize: 16 + style: Text.Raised; styleColor: "black" + } + } +} diff --git a/src-qt5/src-qml/test-basic.qml b/src-qt5/src-qml/test-basic.qml new file mode 100644 index 00000000..5d21ae41 --- /dev/null +++ b/src-qt5/src-qml/test-basic.qml @@ -0,0 +1,48 @@ +import QtQuick 2.0 +import "." as QML + +Rectangle { + id: root + width: 800; height: 600 + color: "#646464" + + ListView { + id: clockview + anchors.fill: parent + orientation: ListView.Horizontal + cacheBuffer: 2000 + snapMode: ListView.SnapOneItem + highlightRangeMode: ListView.ApplyRange + + delegate: QML.Clock { city: cityName; shift: timeShift } + model: ListModel { + ListElement { cityName: "New York"; timeShift: -4 } + ListElement { cityName: "London"; timeShift: 0 } + ListElement { cityName: "Oslo"; timeShift: 1 } + ListElement { cityName: "Mumbai"; timeShift: 5.5 } + ListElement { cityName: "Tokyo"; timeShift: 9 } + ListElement { cityName: "Brisbane"; timeShift: 10 } + ListElement { cityName: "Los Angeles"; timeShift: -8 } + } + } + + Image { + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.margins: 10 + source: "content/arrow.png" + rotation: -90 + opacity: clockview.atXBeginning ? 0 : 0.5 + Behavior on opacity { NumberAnimation { duration: 500 } } + } + + Image { + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 10 + source: "content/arrow.png" + rotation: 90 + opacity: clockview.atXEnd ? 0 : 0.5 + Behavior on opacity { NumberAnimation { duration: 500 } } + } +} diff --git a/src-qt5/src-qml/test-cpugauge.qml b/src-qt5/src-qml/test-cpugauge.qml new file mode 100644 index 00000000..1151c435 --- /dev/null +++ b/src-qt5/src-qml/test-cpugauge.qml @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Window 2.1 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Extras 1.4 + +import "." as QML + +Rectangle{ + id: rootwindow + visible: true + width: 800 + height: 600 + + color: "#161616" + property alias cpu: cpu + + Item { + id: container + anchors.fill: parent + property real diff: 5.1 + + Row { + id: gaugeRow + spacing: container.width * 0.02 + anchors.centerIn: parent + + CircularGauge { + id: cpu + width: height + height: container.height * 0.9 - gaugeRow.spacing + value: 0 + maximumValue: 100 + anchors.verticalCenter: parent.verticalCenter + + style: QML.CPUGaugeStyle {} + + } + + function updatevalue() { + if( container.diff >0 && cpu.value > (100-container.diff) ){ + cpu.value = 100; + container.diff = 0 - container.diff + } else if( container.diff <0 && cpu.value <(0-container.diff) ){ + cpu.value = 0; + container.diff = 0 - container.diff + } else { + cpu.value = cpu.value + container.diff + } + } + + Timer { + interval: 100; running: true; repeat: true; + onTriggered: gaugeRow.updatevalue() + } + } + } +} diff --git a/src-qt5/src-qml/test/test.pro b/src-qt5/src-qml/test/test.pro index 4470adea..41d7d2a2 100644 --- a/src-qt5/src-qml/test/test.pro +++ b/src-qt5/src-qml/test/test.pro @@ -1,4 +1,4 @@ -QT = core gui widgets quick quickwidgets +QT = core gui widgets quick quickwidgets qml TARGET = test -- cgit From 860d2ca1863f3838b5575c6efc2151a7270b0d79 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 9 Oct 2017 16:06:38 -0400 Subject: Clean up how the backend of the file manager handles atomic updates to changes in the current directory. This speeds up sequential re-scans considerably. --- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 43 +++++++++++++++------- src-qt5/desktop-utils/lumina-fm/Browser.h | 10 +++-- src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp | 10 ++--- src-qt5/desktop-utils/lumina-fm/BrowserWidget.h | 2 +- .../desktop-utils/lumina-fm/widgets/DirWidget2.cpp | 2 +- 5 files changed, 42 insertions(+), 25 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index e0e79d04..4665ccc4 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -35,6 +35,7 @@ QString Browser::currentDirectory(){ return currentDir; } void Browser::showHiddenFiles(bool show){ if(show !=showHidden){ showHidden = show; + lastcheck = QDateTime(); //reset this timestamp - need to reload all if(!currentDir.isEmpty()){ QTimer::singleShot(0, this, SLOT(loadDirectory()) ); } } } @@ -45,6 +46,7 @@ bool Browser::showingHiddenFiles(){ void Browser::showThumbnails(bool show){ if(show != showThumbs){ showThumbs = show; + lastcheck = QDateTime(); //reset this timestamp - need to reload all if(!currentDir.isEmpty()){ QTimer::singleShot(0, this, SLOT(loadDirectory()) ); } } } @@ -69,7 +71,7 @@ void Browser::loadItem(QString info, Browser *obj){ }else if(videoFormats.contains(info.section(".",-1).toLower()) ){ videoList.push_back(info); } - qDebug() << " - done with item:" << info; + //qDebug() << " - done with item:" << info; obj->emit threadDone(info, pix); } @@ -84,15 +86,19 @@ QIcon* Browser::loadIcon(QString icon){ // PRIVATE SLOTS void Browser::fileChanged(QString file){ - if(file.startsWith(currentDir+"/") ){ + //qDebug() << "Got File Changed:" << file; + if(file.section("/",0,-2) == currentDir){ if(QFile::exists(file) ){ QtConcurrent::run(this, &Browser::loadItem, file, this); } //file modified but not removed - else{ QTimer::singleShot(0, this, SLOT(loadDirectory()) ); } //file removed - need to update entire dir - }else if(file==currentDir){ QTimer::singleShot(0, this, SLOT(loadDirectory()) ); } + else if(oldFiles.contains(file) ){ + oldFiles.removeAll(file); + emit itemRemoved(file); + } + }//else if(file==currentDir){ QTimer::singleShot(0, this, SLOT(loadDirectory()) ); } } void Browser::dirChanged(QString dir){ - - if(dir==currentDir){ QTimer::singleShot(500, this, SLOT(loadDirectory()) ); } + //qDebug() << "Got Dir Changed:" << dir; + if(dir==currentDir){ QTimer::singleShot(10, this, SLOT(loadDirectory()) ); } else if(dir.startsWith(currentDir)){ QtConcurrent::run(this, &Browser::loadItem, dir, this ); } } @@ -109,7 +115,7 @@ void Browser::captureFrame(QPixmap pix, QIcon *ico) { static int received = 0; //qDebug() << "grabbing frame" << received+1; *ico = pix/*.scaledToHeight(64)*/; - if(++received == videoList.size()) { + if(++received == videoList.size()) { emit frameChanged(); received = 0; } @@ -145,7 +151,7 @@ void Browser::futureFinished(QString name, QImage icon){ player->play(); player->pause(); - //qDebug() << "Started loop"; + //qDebug() << "Started loop"; loadingTime.start(); QTimer timeout; timeout.setSingleShot(true); @@ -154,7 +160,7 @@ void Browser::futureFinished(QString name, QImage icon){ connect(this, SIGNAL(frameChanged()), &loop, SLOT(quit()), Qt::DirectConnection); connect(&timeout, SIGNAL(timeout()), &loop, SLOT(quit())); loop.exec(); - //qDebug() << "Exited loop"; + //qDebug() << "Exited loop"; qDebug() << loadingTime.elapsed(); delete player; @@ -168,16 +174,21 @@ void Browser::futureFinished(QString name, QImage icon){ } // PUBLIC SLOTS -void Browser::loadDirectory(QString dir){ +void Browser::loadDirectory(QString dir, bool force){ + if(force){ lastcheck = QDateTime(); } //reset check time to force reloads videoList.clear(); if(dir.isEmpty()){ dir = currentDir; } //reload current directory if(dir.isEmpty()){ return; } //nothing to do - nothing previously loaded //qDebug() << "Load Directory" << dir; + bool dirupdate = true; if(currentDir != dir){ //let the main widget know to clear all current items (completely different dir) oldFiles.clear(); + lastcheck = QDateTime(); //null time emit clearItems(); + dirupdate = false; } currentDir = dir; //save this for later + QDateTime now = QDateTime::currentDateTime(); //clean up the watcher first QStringList watched; watched << watcher->files() << watcher->directories(); if(!watched.isEmpty()){ watcher->removePaths(watched); } @@ -189,15 +200,18 @@ void Browser::loadDirectory(QString dir){ QStringList files; if(showHidden){ files = directory.entryList( QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDir::NoSort); } else{ files = directory.entryList( QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::NoSort); } - emit itemsLoading(files.length()); + if(dirupdate){ emit itemsLoading(files.length()); } for(int i=0; iaddPath(directory.absoluteFilePath(files[i])); - //qDebug() << "Future Starting:" << files[i]; QString path = directory.absoluteFilePath(files[i]); - if(old.contains(path)){ old.removeAll(path); } oldFiles << path; //add to list for next time + bool reloaditem = !dirupdate || lastcheck.isNull() || (QFileInfo(path).lastModified() > lastcheck || QFileInfo(path).created() > lastcheck); + //if(dirupdate){ qDebug() << "Reload Item:" << reloaditem << path.section("/",-1); } + //reloaditem = true; + if(old.contains(path)){ old.removeAll(path); } //still in existance //if(showThumbs && imageFormats.contains(path.section(".",-1).toLower())){ - QtConcurrent::run(this, &Browser::loadItem, path, this); + //qDebug() << "Future Starting:" << files[i]; + if(reloaditem){ QtConcurrent::run(this, &Browser::loadItem, path, this); } /*}else{ //No special icon loading - just skip the file read step futureFinished(path, QImage()); //loadItem(path, this); @@ -213,4 +227,5 @@ void Browser::loadDirectory(QString dir){ }else{ emit itemsLoading(0); //nothing to load } + lastcheck = now; // save this for later } diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.h b/src-qt5/desktop-utils/lumina-fm/Browser.h index 004bf046..3254db54 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.h +++ b/src-qt5/desktop-utils/lumina-fm/Browser.h @@ -44,8 +44,9 @@ public: private: QString currentDir; + QDateTime lastcheck; QFileSystemWatcher *watcher; - QList videoList; + QList videoList; bool showHidden, showThumbs; QStringList imageFormats, videoFormats, oldFiles; QHash mimeIcons; //cache for quickly re-using QIcons @@ -56,12 +57,13 @@ private: private slots: void fileChanged(QString); //tied into the watcher - for file change notifications void dirChanged(QString); // tied into the watcher - for new/removed files in the current dir - void captureFrame(QPixmap, QIcon*); - void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); + void captureFrame(QPixmap, QIcon*); + void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); void futureFinished(QString, QImage); public slots: - void loadDirectory(QString dir = ""); + void loadDirectory(QString dir = "", bool force = false); + signals: //Main Signals void itemRemoved(QString item); //emitted if a file was removed from the underlying diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp index d5f219bb..d2c07648 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp @@ -24,7 +24,7 @@ BrowserWidget::BrowserWidget(QString objID, QWidget *parent) : QWidget(parent){ connect(BROWSER, SIGNAL(itemRemoved(QString)), this, SLOT(itemRemoved(QString)) ); connect(BROWSER, SIGNAL(itemDataAvailable(QIcon, LFileInfo*)), this, SLOT(itemDataAvailable(QIcon, LFileInfo*)) ); connect(BROWSER, SIGNAL(itemsLoading(int)), this, SLOT(itemsLoading(int)) ); - connect(this, SIGNAL(dirChange(QString)), BROWSER, SLOT(loadDirectory(QString)) ); + connect(this, SIGNAL(dirChange(QString, bool)), BROWSER, SLOT(loadDirectory(QString, bool)) ); listWidget = 0; treeWidget = 0; readDateFormat(); @@ -50,7 +50,7 @@ void BrowserWidget::changeDirectory(QString dir){ if( (historyList.isEmpty() || historyList.last()!=cleaned) && !cleaned.isEmpty() ){ historyList << cleaned; } } //qDebug() << "History:" << historyList; - emit dirChange(dir); + emit dirChange(dir, false); } void BrowserWidget::showDetails(bool show){ @@ -81,7 +81,7 @@ void BrowserWidget::showDetails(bool show){ connect(treeWidget, SIGNAL(GotFocus()), this, SLOT(selectionChanged()) ); retranslate(); treeWidget->sortItems(0, Qt::AscendingOrder); - if(!BROWSER->currentDirectory().isEmpty()){ emit dirChange(""); } + if(!BROWSER->currentDirectory().isEmpty()){ emit dirChange("", true); } }else if(!show && listWidget==0){ listWidget = new DDListWidget(this); listWidget->setContextMenuPolicy(Qt::CustomContextMenu); @@ -91,7 +91,7 @@ void BrowserWidget::showDetails(bool show){ connect(listWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SIGNAL(contextMenuRequested()) ); connect(listWidget, SIGNAL(DataDropped(QString, QStringList)), this, SIGNAL(DataDropped(QString, QStringList)) ); connect(listWidget, SIGNAL(GotFocus()), this, SLOT(selectionChanged()) ); - if(!BROWSER->currentDirectory().isEmpty()){ emit dirChange(""); } + if(!BROWSER->currentDirectory().isEmpty()){ emit dirChange("",true); } } //qDebug() << " Done making widget"; } @@ -127,7 +127,7 @@ void BrowserWidget::setThumbnailSize(int px){ } //qDebug() << "Changing Icon Size:" << px << larger; if(BROWSER->currentDirectory().isEmpty() || !larger ){ return; } //don't need to reload icons unless the new size is larger - emit dirChange(""); + emit dirChange("", larger); } int BrowserWidget::thumbnailSize(){ diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h index fafb3746..a9e58bf3 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h @@ -88,7 +88,7 @@ signals: void hasFocus(QString); //ID output //Internal signal - void dirChange(QString); //current dir path + void dirChange(QString, bool); //current dir path, force }; #endif diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp index 8273d09c..1b00343d 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp @@ -59,7 +59,7 @@ DirWidget::DirWidget(QString objID, QSettings *settings, QWidget *parent) : QWid RCBW = 0; //right column browser is unavailable initially BW = new BrowserWidget("", this); ui->browser_layout->addWidget(BW); - connect(BW, SIGNAL(dirChange(QString)), this, SLOT(currentDirectoryChanged()) ); + connect(BW, SIGNAL(dirChange(QString, bool)), this, SLOT(currentDirectoryChanged()) ); connect(BW, SIGNAL(itemsActivated()), this, SLOT(runFiles()) ); connect(BW, SIGNAL(DataDropped(QString, QStringList)), this, SIGNAL(PasteFiles(QString, QStringList)) ); connect(BW, SIGNAL(contextMenuRequested()), this, SLOT(OpenContextMenu()) ); -- cgit From 20373eb1665303d77c17d4b268b95e7a4b6ab440 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Mon, 9 Oct 2017 19:01:31 -0400 Subject: Read the default app desktop files from full path to fix settings persistance bug --- src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp index c2d689ec..df7ae516 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp @@ -245,7 +245,7 @@ void page_defaultapps::setdefaultitem(){ //Now set the items for(int i=0; iwhatsThis(0), app.section("/",-1)); + LXDG::setDefaultAppForMime(list[i]->whatsThis(0), app); //Set it in the UI XDGDesktop desk(app); list[i]->setWhatsThis(1,app); //app path -- cgit From 4723568e850cf593b2212054a766c5d7b6051739 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 9 Oct 2017 22:28:38 -0400 Subject: Remove the src-glwidgets tree. No longer needed since it has been replaced by the src-qml source tree. --- src-qt5/src-glwidgets/gltest/colorchange.h | 30 -------- src-qt5/src-glwidgets/gltest/main.cpp | 52 ------------- src-qt5/src-glwidgets/gltest/test | Bin 58272 -> 0 bytes src-qt5/src-glwidgets/gltest/test.pro | 9 --- src-qt5/src-glwidgets/glw-base.cpp | 120 ----------------------------- src-qt5/src-glwidgets/glw-base.h | 49 ------------ src-qt5/src-glwidgets/glw-widget.cpp | 115 --------------------------- src-qt5/src-glwidgets/glw-widget.h | 63 --------------- src-qt5/src-glwidgets/glwidgets.pri | 7 -- 9 files changed, 445 deletions(-) delete mode 100644 src-qt5/src-glwidgets/gltest/colorchange.h delete mode 100644 src-qt5/src-glwidgets/gltest/main.cpp delete mode 100755 src-qt5/src-glwidgets/gltest/test delete mode 100644 src-qt5/src-glwidgets/gltest/test.pro delete mode 100644 src-qt5/src-glwidgets/glw-base.cpp delete mode 100644 src-qt5/src-glwidgets/glw-base.h delete mode 100644 src-qt5/src-glwidgets/glw-widget.cpp delete mode 100644 src-qt5/src-glwidgets/glw-widget.h delete mode 100644 src-qt5/src-glwidgets/glwidgets.pri (limited to 'src-qt5') diff --git a/src-qt5/src-glwidgets/gltest/colorchange.h b/src-qt5/src-glwidgets/gltest/colorchange.h deleted file mode 100644 index aad01f05..00000000 --- a/src-qt5/src-glwidgets/gltest/colorchange.h +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include - -#include "../glw-base.h" - -class colorchange : public QObject{ - Q_OBJECT -private: - GLW_Base *base; - QTimer *timer; - -public slots: - void toggle(){ - static bool current = false; - base->setBackgroundColor( current ? QColor(Qt::blue) : QColor(Qt::red)); - current = !current; - } - -public: - colorchange(GLW_Base *parent) : QObject(){ - base = parent; - timer = new QTimer(this); - timer->setInterval(5000); - connect(timer, SIGNAL(timeout()), this, SLOT(toggle()) ); - timer->start(); - } - -}; diff --git a/src-qt5/src-glwidgets/gltest/main.cpp b/src-qt5/src-glwidgets/gltest/main.cpp deleted file mode 100644 index efcebea1..00000000 --- a/src-qt5/src-glwidgets/gltest/main.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include -#include -#include "../glw-base.h" -#include "../glw-widget.h" - -#include "colorchange.h" - -int main(int argc, char** argv){ - - QSurfaceFormat fmt; - fmt.setRenderableType(QSurfaceFormat::OpenGL); //OpenGL, OpenGLES, OpenVG - fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - QSurfaceFormat::setDefaultFormat(fmt); - - QApplication A(argc,argv); - - qDebug() << "Creating base widget"; - GLW_Base base; - qDebug() << "Resize base widget"; - base.resize(1024,768); - qDebug() << "Create Other widgets"; - GLW_Widget wgt1(&base); - wgt1.setGLBase(&base); - wgt1.setGeometry(50,50,50,50); - wgt1.setDraggable(true); - GLW_Widget wgt(&base); - wgt.setGLBase(&base); - wgt.setGeometry(75,50,50,50); - QPropertyAnimation anim(&wgt); - anim.setTargetObject(&wgt); - anim.setPropertyName("geometry"); - //anim.setStartValue(QRect(-50,-50,50,50)); - //anim.setEndValue(QRect(200,200,50,50)); - anim.setStartValue(QRect(base.width()/2,base.height()/2,0,0)); - anim.setEndValue(QRect(0,0,base.width(),base.height())); - anim.setDuration(1500); - anim.setLoopCount(-1); - anim.start(); - /*QPushButton but(&base); - but.setText("button"); - but.setGeometry(100,100,50,50); - but.setStyleSheet("background: rgba(0,150,0,125)");*/ - colorchange CC(&base); - qDebug() << "Start Event loop"; - base.show(); - int ret = A.exec(); - qDebug() << " - Finished"; - return ret; -} diff --git a/src-qt5/src-glwidgets/gltest/test b/src-qt5/src-glwidgets/gltest/test deleted file mode 100755 index 3ba6f8db..00000000 Binary files a/src-qt5/src-glwidgets/gltest/test and /dev/null differ diff --git a/src-qt5/src-glwidgets/gltest/test.pro b/src-qt5/src-glwidgets/gltest/test.pro deleted file mode 100644 index cba315c3..00000000 --- a/src-qt5/src-glwidgets/gltest/test.pro +++ /dev/null @@ -1,9 +0,0 @@ -QT = core gui widgets - -TARGET = test - -SOURCES += main.cpp - -HEADERS += colorchange.h - -include(../glwidgets.pri); diff --git a/src-qt5/src-glwidgets/glw-base.cpp b/src-qt5/src-glwidgets/glw-base.cpp deleted file mode 100644 index 4065f70f..00000000 --- a/src-qt5/src-glwidgets/glw-base.cpp +++ /dev/null @@ -1,120 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "glw-base.h" -#include "glw-widget.h" -#include -#include -#include -#include -#include - -GLW_Base::GLW_Base(QWidget *parent, Qt::WindowFlags f) : QOpenGLWidget(parent,f){ - bg_color = QColor(Qt::black); - mouse_over_child = 0; - qDebug() << "Canvas supports threaded OpenGL:" << this->context()->supportsThreadedOpenGL(); - qDebug() << " - globally:" << QOpenGLContext::globalShareContext()->supportsThreadedOpenGL(); -} - -GLW_Base::~GLW_Base(){ - -} - -QWidget * GLW_Base::mouseOverWidget(){ - return mouse_over_child; -} - -// --- PUBLIC SLOTS --- -void GLW_Base::setBackgroundColor(QColor color){ - bg_color = color; - this->update(); //repaint the entire widget (just in case you can see through the image) - -} - -void GLW_Base::setBackground(QRect geom, QImage img){ - QPainter P(&bg_img); - P.drawImage(geom, img); - this->update(geom); -} - -void GLW_Base::repaintArea(QRect rect){ - this->update(rect); -} - -void GLW_Base::setMouseOverWidget(QWidget *child){ - mouse_over_child = child; -} - -// --- PROTECTED --- -void GLW_Base::mouseMoveEvent(QMouseEvent *ev){ - mouse_over_child = 0; //reset this flag - mouse is over the base right now - QWidget::mouseMoveEvent(ev); -} - -void GLW_Base::resizeEvent(QResizeEvent *ev){ - QOpenGLWidget::resizeEvent(ev); - if(!bg_img.isNull()){ - bg_img = bg_img.scaled(ev->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - } - emit BaseResized(); -} - -/*void GLW_Base::paintEvent(QPaintEvent *ev){ - QOpenGLWidget::paintEvent(ev); -}*/ - -void GLW_Base::paintGL(){ - - //Setup the OpenGL stuff - QOpenGLFunctions *f = this->context()->functions(); - f->glViewport(0, 0, width(), height()); - f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - GLfloat vertices[] = { - 0.0f, 0.707f, - -0.5f, -0.5f, - 0.5f, -0.5f - }; - - f->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); - f->glEnableVertexAttribArray(0); - f->glDrawArrays(GL_TRIANGLES, 0, 3); - f->glDisableVertexAttribArray(0); - glDrawPixels(bg_img.width(), bg_img.height(), GL_RGBA, GL_UNSIGNED_BYTE, bg_img.bits()); - - QRect rect = QRect(QPoint(0,0), this->size()); - //Prepare the image to be painted - QImage img(this->size(), QImage::Format_RGBA8888); - QPainter painter; - painter.begin(&img); - painter.fillRect(rect, bg_color); - painter.end(); - - //Now do any QPainter drawing - /*QOpenGLPaintDevice device(rect.size()); - QStylePainter painter; - painter.begin(&device, this); - //qDebug() << "Paint Engine type:" << painter.paintEngine()->type(); - painter.setClipRegion(rect); - //Fill in the background color first - painter.fillRect(rect, bg_color); - //Now paint any background image over that - painter.drawImage(rect, bg_img, rect, Qt::AutoColor | Qt::PreferDither | Qt::NoOpaqueDetection); - //Now find any children widgets and paint them if they are in that area - QObjectList child = this->children(); //Note: This is returned in stacking order (lowest -> highest) - for(int i=0; iisWidgetType() ){ continue; } //not a widget - GLW_Widget *glww = qobject_cast(child[i]); - if(glww!=0){ - if(!rect.intersected(glww->widgetRect()).isNull()){ - glww->paintYourself(&painter, &rect); - glww->paintChildren(&painter,&rect); - } - } - } - painter.end(); - update();*/ -} diff --git a/src-qt5/src-glwidgets/glw-base.h b/src-qt5/src-glwidgets/glw-base.h deleted file mode 100644 index ecc5bc3a..00000000 --- a/src-qt5/src-glwidgets/glw-base.h +++ /dev/null @@ -1,49 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#ifndef _LUMINA_OPENGL_WIDGETS_BASE_H -#define _LUMINA_OPENGL_WIDGETS_BASE_H - -#include -#include -#include -#include -#include -#include - -class GLW_Base : public QOpenGLWidget{ - Q_OBJECT -private: - QColor bg_color; - QImage bg_img; - QWidget *mouse_over_child; - -public: - GLW_Base(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); - ~GLW_Base(); - - QWidget * mouseOverWidget(); - -private slots: - -public slots: - void setBackgroundColor(QColor color); - void setBackground(QRect geom, QImage img); - void repaintArea(QRect); - void setMouseOverWidget(QWidget*); - -signals: - void BaseResized(); - -protected: - void mouseMoveEvent(QMouseEvent *ev); - void resizeEvent(QResizeEvent *ev); - //void paintEvent(QPaintEvent *ev); - //void initializeGL(); - void paintGL(); -}; - -#endif diff --git a/src-qt5/src-glwidgets/glw-widget.cpp b/src-qt5/src-glwidgets/glw-widget.cpp deleted file mode 100644 index e8d255b9..00000000 --- a/src-qt5/src-glwidgets/glw-widget.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "glw-widget.h" -#include - -// --- PUBLIC --- -GLW_Widget::GLW_Widget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f){ - glw_base = 0; - draggable = false; - drag_offset = QPoint(); -} - -GLW_Widget::~GLW_Widget(){ - -} - -QRect GLW_Widget::widgetRect(){ - QPoint pos = this->mapTo(glw_base, QPoint(0,0)); - return QRect(pos, this->size()); -} - -bool GLW_Widget::mouseOverWidget(){ - return (glw_base->mouseOverWidget()==this); -} - -void GLW_Widget::setGLBase(GLW_Base *base){ - if(glw_base!=0){ this->disconnect(glw_base, SLOT(repaintArea(QRect))); } - glw_base=base; - connect(this, SIGNAL(repaintArea(QRect)), glw_base, SLOT(repaintArea(QRect)) ); -} - -void GLW_Widget::paintYourself(QStylePainter *painter, const QRect *prect){ - QRect rect = widgetRect(); - rect = prect->intersected(rect); - QColor color( mouseOverWidget() ? Qt::gray : Qt::yellow); - //if(this->windowOpacity()!=1.0){ qDebug() << "Opacity:" << this->windowOpacity(); } - //color.setAlpha( qRound(this->windowOpacity()*255) ); - color.setAlpha( 125); - painter->fillRect(rect, color); -} - -void GLW_Widget::paintChildren(QStylePainter *painter, const QRect *prect){ - QObjectList child = this->children(); //Note: This is returned in stacking order (lowest -> highest) - for(int i=0; iisWidgetType() ){ continue; } //not a widget - GLW_Widget *glww = qobject_cast(child[i]); - if(glww!=0){ - if( !prect->intersected(glww->widgetRect()).isNull() ){ - glww->paintYourself(painter, prect); - glww->paintChildren(painter,prect); - } - } - } -} - - -// --- PROTECTED --- -void GLW_Widget::enterEvent(QEvent*){ - if(!mouseOverWidget()){ glw_base->setMouseOverWidget(this); } - this->update(); -} - -void GLW_Widget::leaveEvent(QEvent*){ - if(mouseOverWidget()){ glw_base->setMouseOverWidget(0); } - this->update(); -} - -void GLW_Widget::mousePressEvent(QMouseEvent *ev){ - if(!draggable){ QWidget::mousePressEvent(ev); return; } - if(ev->button()==Qt::LeftButton){ - drag_offset = ev->pos(); - } -} - -void GLW_Widget::mouseReleaseEvent(QMouseEvent *ev){ - if(!draggable){ QWidget::mouseReleaseEvent(ev); return; } - if(ev->button()==Qt::LeftButton){ - if(drag_offset!=ev->pos()){ emit doneDragging(); } - drag_offset = QPoint(); } //reset offset -} - -void GLW_Widget::mouseMoveEvent(QMouseEvent *ev){ - if(!mouseOverWidget()){ glw_base->setMouseOverWidget(this); } - if(!draggable){ QWidget::mouseMoveEvent(ev); return; } - if(!drag_offset.isNull()){ - this->move( this->mapTo(glw_base, ev->pos()-drag_offset) ); - } -} - - -void GLW_Widget::moveEvent(QMoveEvent *ev){ - QRect oldgeom = QRect(ev->oldPos(), this->size()); - QRect newgeom = QRect(ev->pos(), this->size()); - emit repaintArea( oldgeom.united(newgeom) ); -} - -void GLW_Widget::resizeEvent(QResizeEvent *ev){ - if(glw_base==0){ return; } - QPoint pos = this->mapTo(glw_base, QPoint(0,0)); - QSize sz = ev->oldSize(); - if(ev->size().width() > sz.width()){ sz.setWidth(ev->size().width()); } - if(ev->size().height() > sz.height()){ sz.setHeight(ev->size().height()); } - emit repaintArea(QRect(pos, sz)); -} - -void GLW_Widget::paintEvent(QPaintEvent *ev){ - //qDebug() << "Got paint event:" << ev->rect(); - QPoint pos = this->mapTo(glw_base, ev->rect().topLeft()); - emit repaintArea(QRect(pos, ev->rect().size()) ); - return; -} diff --git a/src-qt5/src-glwidgets/glw-widget.h b/src-qt5/src-glwidgets/glw-widget.h deleted file mode 100644 index 69d3515d..00000000 --- a/src-qt5/src-glwidgets/glw-widget.h +++ /dev/null @@ -1,63 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#ifndef _LUMINA_OPENGL_WIDGETS_WIDGET_H -#define _LUMINA_OPENGL_WIDGETS_WIDGET_H - -#include -#include -#include -#include -#include - -#include "glw-base.h" - -class GLW_Widget : public QWidget{ - Q_OBJECT -private: - GLW_Base *glw_base; - QPoint drag_offset; - bool draggable; - -public: - GLW_Widget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); - ~GLW_Widget(); - - QRect widgetRect(); //converts to the coordinate scheme of the base widget - bool mouseOverWidget(); - - void setGLBase(GLW_Base *base); - - virtual void paintYourself(QStylePainter *painter, const QRect *prect); - void paintChildren(QStylePainter *painter, const QRect *prect); - - //Properties - bool isDraggable(){ return draggable; } - -private slots: - -public slots: - void setDraggable(bool drag){ draggable = drag; } - - -protected: - virtual void enterEvent(QEvent*); - virtual void leaveEvent(QEvent*); - - virtual void mousePressEvent(QMouseEvent *ev); - virtual void mouseReleaseEvent(QMouseEvent *ev); - virtual void mouseMoveEvent(QMouseEvent *ev); - virtual void moveEvent(QMoveEvent *ev); - virtual void resizeEvent(QResizeEvent *ev); - virtual void paintEvent(QPaintEvent *ev); - -signals: - void repaintArea(QRect); - void doneDragging(); -}; - -Q_DECLARE_INTERFACE(GLW_Widget, "GLW_Widget"); -#endif diff --git a/src-qt5/src-glwidgets/glwidgets.pri b/src-qt5/src-glwidgets/glwidgets.pri deleted file mode 100644 index e391aef0..00000000 --- a/src-qt5/src-glwidgets/glwidgets.pri +++ /dev/null @@ -1,7 +0,0 @@ -QT *= widgets - -SOURCES *= $${PWD}/glw-base.cpp \ - $${PWD}/glw-widget.cpp - -HEADERS *= $${PWD}/glw-base.h \ - $${PWD}/glw-widget.h -- cgit From 7f013d766723468f4c4785411dcf5d42694cec3b Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 10 Oct 2017 10:24:50 -0400 Subject: Fix up the QML test routine a bit, and add a couple works-in-progress for a new firefly screensaver. --- .../extrafiles/screensavers/Fireflies.qml | 18 ++++++++ .../extrafiles/screensavers/Firefly.qml | 52 ++++++++++++++++++++++ src-qt5/src-qml/test/main.cpp | 5 ++- 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml new file mode 100644 index 00000000..36ed4df5 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +import QtGraphicalEffects 1.0 +import "." as QML + +Rectangle { + id : canvas + anchors.fill: parent + color: "black" + + Repeater { + model: Math.round(Math.random()*100)+30 + QML.Firefly { + parent: canvas + x: Math.round(Math.random()*canvas.width) + y: Math.round(Math.random()*canvas.height) + } + } //end of Repeater +} //end of canvas rectangle diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml new file mode 100644 index 00000000..704811a7 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml @@ -0,0 +1,52 @@ +import QtQuick 2.0 +import QtQuick.Window 2.2 +import QtGraphicalEffects 1.0 + +Item { + + RectangularGlow { + anchors.fill: fly + glowRadius: 0.1 + spread: 0.1 + color: Qt.rgba(Math.random()*255,Math.random()*255,0,0.3) + cornerRadius: fly.radius + glowRadius + } + + Rectangle { + id: fly + width: Math.round(Math.random()*3)+2 + height: width + color: Qt.rgba(Math.random()*255,Math.random()*255,0,0.8) + radius: Math.floor(width/2) + property int jitterX: Math.round(Math.random()*100)+10 + property int jitterY: Math.round(Math.random()*100)+10 + + } + + Behavior on x { + SmoothedAnimation { + velocity: 10+Math.random()*canvas.width/100 + } + } + Behavior on y { + SmoothedAnimation { + velocity: 10+Math.random()*canvas.height/100 + } + } + + Timer { + interval: Math.round(Math.random()*1000) + repeat: true + running: true + onTriggered: { + if ( (x+fly.jitterX)>canvas.width || (x+fly.jitterX)<0 ){ fly.jitterX = 0-fly.jitterX } + x = x+fly.jitterX + if( (y+fly.jitterY)>canvas.height || (y+fly.jitterY)<0 ){ fly.jitterY = 0-fly.jitterY } + y = y+fly.jitterY + fly.jitterX = (Math.round(Math.random())*2 - 1) *fly.jitterX + fly.jitterY = (Math.round(Math.random())*2 - 1) *fly.jitterY + fly.color = Qt.rgba(Math.random()*255,Math.random()*255,Math.random()*150,0.8) + + } + } //end of timer +} //end of item diff --git a/src-qt5/src-qml/test/main.cpp b/src-qt5/src-qml/test/main.cpp index eabe7dc5..e65c599f 100644 --- a/src-qt5/src-qml/test/main.cpp +++ b/src-qt5/src-qml/test/main.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include int main(int argc, char** argv){ QString QMLFile; @@ -14,7 +14,8 @@ int main(int argc, char** argv){ } QApplication A(argc,argv); qDebug() << "Creating base widget"; - QQuickWidget base; + QQuickView base; + base.setResizeMode(QQuickView::SizeRootObjectToView); qDebug() << "Resize base widget"; base.resize(1024,768); qDebug() << "Load QML File:" << QMLFile; -- cgit From 23efad7b8634b32ff6f4d901af9997bc98206af3 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 10 Oct 2017 11:09:16 -0400 Subject: Update the Fireflies screensaver - seems to work fine now --- .../extrafiles/screensavers/Fireflies.qml | 3 +- .../extrafiles/screensavers/Firefly.qml | 39 ++++++++++++++-------- 2 files changed, 27 insertions(+), 15 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml index 36ed4df5..c2295a8f 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml @@ -8,11 +8,12 @@ Rectangle { color: "black" Repeater { - model: Math.round(Math.random()*100)+30 + model: Math.round(Math.random()*200)+60 QML.Firefly { parent: canvas x: Math.round(Math.random()*canvas.width) y: Math.round(Math.random()*canvas.height) } } //end of Repeater + } //end of canvas rectangle diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml index 704811a7..7b65d8ec 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml @@ -6,23 +6,28 @@ Item { RectangularGlow { anchors.fill: fly - glowRadius: 0.1 - spread: 0.1 - color: Qt.rgba(Math.random()*255,Math.random()*255,0,0.3) + glowRadius: Math.round(fly.radius /2) + spread: 0.5 + color: Qt.rgba(1,1,1,0.3) cornerRadius: fly.radius + glowRadius } Rectangle { id: fly - width: Math.round(Math.random()*3)+2 + width: Math.round(Math.random()*canvas.width/200)+2 height: width - color: Qt.rgba(Math.random()*255,Math.random()*255,0,0.8) + x: parent.x + y: parent.y + color: Qt.rgba(Math.random(),Math.random(),0,0.5) radius: Math.floor(width/2) property int jitterX: Math.round(Math.random()*100)+10 property int jitterY: Math.round(Math.random()*100)+10 - - } - + + Behavior on color { + ColorAnimation { + duration: 500 + } + } Behavior on x { SmoothedAnimation { velocity: 10+Math.random()*canvas.width/100 @@ -34,18 +39,24 @@ Item { } } + } + + + Timer { - interval: Math.round(Math.random()*1000) + interval: 5 repeat: true running: true + property bool starting: true onTriggered: { - if ( (x+fly.jitterX)>canvas.width || (x+fly.jitterX)<0 ){ fly.jitterX = 0-fly.jitterX } - x = x+fly.jitterX - if( (y+fly.jitterY)>canvas.height || (y+fly.jitterY)<0 ){ fly.jitterY = 0-fly.jitterY } - y = y+fly.jitterY + if(starting){ interval = Math.round(Math.random()*1000)+500; starting = false; } + if ( (fly.x+fly.jitterX)>parent.width || (fly.x+fly.jitterX)<0 ){ fly.jitterX = 0-fly.jitterX } + fly.x = fly.x+fly.jitterX + if( (fly.y+fly.jitterY)>parent.height || (fly.y+fly.jitterY)<0 ){ fly.jitterY = 0-fly.jitterY } + fly.y = fly.y+fly.jitterY fly.jitterX = (Math.round(Math.random())*2 - 1) *fly.jitterX fly.jitterY = (Math.round(Math.random())*2 - 1) *fly.jitterY - fly.color = Qt.rgba(Math.random()*255,Math.random()*255,Math.random()*150,0.8) + fly.color = Qt.rgba(Math.random(),Math.random(),Math.random(),0.5) } } //end of timer -- cgit From f81d342ebc0aba7295c78b91a0ecfb1cb013f723 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 10 Oct 2017 11:16:58 -0400 Subject: Make the number of fireflies scale a bit better with the size of the screen --- .../core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml index c2295a8f..d8dcc1ed 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml @@ -8,7 +8,7 @@ Rectangle { color: "black" Repeater { - model: Math.round(Math.random()*200)+60 + model: Math.round(Math.random()*canvas.width/10)+100 QML.Firefly { parent: canvas x: Math.round(Math.random()*canvas.width) -- cgit From 93536aa33906895760d87c79da5f74471fcf0696 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 10 Oct 2017 13:18:53 -0400 Subject: Change the layout of the screensaver files directory a bit. This adds the formalization of a JSON manifest for determining which screensavers are valid and how to launch them, as well as all sorts of other legal/author information as desired. --- .../extrafiles/screensavers/Fireflies.json | 26 +++++++ .../extrafiles/screensavers/Fireflies.qml | 19 ------ .../extrafiles/screensavers/Firefly.qml | 63 ----------------- .../extrafiles/screensavers/README.md | 79 ++++++++++++++++++++++ .../screensavers/qml_scripts/Fireflies.qml | 19 ++++++ .../screensavers/qml_scripts/Firefly.qml | 63 +++++++++++++++++ 6 files changed, 187 insertions(+), 82 deletions(-) create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Fireflies.qml create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Firefly.qml (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json new file mode 100644 index 00000000..e01d6d2b --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json @@ -0,0 +1,26 @@ +{ + "name" : { + "default" : "Fireflies" + }, + "description" : { + "default" : "Dancing balls of light on the screen" + }, + "author" : { + "name" : "Ken Moore", + "email" : "ken@ixsystems.com", + "website" : "https://github.com/beanpole135", + "company" : "iXsystems", + "company_website" : "http://ixsystems.com" + }, + "meta" : { + "license" : "3-clause BSD", + "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE", + "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", + "date_created" : "20171010", + "version" : "1.0" + } + "qml" : { + "qml_file" : "qml_scripts/Fireflies.qml", + "additional_files" : ["qml_scripts/Firefly.qml"] + } +} diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml deleted file mode 100644 index d8dcc1ed..00000000 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.qml +++ /dev/null @@ -1,19 +0,0 @@ -import QtQuick 2.0 -import QtGraphicalEffects 1.0 -import "." as QML - -Rectangle { - id : canvas - anchors.fill: parent - color: "black" - - Repeater { - model: Math.round(Math.random()*canvas.width/10)+100 - QML.Firefly { - parent: canvas - x: Math.round(Math.random()*canvas.width) - y: Math.round(Math.random()*canvas.height) - } - } //end of Repeater - -} //end of canvas rectangle diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml deleted file mode 100644 index 7b65d8ec..00000000 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Firefly.qml +++ /dev/null @@ -1,63 +0,0 @@ -import QtQuick 2.0 -import QtQuick.Window 2.2 -import QtGraphicalEffects 1.0 - -Item { - - RectangularGlow { - anchors.fill: fly - glowRadius: Math.round(fly.radius /2) - spread: 0.5 - color: Qt.rgba(1,1,1,0.3) - cornerRadius: fly.radius + glowRadius - } - - Rectangle { - id: fly - width: Math.round(Math.random()*canvas.width/200)+2 - height: width - x: parent.x - y: parent.y - color: Qt.rgba(Math.random(),Math.random(),0,0.5) - radius: Math.floor(width/2) - property int jitterX: Math.round(Math.random()*100)+10 - property int jitterY: Math.round(Math.random()*100)+10 - - Behavior on color { - ColorAnimation { - duration: 500 - } - } - Behavior on x { - SmoothedAnimation { - velocity: 10+Math.random()*canvas.width/100 - } - } - Behavior on y { - SmoothedAnimation { - velocity: 10+Math.random()*canvas.height/100 - } - } - - } - - - - Timer { - interval: 5 - repeat: true - running: true - property bool starting: true - onTriggered: { - if(starting){ interval = Math.round(Math.random()*1000)+500; starting = false; } - if ( (fly.x+fly.jitterX)>parent.width || (fly.x+fly.jitterX)<0 ){ fly.jitterX = 0-fly.jitterX } - fly.x = fly.x+fly.jitterX - if( (fly.y+fly.jitterY)>parent.height || (fly.y+fly.jitterY)<0 ){ fly.jitterY = 0-fly.jitterY } - fly.y = fly.y+fly.jitterY - fly.jitterX = (Math.round(Math.random())*2 - 1) *fly.jitterX - fly.jitterY = (Math.round(Math.random())*2 - 1) *fly.jitterY - fly.color = Qt.rgba(Math.random(),Math.random(),Math.random(),0.5) - - } - } //end of timer -} //end of item diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md new file mode 100644 index 00000000..768f0e14 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md @@ -0,0 +1,79 @@ +## Screensaver Format +The screensaver system for the Lumina desktop allows for the creation and use of scripts written in the QML language, with a number of screensavers and other examples installed out-of-box. There are only a couple warnings/caveats to consider when developing a new screensaver: + +1. The root object in your QML script will be automatically sized to fit the screen as needed. Avoid trying to hard-code specific screen dimensions within your script as it will not work properly. +2. A JSON manifest file must be created (format listed below) and placed into one of the screensaver plugin directories for it to be recognized as a valid screensaver by the desktop. + + +### JSON Manifest +The manifest file contains all the information needed to actually validate/launch the screensaver, as well as additional information about the author and/or the screensaver itself. + +Example JSON manifest file (sample.json): +``` +{ + "name" : { + "default" : "sample", + "en_US" : "US English localization of the name" + "en" : "Generic english localization of the name" + } + + "description" : { + "default" : "sample screensaver", + "en_US" : "US English Localization of the description" + } + + "author" : { + "name" : "Me", + "email" : "Me@myself.net", + "website" : "http://mywebsite.net", + "company" : "iXsystems" + "company_website" : "http://ixsystems.com" + } + + "meta" : { + "license" : "3-clause BSD", + "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE", + "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", + "date_created" : "20171010", + "date_updated" : "20171011", + "version" : "1.0" + } + + "qml" : { + "exec" : "absolute/or/relative/path/to/script.qml", + "additional_files" : ["file/which/must/exist.png"], + "qt_min_version" : "5.0", + "qt_max_version" : "6.0" + } +} +``` + +Details of the individual items in the manifest: +* NOTE: for locale codes, both long and short version are acceptable: + Example 1: If the current locale is "en_GB", but the JSON manifest lists translations for "en_US" and "en", then the "en" translation will be used. + Example 2: If the current locale is "en_GB", but neither "en_GB" nor "en" translations exist, then the "default" version will be used. + +* **name** : (required) This is the official name of the screensaver to show to users + * *default* : (required) Non-translated name of the screensaver + * *[locale]* : (optional) Translated name for specific [locale] +* **description** : (required) This is a short description of the screensaver to show to users + * *default* : (required) Non-translated description of the screensaver + * *[locale]* : (optional) Translated description for specific [locale] +* **author** : (all optional) Additional information about the author(s) of the screensaver + * *name* : Name of the author + * *email* : Email to contact the author (useful for licensing questions and such) + * *website* : Personal website for the author (github/facebook/twitter profile, etc) + * *company* : Company for which the author is creating this screensaver + * *company_website* : Website for the company +* **meta** : (all optional) Additional information about the screensaver itself + * *license* : License the screensaver is released under + * *license_url* : Website which contains the full text of the license + * *copyright* : Copyright notice for this screensaver + * *date_created* : (yyyyMMdd) Date the screensaver was initially created + * *date_updated* : (yyyyMMdd) Date the screensaver was last updated + * *version* : Current version of the screensaver (typically updated every time "date_updated" is changed) +* **qml** : (required) Information about launching the screensaver and checking validity + * *exec* : (required) Absolute or relative path to the QML script (relative to the directory which contains the JSON manifest) + * *additional_files* : (optional) Array of paths for other files/scripts which must exist for the screensaver to work properly. + * *qt_min_version* : (optional) Minimum version of the Qt libraries that this screensaver supports + * *qt_max_version* : (optional) Maximum version of the Qt libraries that this screensaver supports diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Fireflies.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Fireflies.qml new file mode 100644 index 00000000..d8dcc1ed --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Fireflies.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 +import QtGraphicalEffects 1.0 +import "." as QML + +Rectangle { + id : canvas + anchors.fill: parent + color: "black" + + Repeater { + model: Math.round(Math.random()*canvas.width/10)+100 + QML.Firefly { + parent: canvas + x: Math.round(Math.random()*canvas.width) + y: Math.round(Math.random()*canvas.height) + } + } //end of Repeater + +} //end of canvas rectangle diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Firefly.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Firefly.qml new file mode 100644 index 00000000..7b65d8ec --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Firefly.qml @@ -0,0 +1,63 @@ +import QtQuick 2.0 +import QtQuick.Window 2.2 +import QtGraphicalEffects 1.0 + +Item { + + RectangularGlow { + anchors.fill: fly + glowRadius: Math.round(fly.radius /2) + spread: 0.5 + color: Qt.rgba(1,1,1,0.3) + cornerRadius: fly.radius + glowRadius + } + + Rectangle { + id: fly + width: Math.round(Math.random()*canvas.width/200)+2 + height: width + x: parent.x + y: parent.y + color: Qt.rgba(Math.random(),Math.random(),0,0.5) + radius: Math.floor(width/2) + property int jitterX: Math.round(Math.random()*100)+10 + property int jitterY: Math.round(Math.random()*100)+10 + + Behavior on color { + ColorAnimation { + duration: 500 + } + } + Behavior on x { + SmoothedAnimation { + velocity: 10+Math.random()*canvas.width/100 + } + } + Behavior on y { + SmoothedAnimation { + velocity: 10+Math.random()*canvas.height/100 + } + } + + } + + + + Timer { + interval: 5 + repeat: true + running: true + property bool starting: true + onTriggered: { + if(starting){ interval = Math.round(Math.random()*1000)+500; starting = false; } + if ( (fly.x+fly.jitterX)>parent.width || (fly.x+fly.jitterX)<0 ){ fly.jitterX = 0-fly.jitterX } + fly.x = fly.x+fly.jitterX + if( (fly.y+fly.jitterY)>parent.height || (fly.y+fly.jitterY)<0 ){ fly.jitterY = 0-fly.jitterY } + fly.y = fly.y+fly.jitterY + fly.jitterX = (Math.round(Math.random())*2 - 1) *fly.jitterX + fly.jitterY = (Math.round(Math.random())*2 - 1) *fly.jitterY + fly.color = Qt.rgba(Math.random(),Math.random(),Math.random(),0.5) + + } + } //end of timer +} //end of item -- cgit From 526b11d189b41c94da315bb80de4c78e176f8471 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 10 Oct 2017 13:30:56 -0400 Subject: Cleanup a lot of stale/unused files within the Lumina2 souce tree. --- .../extrafiles/audiofiles/LICENCE | 7 ----- .../extrafiles/audiofiles/Login.ogg | Bin 32111 -> 0 bytes .../extrafiles/audiofiles/Logout.ogg | Bin 31255 -> 0 bytes .../extrafiles/audiofiles/low-battery.ogg | Bin 49748 -> 0 bytes .../extrafiles/lumina-desktop.desktop | 34 --------------------- .../wallpapers/Lumina_Wispy_blue-grey-zoom.jpg | Bin 6269314 -> 0 bytes .../wallpapers/Lumina_Wispy_blue-grey.jpg | Bin 6508360 -> 0 bytes .../extrafiles/wallpapers/Lumina_Wispy_gold.jpg | Bin 2523711 -> 0 bytes .../extrafiles/wallpapers/Lumina_Wispy_green.jpg | Bin 1286362 -> 0 bytes .../wallpapers/Lumina_Wispy_grey-blue-zoom.jpg | Bin 563037 -> 0 bytes .../wallpapers/Lumina_Wispy_grey-blue.jpg | Bin 361771 -> 0 bytes .../extrafiles/wallpapers/Lumina_Wispy_purple.jpg | Bin 926969 -> 0 bytes .../extrafiles/wallpapers/Lumina_Wispy_red.jpg | Bin 1141515 -> 0 bytes .../core/lumina-desktop-unified/lumina-desktop.pro | 3 ++ 14 files changed, 3 insertions(+), 41 deletions(-) delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/LICENCE delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Login.ogg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Logout.ogg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/low-battery.ogg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/lumina-desktop.desktop delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey.jpg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_gold.jpg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_green.jpg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue.jpg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_purple.jpg delete mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_red.jpg (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/LICENCE b/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/LICENCE deleted file mode 100644 index aa601d5e..00000000 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/LICENCE +++ /dev/null @@ -1,7 +0,0 @@ -These audio files are BSD-licensed and were created/owned by the TrueOS Project: - - Login.ogg - - Logout.ogg - -These audio files are freely available on jewelbeat.com: -"Music by JewelBeat. Download your free music and free sound effects at www.jewelbeat.com." - - low-battery.ogg (http://www.jewelbeat.com/free/free-sound-effects/musical%20effects/Tympani_2.mp3 - converted to OGG afterward) diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Login.ogg b/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Login.ogg deleted file mode 100644 index 43a07e27..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Login.ogg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Logout.ogg b/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Logout.ogg deleted file mode 100644 index e63ae07f..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/Logout.ogg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/low-battery.ogg b/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/low-battery.ogg deleted file mode 100644 index d129a2b3..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/audiofiles/low-battery.ogg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/lumina-desktop.desktop b/src-qt5/core/lumina-desktop-unified/extrafiles/lumina-desktop.desktop deleted file mode 100644 index 7d87f93a..00000000 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/lumina-desktop.desktop +++ /dev/null @@ -1,34 +0,0 @@ -[Desktop Entry] -Exec=start-lumina-desktop -TryExec=start-lumina-desktop -Icon=Lumina-DE -Type=Application -Name=Lumina -Name[de]=Lumina -Name[en_GB]=Lumina -Name[en_ZA]=Lumina -Name[et]=Lumina -Name[fr]=Lumina -Name[fr_CA]=Lumina -Name[hi]=ल्यूमिना -Name[ja]=Lumina -Name[mt]=Lumina -Name[pl]=Lumina -Name[pt_BR]=Lumina -Name[ru]=Lumina -Name[uk]=Lumina -Name[vi]=Lumina -Comment=A Lightweight Desktop for FreeBSD -Comment[de]=Eine leichtgewichtige Arbeitsplatzumgebung für FreeBSD -Comment[en_GB]=A Lightweight Desktop for FreeBSD -Comment[en_ZA]=A Lightweight Desktop for FreeBSD -Comment[et]=Minimalistlik töölauakeskkond FreeBSD-le -Comment[fr]=Un environnement bureau léger pour FreeBSD -Comment[fr_CA]=Un environnement bureau léger pour FreeBSD -Comment[hi]=एक हल्का डेस्कटॉप फ्री बी.एस.डी के लिए -Comment[ja]=FreeBSD の為に作られた軽快なデスクトップ環境 -Comment[mt]=A Desktop irqiq għal FreeBSD -Comment[pl]=Lekkie Środowisko graficzne dla FreeBSD -Comment[pt_BR]=Um ambiente de trabalho leve para FreeBSD -Comment[uk]=Легковісне оточення стільниці для FreeBSD -Comment[vi]=Một máy tính để bàn nhẹ cho FreeBSD diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg deleted file mode 100644 index 481ca438..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey.jpg deleted file mode 100644 index 9da67596..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_blue-grey.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_gold.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_gold.jpg deleted file mode 100644 index cba03cee..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_gold.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_green.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_green.jpg deleted file mode 100644 index 80b0d3e3..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_green.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg deleted file mode 100644 index 4f753ed5..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue.jpg deleted file mode 100644 index c214cd78..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_grey-blue.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_purple.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_purple.jpg deleted file mode 100644 index e4c3d7a8..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_purple.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_red.jpg b/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_red.jpg deleted file mode 100644 index a092f636..00000000 Binary files a/src-qt5/core/lumina-desktop-unified/extrafiles/wallpapers/Lumina_Wispy_red.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro index e8cf2f28..ba958401 100644 --- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro @@ -54,6 +54,9 @@ desktop.files = lumina-desktop.desktop defaults.path = $${L_SHAREDIR}/lumina-desktop defaults.files = defaults/* +extrafiles.path = $${L_SHAREDIR}/lumina-desktop +extrafiles.files = extrafiles/* + TRANSLATIONS = i18n/lumina-desktop_af.ts \ i18n/lumina-desktop_ar.ts \ i18n/lumina-desktop_az.ts \ -- cgit From 7dd1ca13749571408725ac45e8d1e1d3bbf7c798 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 10 Oct 2017 15:29:13 -0400 Subject: Write up the new ScreenSaver plugins management class (untested) Also cleanup a bit more of the documentation for the new plugin system. --- .../extrafiles/screensavers/Fireflies.json | 2 +- .../extrafiles/screensavers/README.md | 12 +- .../core/lumina-desktop-unified/lumina-desktop.pro | 2 +- src-qt5/src-cpp/plugins-screensaver.cpp | 143 +++++++++++++++++++++ src-qt5/src-cpp/plugins-screensaver.h | 50 +++++++ src-qt5/src-cpp/plugins-screensaver.pri | 4 + 6 files changed, 205 insertions(+), 8 deletions(-) create mode 100644 src-qt5/src-cpp/plugins-screensaver.cpp create mode 100644 src-qt5/src-cpp/plugins-screensaver.h create mode 100644 src-qt5/src-cpp/plugins-screensaver.pri (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json index e01d6d2b..8d0d25c4 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json @@ -18,7 +18,7 @@ "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", "date_created" : "20171010", "version" : "1.0" - } + }, "qml" : { "qml_file" : "qml_scripts/Fireflies.qml", "additional_files" : ["qml_scripts/Firefly.qml"] diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md index 768f0e14..d9093b44 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/README.md @@ -13,22 +13,22 @@ Example JSON manifest file (sample.json): { "name" : { "default" : "sample", - "en_US" : "US English localization of the name" + "en_US" : "US English localization of the name", "en" : "Generic english localization of the name" - } + }, "description" : { "default" : "sample screensaver", "en_US" : "US English Localization of the description" - } + }, "author" : { "name" : "Me", "email" : "Me@myself.net", "website" : "http://mywebsite.net", - "company" : "iXsystems" + "company" : "iXsystems", "company_website" : "http://ixsystems.com" - } + }, "meta" : { "license" : "3-clause BSD", @@ -37,7 +37,7 @@ Example JSON manifest file (sample.json): "date_created" : "20171010", "date_updated" : "20171011", "version" : "1.0" - } + }, "qml" : { "exec" : "absolute/or/relative/path/to/script.qml", diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro index ba958401..9b0c2fb3 100644 --- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro @@ -123,7 +123,7 @@ TRANSLATIONS = i18n/lumina-desktop_af.ts \ dotrans.path=$${L_SHAREDIR}/lumina-desktop/i18n/ dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$${L_SHAREDIR}/lumina-desktop/i18n/ -INSTALLS += target desktop defaults +INSTALLS += target desktop defaults extrafiles WITH_I18N{ INSTALLS += dotrans diff --git a/src-qt5/src-cpp/plugins-screensaver.cpp b/src-qt5/src-cpp/plugins-screensaver.cpp new file mode 100644 index 00000000..8271e7ac --- /dev/null +++ b/src-qt5/src-cpp/plugins-screensaver.cpp @@ -0,0 +1,143 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "plugins-screensaver.h" +#include + +//Relative directory to search along the XDG paths for screensavers +#define REL_DIR QString("/lumina-desktop/screensavers") + +// ============ +// SS PLUGIN +// ============ +SSPlugin::SSPlugin(){ + +} + +SSPlugin::~SSPlugin(){ + +} + +void SSPlugin::loadFile(QString path){ + data = QJsonObject(); + currentfile = path; + SSPlugin SSP; + QFile file(path); + if(!file.exists() || !file.open(QIODevice::ReadOnly)){ return SSP; } + SSP.data = QJsonDocument::fromJson(file.readAll()).object(); + file.close(); + return SSP; +} + +bool SSPlugin::isLoaded(){ + return !data.isEmpty(); +} + +bool SSPlugin::isValid(){ + if(data.isEmpty()){ return false; } + bool ok = data.contains("name") && data.contains("qml") && data.contains("description"); + if(ok){ + //go to the next name level and see if required sub-items exist + QJsonObject tmp = data.value("name").toObject(); + ok = tmp.contains("default"); + } + if(ok){ + //go to the next description level and see if required sub-items exist + QJsonObject tmp = data.value("description").toObject(); + ok = tmp.contains("default"); + } +if(ok){ + //go to the next qml level and see if required sub-items exist + QJsonObject tmp = data.value("qml").toObject(); + QStringList mustexist; + mustexist << tmp.value("exec").toString(); + ok = !mustexist.isEmpty(); //exec file should **always** be listed + QJsonArray tmpA = data.value("additional_files").toArray(); + for(int i=0; i SSPluginSystem::findAllPlugins(bool validonly = true){ + QList LIST; + //Get the list of directories to search + QStringList dirs; + dirs << QString(getenv("XDG_DATA_HOME")) << QString(getenv("XDG_DATA_DIRS")).split(":"); + //Look for that file within these directories and return the first one found + for(int i=0; i SYSTEM plugins +// XDG_DATA_HOME/lumina-desktop/screensavers > XDG_DATA_DIRS/lumina-desktop/screensavers +//=========================================== +#ifndef _LUMINA_DESKTOP_SCREENSAVER_PLUGINS_CLASS_H +#define _LUMINA_DESKTOP_SCREENSAVER_PLUGINS_CLASS_H + +#include +#include +#include +#include + +class SSPlugin{ +private: + QString currentfile; + +public: + QJsonObject data; //Hazardous to manually modify + + SSPlugin(); + ~SSPlugin(); + + void loadFile(QString path); + bool isLoaded(); + + bool isValid(); + + QString translatedName(); + QString translatedDescription(); + QUrl scriptURL(); +}; + +class SSPluginSystem{ +public: + static SSPlugin findPlugin(QString name); + static QList findAllPlugins(bool validonly = true); + +}; + +#endif diff --git a/src-qt5/src-cpp/plugins-screensaver.pri b/src-qt5/src-cpp/plugins-screensaver.pri new file mode 100644 index 00000000..883a850f --- /dev/null +++ b/src-qt5/src-cpp/plugins-screensaver.pri @@ -0,0 +1,4 @@ +HEADERS *= $${PWD}/plugins-screensaver.h +SOURCES *= $${PWD}/plugins-screensaver.cpp + +INCLUDEPATH *= ${PWD} -- cgit From dfac324cb6b02d19857f0e5dcced099d31ce957d Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 11 Oct 2017 10:34:53 -0400 Subject: Get the Lumina2 screensaver system converted over to the new QML-backed plugin system. Still need to clean up some old files within the source tree, but it all works right now. --- src-qt5/OS-detect.pri | 2 +- src-qt5/core/lumina-desktop-unified/LSession.cpp | 4 +- .../extrafiles/screensavers/Fireflies.json | 2 +- .../core/lumina-desktop-unified/global-includes.h | 1 + .../core/lumina-desktop-unified/lumina-desktop.pro | 13 ++++- .../src-screensaver/SSBaseWidget.cpp | 63 +++++++--------------- .../src-screensaver/SSBaseWidget.h | 12 ++--- src-qt5/src-cpp/plugins-screensaver.cpp | 25 +++++---- src-qt5/src-cpp/plugins-screensaver.pri | 2 +- 9 files changed, 57 insertions(+), 67 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/OS-detect.pri b/src-qt5/OS-detect.pri index 9f3019e3..8511bd81 100644 --- a/src-qt5/OS-detect.pri +++ b/src-qt5/OS-detect.pri @@ -23,7 +23,7 @@ # ============================================= isEmpty(OS){ message("Build OS Info: $${QMAKE_HOST.os}, $${QMAKE_HOST.arch}, $${QMAKE_HOST.version_string}") - + message(" - Detected Qt Version: $${QT_VERSION}") #Load the initial library/includefile search locations (more can be added in the OS-specific sections below) LIBS = -L$${PWD}/core/libLumina -L$$[QT_INSTALL_LIBS] INCLUDEPATH = $${PWD}/core/libLumina $$[QT_INSTALL_HEADERS] $$[QT_INSTALL_PREFIX] diff --git a/src-qt5/core/lumina-desktop-unified/LSession.cpp b/src-qt5/core/lumina-desktop-unified/LSession.cpp index d70ff973..bace2dbe 100644 --- a/src-qt5/core/lumina-desktop-unified/LSession.cpp +++ b/src-qt5/core/lumina-desktop-unified/LSession.cpp @@ -356,12 +356,12 @@ void LSession::launchStartupApps(){ void LSession::checkUserFiles(){ //internal version conversion examples: // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] - QString OVS = DesktopSettings::instance()->value(DesktopSettings::System,"DesktopVersion","0").toString(); //Old Version String + /*QString OVS = DesktopSettings::instance()->value(DesktopSettings::System,"DesktopVersion","0").toString(); //Old Version String bool changed = LDesktopUtils::checkUserFiles(OVS); if(changed){ //Save the current version of the session to the settings file (for next time) DesktopSettings::instance()->setValue(DesktopSettings::System,"DesktopVersion", this->applicationVersion()); - } + }*/ } diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json index 8d0d25c4..c09de308 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Fireflies.json @@ -20,7 +20,7 @@ "version" : "1.0" }, "qml" : { - "qml_file" : "qml_scripts/Fireflies.qml", + "exec" : "qml_scripts/Fireflies.qml", "additional_files" : ["qml_scripts/Firefly.qml"] } } diff --git a/src-qt5/core/lumina-desktop-unified/global-includes.h b/src-qt5/core/lumina-desktop-unified/global-includes.h index 184f5b8d..ba1beb06 100644 --- a/src-qt5/core/lumina-desktop-unified/global-includes.h +++ b/src-qt5/core/lumina-desktop-unified/global-includes.h @@ -53,6 +53,7 @@ #include #include #include +#include // libLumina includes diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro index 9b0c2fb3..6b9ee876 100644 --- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro @@ -1,8 +1,15 @@ include($${PWD}/../../OS-detect.pri) -QT += core gui network -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets x11extras multimedia multimediawidgets concurrent svg +lessThan(QT_MAJOR_VERSION, 5) { + message("[ERROR] Qt 5.4+ is required to use the Lumina Desktop!") + exit +} +lessThan(QT_MINOR_VERSION, 4){ + message("[ERROR] Qt 5.4+ is required to use the Lumina Desktop!") + exit +} +QT *= core gui network widgets x11extras multimedia multimediawidgets concurrent svg quick qml TARGET = lumina-desktop-unified @@ -22,6 +29,8 @@ include(../libLumina/NativeWindow.pri) include(../libLumina/XDGMime.pri) include(../libLumina/LIconCache.pri) +include(../../src-cpp/plugins-screensaver.pri) + #include all the main individual source groups include(src-screensaver/screensaver.pri) include(src-events/events.pri) diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp index a6d5be60..227e51ac 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp @@ -12,10 +12,11 @@ // ======== // PUBLIC // ======== -SSBaseWidget::SSBaseWidget(QWidget *parent) : QWidget(parent){ +SSBaseWidget::SSBaseWidget(QWidget *parent) : QQuickView(parent->windowHandle()){ this->setObjectName("LuminaBaseSSWidget"); - ANIM = 0; - this->setMouseTracking(true); + this->setResizeMode(QQuickView::SizeRootObjectToView); + this->setColor(QColor("black")); //default color for the view + //this->setMouseTracking(true); plugType="none"; restartTimer = new QTimer(this); restartTimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "globals/plugin_time_seconds", 60).toInt() * 1000); @@ -24,7 +25,6 @@ SSBaseWidget::SSBaseWidget(QWidget *parent) : QWidget(parent){ } SSBaseWidget::~SSBaseWidget(){ - if(ANIM!=0){ this->stopPainting(); } } void SSBaseWidget::setPlugin(QString plug){ @@ -35,54 +35,27 @@ void SSBaseWidget::setPlugin(QString plug){ // PUBLIC SLOTS // ============= void SSBaseWidget::startPainting(){ - cplug = plugType; //free up any old animation instance - if(ANIM!=0){ - stopPainting(); - } + stopPainting(); //If a random plugin - grab one of the known plugins - if(cplug=="random"){ - QStringList valid = BaseAnimGroup::KnownAnimations(); - valid.removeAll("none"); //they want a screensaver - remove the "none" option from the valid list - if(valid.isEmpty()){ cplug = "none"; } //no known plugins - else{ cplug = valid[ qrand()%valid.length() ]; } //grab a random plugin - } - if(DEBUG){ qDebug() << " - Screen Saver:" << plugType << cplug; } - //Now list all the various plugins and start them appropriately - QString style; - if(cplug=="none"){ - style = "background: black;"; //show the underlying black parent widget - }else{ - style = "background: black;"; + if(plugType=="random"){ + QList valid = SSPluginSystem::findAllPlugins(); + if(!valid.isEmpty()){ cplug = valid[ qrand()%valid.length() ]; } //grab a random plugin + }else if(plugType!="none"){ + cplug = SSPluginSystem::findPlugin(plugType); } - this->setStyleSheet("QWidget#LuminaBaseSSWidget{ "+style+"}"); - this->repaint(); - //If not a stylesheet-based plugin - set it here - if(cplug!="none"){ - ANIM = BaseAnimGroup::NewAnimation(cplug, this); - connect(ANIM, SIGNAL(finished()), this, SLOT(startPainting()) ); //repeat the plugin as needed - ANIM->LoadAnimations(); + if(DEBUG){ qDebug() << " - Screen Saver:" << plugType << cplug.scriptURL() << cplug.isValid(); } + if(cplug.isValid()){ + this->setSource( cplug.scriptURL() ); + restartTimer->start(); } - //Now start the animation(s) - if(ANIM!=0){ - if(ANIM->animationCount()>0){ - if(DEBUG){ qDebug() << " - Starting SS Plugin:" << cplug << ANIM->animationCount() << ANIM->duration() << ANIM->loopCount(); } - ANIM->start(); - } - } - restartTimer->start(); + } void SSBaseWidget::stopPainting(){ - if(ANIM!=0){ - if(DEBUG){ qDebug() << "Stopping Animation!!"; } - ANIM->stop(); - //ANIM->clear(); - ANIM->deleteLater(); - ANIM = 0; - //Delete any child widgets of the canvas - QList widgets = this->findChildren("",Qt::FindDirectChildrenOnly); - for(int i=0; ideleteLater(); } + if(!this->source().isEmpty()){ + this->setSource(QUrl()); + cplug = SSPlugin(); //empty structure } if(restartTimer->isActive()){ restartTimer->stop(); } } diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h index af809127..fdb23e66 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h @@ -10,9 +10,9 @@ #define _LUMINA_DESKTOP_SCREEN_SAVER_BASE_WIDGET_H #include "global-includes.h" -#include "animations/BaseAnimGroup.h" +#include -class SSBaseWidget : public QWidget{ +class SSBaseWidget : public QQuickView{ Q_OBJECT public: SSBaseWidget(QWidget *parent); @@ -25,8 +25,8 @@ public slots: void stopPainting(); private: - QString plugType, cplug; //type of custom painting to do - BaseAnimGroup *ANIM; + QString plugType; + SSPlugin cplug; QTimer *restartTimer; private slots: @@ -43,12 +43,12 @@ protected: ev->accept(); emit InputDetected(); } - void paintEvent(QPaintEvent*){ + /*void paintEvent(QPaintEvent*){ QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); - } + }*/ }; diff --git a/src-qt5/src-cpp/plugins-screensaver.cpp b/src-qt5/src-cpp/plugins-screensaver.cpp index 8271e7ac..e9ac1330 100644 --- a/src-qt5/src-cpp/plugins-screensaver.cpp +++ b/src-qt5/src-cpp/plugins-screensaver.cpp @@ -6,6 +6,10 @@ //=========================================== #include "plugins-screensaver.h" #include +#include +#include +#include +#include //Relative directory to search along the XDG paths for screensavers #define REL_DIR QString("/lumina-desktop/screensavers") @@ -24,12 +28,10 @@ SSPlugin::~SSPlugin(){ void SSPlugin::loadFile(QString path){ data = QJsonObject(); currentfile = path; - SSPlugin SSP; QFile file(path); - if(!file.exists() || !file.open(QIODevice::ReadOnly)){ return SSP; } - SSP.data = QJsonDocument::fromJson(file.readAll()).object(); + if(!file.exists() || !file.open(QIODevice::ReadOnly)){ return; } + data = QJsonDocument::fromJson(file.readAll()).object(); file.close(); - return SSP; } bool SSPlugin::isLoaded(){ @@ -53,11 +55,13 @@ if(ok){ //go to the next qml level and see if required sub-items exist QJsonObject tmp = data.value("qml").toObject(); QStringList mustexist; - mustexist << tmp.value("exec").toString(); - ok = !mustexist.isEmpty(); //exec file should **always** be listed + QString exec = tmp.value("exec").toString(); + if(exec.isEmpty() || !exec.endsWith(".qml")){ return false; } + mustexist << exec; QJsonArray tmpA = data.value("additional_files").toArray(); for(int i=0; i SSPluginSystem::findAllPlugins(bool validonly = true){ +QList SSPluginSystem::findAllPlugins(bool validonly){ QList LIST; //Get the list of directories to search QStringList dirs; @@ -132,10 +137,12 @@ QList SSPluginSystem::findAllPlugins(bool validonly = true){ for(int i=0; i Date: Wed, 11 Oct 2017 12:14:26 -0400 Subject: A bit more cleanup for the screensaver system. Now the old animations are completely ignored in the build, and the mouse cursor is hidden while the screensaver is active. --- .../core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp | 6 +++--- src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h | 6 ------ src-qt5/core/lumina-desktop-unified/src-screensaver/screensaver.pri | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp index 227e51ac..122307b3 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp @@ -16,10 +16,10 @@ SSBaseWidget::SSBaseWidget(QWidget *parent) : QQuickView(parent->windowHandle()) this->setObjectName("LuminaBaseSSWidget"); this->setResizeMode(QQuickView::SizeRootObjectToView); this->setColor(QColor("black")); //default color for the view - //this->setMouseTracking(true); + this->setCursor(Qt::BlankCursor); plugType="none"; restartTimer = new QTimer(this); - restartTimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "globals/plugin_time_seconds", 60).toInt() * 1000); + restartTimer->setInterval( DesktopSettings::instance()->value(DesktopSettings::ScreenSaver, "globals/plugin_time_seconds", 120).toInt() * 1000); restartTimer->setSingleShot(true); connect(restartTimer, SIGNAL(timeout()), this, SLOT(startPainting()) ); } @@ -47,7 +47,7 @@ void SSBaseWidget::startPainting(){ if(DEBUG){ qDebug() << " - Screen Saver:" << plugType << cplug.scriptURL() << cplug.isValid(); } if(cplug.isValid()){ this->setSource( cplug.scriptURL() ); - restartTimer->start(); + if(plugType=="random"){ restartTimer->start(); } } } diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h index fdb23e66..72e02702 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.h @@ -43,12 +43,6 @@ protected: ev->accept(); emit InputDetected(); } - /*void paintEvent(QPaintEvent*){ - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); - }*/ }; diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/screensaver.pri b/src-qt5/core/lumina-desktop-unified/src-screensaver/screensaver.pri index f95891c1..92cc7bd2 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/screensaver.pri +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/screensaver.pri @@ -9,7 +9,7 @@ HEADERS *= $${PWD}/LLockScreen.h \ FORMS *= $${PWD}/LLockScreen.ui #update the includepath so we can just (#include ) as needed without paths -INCLUDEPATH *= ${PWD} +INCLUDEPATH *= $${PWD} #Now include all the screensaver animations/options -include(animations/animations.pri) +#include(animations/animations.pri) -- cgit From 2cedaf2c2ac9e4b4e3078c5a6f04ba5fc3f4f5b3 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 11 Oct 2017 14:46:54 -0400 Subject: Update lumina-checkpass with 2 additional options: 1. "-fd " pass in a file descriptor (such as 0 for standard input) to read password 2. "-f " pass in a file path to read the password Then update lumina-desktop-unified to use the "-f" version with a QTemporaryFile. I was trying to get it to use the "-fd" version, but the file descriptor I am getting from the QTemporaryFile does not seem to work properly - still need to track this down a bit more later but the -f option works fine for now. --- src-qt5/core/lumina-checkpass/main.c | 39 +++++++++++++++++++--- .../core/lumina-desktop-unified/global-includes.h | 1 + .../src-screensaver/LLockScreen.cpp | 13 +++++++- 3 files changed, 47 insertions(+), 6 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-checkpass/main.c b/src-qt5/core/lumina-checkpass/main.c index e12e7c78..481cce33 100644 --- a/src-qt5/core/lumina-checkpass/main.c +++ b/src-qt5/core/lumina-checkpass/main.c @@ -14,23 +14,52 @@ //=========================================== //Standard C libary #include // Standard C +#include #include // Usage output #include // User DB information +#include //PAM/security libraries #include #include #include +void showUsage(){ + puts("lumina-checkpass: Simple user-level check for password validity (for screen unlockers and such)."); + puts("Usage:"); + puts(" lumina-checkpass "); + puts(" lumina-checkpass -fd "); + puts(" lumina-checkpass -f "); + puts("Returns: 0 for a valid password, 1 for invalid"); +} + int main(int argc, char** argv){ //Check the inputs - if(argc!=2){ + if(argc<2){ //Invalid inputs - show the help text - puts("lumina-checkpass: Simple user-level check for password validity (for screen unlockers and such)."); - puts("Usage: lumina-checkpass "); - puts("Returns: 0 for a valid password, 1 for invalid"); + showUsage(); return 1; } + char*pass = 0; + if(argc==2){ pass = argv[1]; } + else if(argc==3 && 0==strcmp(argv[1],"-fd") ){ + FILE *fp = fdopen(atoi(argv[2]), "r"); + size_t len; + if(fp!=0){ + ssize_t slen = getline(&pass, &len, fp); + if(pass[slen-1]=='\n'){ pass[slen-1] = '\0'; } + } + fclose(fp); + }else if(argc==3 && 0==strcmp(argv[1],"-f") ){ + FILE *fp = fopen(argv[2], "r"); + size_t len; + if(fp!=0){ + ssize_t slen = getline(&pass, &len, fp); + if(pass[slen-1]=='\n'){ pass[slen-1] = '\0'; } + } + fclose(fp); + } + if(pass == 0){ puts("Could not read password!!"); return 1; } //error in reading password //Validate current user (make sure current UID matches the logged-in user, char* cUser = getlogin(); struct passwd *pwd = 0; @@ -44,7 +73,7 @@ int main(int argc, char** argv){ int ret = pam_start( "system", cUser, &pamc, &pamh); if(ret != PAM_SUCCESS){ return 1; } //could not init PAM //char* cPassword = argv[1]; - ret = pam_set_item(pamh, PAM_AUTHTOK, argv[1]); + ret = pam_set_item(pamh, PAM_AUTHTOK, pass); //Authenticate with PAM ret = pam_authenticate(pamh,0); //this can be true without verifying password if pam_self.so is used in the auth procedures (common) if( ret == PAM_SUCCESS ){ ret = pam_acct_mgmt(pamh,0); } //Check for valid, unexpired account and verify access restrictions diff --git a/src-qt5/core/lumina-desktop-unified/global-includes.h b/src-qt5/core/lumina-desktop-unified/global-includes.h index ba1beb06..ae57ac08 100644 --- a/src-qt5/core/lumina-desktop-unified/global-includes.h +++ b/src-qt5/core/lumina-desktop-unified/global-includes.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.cpp b/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.cpp index 0ff70142..b791ffd2 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/LLockScreen.cpp @@ -77,7 +77,18 @@ void LLockScreen::TryUnlock(){ this->setEnabled(false); QString pass = ui->line_password->text(); ui->line_password->clear(); - bool ok = (LUtils::runCmd("lumina-checkpass", QStringList() << pass) == 0); + //Create a temporary file for the password, then pass that file descriptor to lumina-checkpass + QTemporaryFile *TF = new QTemporaryFile(".XXXXXXXXXX"); + TF->setAutoRemove(true); + bool ok = false; + if( TF->open() ){ + QTextStream in(TF); + in << pass; + in.flush(); //make sure we push it to the file **right now** since we need to keep the file open + ok = (LUtils::runCmd("lumina-checkpass", QStringList() << "-f" << TF->fileName() ) == 0); + TF->close(); + } + delete TF; if(ok){ emit ScreenUnlocked(); this->setEnabled(true); -- cgit From f649d4976e64cfdf9b32022d55bfd08f39d00a8f Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Wed, 11 Oct 2017 20:51:56 -0400 Subject: Added framework to play video when the mouse is put over them. Breaks picture and video preview for lumina-fileinfo currently --- src-qt5/core/libLumina/LVideoLabel.cpp | 61 ++++++++++++++++++++++ src-qt5/core/libLumina/LVideoLabel.h | 30 +++++++++++ src-qt5/core/libLumina/LVideoLabel.pri | 8 +++ src-qt5/core/libLumina/LVideoSurface.cpp | 23 ++++---- src-qt5/core/libLumina/LVideoSurface.h | 11 ++-- src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 39 ++------------ src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 3 +- .../lumina-fileinfo/lumina-fileinfo.pro | 2 +- 8 files changed, 123 insertions(+), 54 deletions(-) create mode 100644 src-qt5/core/libLumina/LVideoLabel.cpp create mode 100644 src-qt5/core/libLumina/LVideoLabel.h create mode 100644 src-qt5/core/libLumina/LVideoLabel.pri (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp new file mode 100644 index 00000000..20b2cad4 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoLabel.cpp @@ -0,0 +1,61 @@ +#include "LVideoLabel.h" + +LVideoLabel::LVideoLabel(QString file, bool video) : QLabel(){ + this->setScaledContents(true); + if(video) { + mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); + thumbnail = QPixmap(); + entered = false; + surface = new LVideoSurface(this); + mediaPlayer->setVideoOutput(surface); + mediaPlayer->setMedia(QUrl("file://" + file)); + mediaPlayer->setPlaybackRate(3); + mediaPlayer->setMuted(true); + mediaPlayer->play(); + mediaPlayer->pause(); + this->connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(stopVideo(QPixmap))); + this->connect(mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus))); + this->connect(this, SIGNAL(rollOver()), surface, SLOT(switchRollOver())); + }else{ + thumbnail = QPixmap(file); + this->setPixmap(thumbnail); + } +} + +LVideoLabel::~LVideoLabel() { + mediaPlayer->deleteLater(); + surface->deleteLater(); +} + +void LVideoLabel::stopVideo(QPixmap pix) { + if(!entered) { + if(thumbnail.isNull()) + thumbnail = QPixmap(pix.scaledToHeight(64)); + this->setPixmap(thumbnail); + mediaPlayer->pause(); + }else { + this->setPixmap(QPixmap(pix.scaledToHeight(64))); + } +} + +void LVideoLabel::setDuration(QMediaPlayer::MediaStatus status) { + if(status == QMediaPlayer::BufferedMedia) { + mediaPlayer->setPosition(mediaPlayer->duration() / 2); + mediaPlayer->play(); + } +} + +void LVideoLabel::enterEvent(QEvent *event) { + entered=true; + emit rollOver(); + mediaPlayer->setPosition(0); + mediaPlayer->play(); + QLabel::enterEvent(event); +} + +void LVideoLabel::leaveEvent(QEvent *event) { + entered=false; + mediaPlayer->setPosition(mediaPlayer->duration() / 2); + emit rollOver(); + QLabel::leaveEvent(event); +} diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h new file mode 100644 index 00000000..fd293200 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoLabel.h @@ -0,0 +1,30 @@ +#ifndef LVIDEOLABEL_H +#define LVIDEOLABEL_H + +#include +#include +#include "LVideoSurface.h" + +//class LVideoSurface; + +class LVideoLabel : public QLabel { + Q_OBJECT + public: + LVideoLabel(QString, bool); + ~LVideoLabel(); + protected: + void enterEvent(QEvent*); + void leaveEvent(QEvent*); + signals: + void rollOver(); + public slots: + void stopVideo(QPixmap); + void setDuration(QMediaPlayer::MediaStatus); + private: + QMediaPlayer *mediaPlayer; + LVideoSurface *surface; + QVideoWidget *videoPlayer; + QPixmap thumbnail; + bool entered; +}; +#endif diff --git a/src-qt5/core/libLumina/LVideoLabel.pri b/src-qt5/core/libLumina/LVideoLabel.pri new file mode 100644 index 00000000..f609df08 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoLabel.pri @@ -0,0 +1,8 @@ +QT *= multimedia + +HEADERS *= $${PWD}/LVideoLabel.h +SOURCES *= $${PWD}/LVideoLabel.cpp + +INCLUDEPATH *= ${PWD} + +include(LVideoSurface.pri) diff --git a/src-qt5/core/libLumina/LVideoSurface.cpp b/src-qt5/core/libLumina/LVideoSurface.cpp index bd6b2c95..e3e87667 100644 --- a/src-qt5/core/libLumina/LVideoSurface.cpp +++ b/src-qt5/core/libLumina/LVideoSurface.cpp @@ -3,10 +3,12 @@ LVideoSurface::LVideoSurface(QObject *parent) : QAbstractVideoSurface(parent) { frameImage = QPixmap(); + entered = false; } bool LVideoSurface::present(const QVideoFrame &frame) { - if(!frameImage.isNull()) { + //qDebug() << surfaceFormat().pixelFormat() << frame.pixelFormat() << surfaceFormat().frameSize() << frame.size(); + if(!frameImage.isNull() && !entered) { emit frameReceived(frameImage); return true; } @@ -15,9 +17,10 @@ bool LVideoSurface::present(const QVideoFrame &frame) { //qDebug() << "Recording Frame" << frame.pixelFormat(); QVideoFrame icon(frame); icon.map(QAbstractVideoBuffer::ReadOnly); + //qDebug() << icon.width() << icon.height(); QImage img(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat())); - if(frameImage.isNull()) + if((frameImage.isNull() && !entered) or entered) frameImage = QPixmap::fromImage(img.copy(img.rect())); icon.unmap(); @@ -33,26 +36,22 @@ QList LVideoSurface::supportedPixelFormats(QAbstractVi << QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB555 << QVideoFrame::Format_BGRA32 << QVideoFrame::Format_BGR32; } -/*bool VideoSurface::isFormatSupported(const QVideoSurfaceFormat &format) const { - const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); - const QSize size = format.frameSize(); - - return imageFormat != QImage::Format_Invalid && !size.isEmpty() && format.handleType() == QAbstractVideoBuffer::NoHandle; +void LVideoSurface::stop() { + QAbstractVideoSurface::stop(); } -void VideoSurface::stop() { - QAbstractVideoSurface::stop(); +void LVideoSurface::switchRollOver() { + entered = !entered; } -bool VideoSurface::start(const QVideoSurfaceFormat &format) { +bool LVideoSurface::start(const QVideoSurfaceFormat &format) { const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); const QSize size = format.frameSize(); if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) { - this->imageFormat = imageFormat; QAbstractVideoSurface::start(format); return true; } else { return false; } -}*/ +} diff --git a/src-qt5/core/libLumina/LVideoSurface.h b/src-qt5/core/libLumina/LVideoSurface.h index 42a140d9..7a3dcaad 100644 --- a/src-qt5/core/libLumina/LVideoSurface.h +++ b/src-qt5/core/libLumina/LVideoSurface.h @@ -1,3 +1,6 @@ +#ifndef LVIDEOSURFACE_H +#define LVIDEOSURFACE_H + #include #include #include @@ -10,12 +13,14 @@ class LVideoSurface : public QAbstractVideoSurface { LVideoSurface(QObject *parent=0); virtual bool present(const QVideoFrame&); virtual QList supportedPixelFormats(QAbstractVideoBuffer::HandleType) const; - /*virtual QListsurfaceFormat(); - player->setVideoOutput(surface); - player->setMuted(true); - connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus))); - connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(stopVideo(QPixmap))); INFO = 0; } MainUI::~MainUI(){ terminate_thread = true; - surface->deleteLater(); - player->deleteLater(); this->close(); } @@ -91,20 +82,10 @@ void MainUI::LoadFile(QString path, QString type){ ui->label_file_type->setText(ftype); //Now load the icon for the file if(INFO->isImage()){ - //qDebug() << "Set Image:"; - QPixmap pix(INFO->absoluteFilePath()); - ui->label_file_icon->setPixmap( pix.scaledToHeight(64) ); - ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); - //qDebug() << " - done with image"; + ui->label_file_icon = new LVideoLabel(INFO->absoluteFilePath(), false); + //ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); }else if(INFO->isVideo()){ - timer.start(); - QMediaResource video = QMediaResource(QUrl("file://"+INFO->absoluteFilePath())); - video.setResolution(64,64); - player->setMedia(video); - //player->setMedia(QUrl("file://"+INFO->absoluteFilePath())); - player->play(); - player->pause(); - //Pixmap set when video is loaded in stopVideo + ui->label_file_icon = new LVideoLabel(INFO->absoluteFilePath(), true); }else{ ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); } @@ -315,20 +296,6 @@ void MainUI::getXdgCommand(QString prev){ xdgvaluechanged(); } -void MainUI::stopVideo(QPixmap img) { - ui->label_file_icon->setPixmap( img.scaledToHeight(64) ); - player->pause(); - qDebug() << timer.elapsed(); - qDebug() << player->media().canonicalResource().resolution(); -} - -void MainUI::setDuration(QMediaPlayer::MediaStatus status) { - if(status == QMediaPlayer::BufferedMedia) { - player->setPosition(player->duration() / 2); - player->play(); - } -} - void MainUI::on_tool_xdg_getDir_clicked(){ //Find a directory QString dir = ui->line_xdg_wdir->text(); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index 3bc85aae..8cac813c 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace Ui{ class MainUI; @@ -56,8 +57,6 @@ private slots: //UI Buttons void on_push_close_clicked(); void on_push_save_clicked(); - void stopVideo(QPixmap); - void setDuration(QMediaPlayer::MediaStatus); void getXdgCommand(QString prev = ""); //void on_tool_xdg_getCommand_clicked(QString prev = ""); void on_tool_xdg_getDir_clicked(); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro index b53d8cba..14345f50 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro +++ b/src-qt5/desktop-utils/lumina-fileinfo/lumina-fileinfo.pro @@ -13,7 +13,7 @@ target.path = $${L_BINDIR} include(../../core/libLumina/LUtils.pri) #includes LUtils include(../../core/libLumina/LuminaXDG.pri) #include(../../core/libLumina/LuminaSingleApplication.pri) -include(../../core/libLumina/LVideoSurface.pri) +include(../../core/libLumina/LVideoLabel.pri) include(../../core/libLumina/LuminaThemes.pri) SOURCES += main.cpp\ -- cgit From 0de3da7df93ab5791b62d2b3da0a4fc9abdd4e4d Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 12 Oct 2017 10:26:39 -0400 Subject: Add a new screensaver: Warp This is a starfield "warping" effect screensaver. Also turn off a bunch of debugging within the C++ screensaver plugin system --- .../extrafiles/screensavers/Warp.json | 25 ++++++++++ .../extrafiles/screensavers/qml_scripts/Warp.qml | 57 ++++++++++++++++++++++ src-qt5/src-cpp/plugins-screensaver.cpp | 8 +-- 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Warp.json create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Warp.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Warp.json new file mode 100644 index 00000000..888df01f --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Warp.json @@ -0,0 +1,25 @@ +{ + "name" : { + "default" : "Warp" + }, + "description" : { + "default" : "Warp trail through the stars" + }, + "author" : { + "name" : "Ken Moore", + "email" : "ken@ixsystems.com", + "website" : "https://github.com/beanpole135", + "company" : "iXsystems", + "company_website" : "http://ixsystems.com" + }, + "meta" : { + "license" : "3-clause BSD", + "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE", + "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", + "date_created" : "20171012", + "version" : "1.0" + }, + "qml" : { + "exec" : "qml_scripts/Warp.qml" + } +} diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml new file mode 100644 index 00000000..4ad4378f --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml @@ -0,0 +1,57 @@ +import QtQuick 2.0 +import QtGraphicalEffects 1.0 + +Rectangle { + id : canvas + anchors.fill: parent + color: "black" + + // CREATE STARFIELD + Repeater { + model: Math.round(Math.random()*canvas.width/10)+500 + Rectangle { + parent: canvas + x: Math.round(Math.random()*canvas.width) + y: Math.round(Math.random()*canvas.height) + width: Math.round(Math.random()*3)+3 + height: width + radius: width/2 + color: "white" + } + } //end of Repeater + + // NOW CREATE THE WARP EFFECT + ZoomBlur { + id: blur + anchors.fill: canvas + source: canvas + samples: 24 + length: canvas.width / 20 + horizontalOffset: 0 + verticalOffset: 0 + + Behavior on horizontalOffset{ + NumberAnimation{ + duration: 3000 + } + } + Behavior on verticalOffset{ + NumberAnimation{ + duration: 3000 + } + } + } //end of zoom blur + + Timer { + interval: 5 + repeat: true + running: true + property bool starting: true + onTriggered: { + if(starting){ interval = 3010; starting = false; } + blur.horizontalOffset = (Math.random()*canvas.width/4) - (canvas.width/8) + blur.verticalOffset = (Math.random()*canvas.height/4) - (canvas.height/8) + } + } //end of timer + +} //end of canvas rectangle diff --git a/src-qt5/src-cpp/plugins-screensaver.cpp b/src-qt5/src-cpp/plugins-screensaver.cpp index e9ac1330..75e93c9d 100644 --- a/src-qt5/src-cpp/plugins-screensaver.cpp +++ b/src-qt5/src-cpp/plugins-screensaver.cpp @@ -61,7 +61,7 @@ if(ok){ QJsonArray tmpA = data.value("additional_files").toArray(); for(int i=0; i SSPluginSystem::findAllPlugins(bool validonly){ if(!QFile::exists(dirs[i]+REL_DIR)){ continue; } QDir dir(dirs[i]+REL_DIR); QStringList files = dir.entryList(QStringList() << "*.json", QDir::Files, QDir::Name); - qDebug() << "Found Files:" << files; + //qDebug() << "Found Files:" << files; for(int j=0; j Date: Thu, 12 Oct 2017 10:43:19 -0400 Subject: Add some color to the "Warp" starfield. --- .../extrafiles/screensavers/qml_scripts/Warp.qml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml index 4ad4378f..08ae15a0 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml @@ -5,7 +5,13 @@ Rectangle { id : canvas anchors.fill: parent color: "black" - + + function getStarColor(num){ + if(num < 0.5) { return "white" } + if(num < 1.5) { return "mistyrose" } + return "lightblue" + } + // CREATE STARFIELD Repeater { model: Math.round(Math.random()*canvas.width/10)+500 @@ -16,7 +22,8 @@ Rectangle { width: Math.round(Math.random()*3)+3 height: width radius: width/2 - color: "white" + color: getStarColor( (index%3) ) + } } //end of Repeater -- cgit From 221c57a127579d6ad4849b475e107d7b60369db3 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 12 Oct 2017 11:10:58 -0400 Subject: Remove the plaintext input option for lumina-checkpass, and add more usage reporting/output if the first input flag is invalid. --- src-qt5/core/lumina-checkpass/main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-checkpass/main.c b/src-qt5/core/lumina-checkpass/main.c index 481cce33..2f54c8e6 100644 --- a/src-qt5/core/lumina-checkpass/main.c +++ b/src-qt5/core/lumina-checkpass/main.c @@ -27,7 +27,7 @@ void showUsage(){ puts("lumina-checkpass: Simple user-level check for password validity (for screen unlockers and such)."); puts("Usage:"); - puts(" lumina-checkpass "); + //puts(" lumina-checkpass "); puts(" lumina-checkpass -fd "); puts(" lumina-checkpass -f "); puts("Returns: 0 for a valid password, 1 for invalid"); @@ -35,14 +35,13 @@ void showUsage(){ int main(int argc, char** argv){ //Check the inputs - if(argc<2){ + if(argc!=3){ //Invalid inputs - show the help text showUsage(); return 1; } char*pass = 0; - if(argc==2){ pass = argv[1]; } - else if(argc==3 && 0==strcmp(argv[1],"-fd") ){ + if(argc==3 && 0==strcmp(argv[1],"-fd") ){ FILE *fp = fdopen(atoi(argv[2]), "r"); size_t len; if(fp!=0){ @@ -56,6 +55,11 @@ int main(int argc, char** argv){ if(fp!=0){ ssize_t slen = getline(&pass, &len, fp); if(pass[slen-1]=='\n'){ pass[slen-1] = '\0'; } + }else{ + puts("[ERROR] Unknown option provided"); + puts("----------------"); + showUsage(); + return 1; } fclose(fp); } -- cgit From 465ea1c7cb25bbc45c33be0e7bef5541540c5b20 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 12 Oct 2017 11:38:04 -0400 Subject: Tinker with the color divisions in "Warp" a bit - ensure more even distribution of colors --- .../extrafiles/screensavers/qml_scripts/Warp.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml index 08ae15a0..1cf9bc37 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Warp.qml @@ -7,8 +7,8 @@ Rectangle { color: "black" function getStarColor(num){ - if(num < 0.5) { return "white" } - if(num < 1.5) { return "mistyrose" } + if(num < 1) { return "white" } + if(num < 2) { return "mistyrose" } return "lightblue" } -- cgit From 34bac34d5d1e7d95120ab745e2be42dd3cdccef5 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 12 Oct 2017 13:51:47 -0400 Subject: Add the beginnings of the root desktop QML system. Not finished yet. --- src-qt5/src-cpp/RootDesktopObject.cpp | 44 ++++++++++++++++++++++ src-qt5/src-cpp/RootDesktopObject.h | 71 +++++++++++++++++++++++++++++++++++ src-qt5/src-qml/RootDesktop.qml | 39 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 src-qt5/src-cpp/RootDesktopObject.cpp create mode 100644 src-qt5/src-cpp/RootDesktopObject.h create mode 100644 src-qt5/src-qml/RootDesktop.qml (limited to 'src-qt5') diff --git a/src-qt5/src-cpp/RootDesktopObject.cpp b/src-qt5/src-cpp/RootDesktopObject.cpp new file mode 100644 index 00000000..088c88b7 --- /dev/null +++ b/src-qt5/src-cpp/RootDesktopObject.cpp @@ -0,0 +1,44 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "RootDesktopObject.h" + +// === PUBLIC === +RootDesktopObject::RootDesktopObject(QObject *parent = 0){ + updateScreens(); //make sure the internal list is updated right away +} + +RootDesktopObject::~RootDesktopObject(){ + +} + +static RootDesktopObject* RootDesktopObject::instance(){ + static RootDesktopObject* r_obj = new RootDesktopObject(); + return r_obj; +} + +//QML Read Functions +QList RootDesktopObject::screens(){ + return ; +} + +// === PUBLIC SLOTS === +void RootDesktopObject::updateScreens(){ + QList scrns = QApplication::screens(); + QList tmp; //copy of the internal array initially + for(int i=0; ideleteLater(); } + s_objects = tmp; +} + +// === PRIVATE === diff --git a/src-qt5/src-cpp/RootDesktopObject.h b/src-qt5/src-cpp/RootDesktopObject.h new file mode 100644 index 00000000..08c15fa2 --- /dev/null +++ b/src-qt5/src-cpp/RootDesktopObject.h @@ -0,0 +1,71 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the base C++ object that is used to pass information to the QML "RootDesktop" object +//=========================================== +#ifndef _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H +#define _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H + +class ScreenObject : public QObject{ + Q_OBJECT + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) + Q_PROPERTY( QScreen * screen READ screen) + +private: + QScreen* bg_screen; + QString bg; + +public + ScreenObject(QScreen *scrn, QObject *parent = 0) : QObject(parent){ + bg_screen = scrn; + } + + QString name(){ return bg_screen->name(); } + QString background(){ return bg; } + QScreen* screen(){ return screen; } + +public slots: + void setBackground(QString fileOrColor){ + if(bg!=fileOrColor){ + bg = fileOrColor; + emit backgroundChanged(); + } + } + +signals: + void backgroundChanged(); +}; + + +class RootDesktopObject : public QObject{ + Q_OBJECT + //Define all the QML Properties here (interface between QML and the C++ methods below) + Q_PROPERTY( QList screens READ screens NOTIFY screensChanged) + +public: + //main contructor/destructor + RootDesktopObject(QObject *parent = 0); + ~RootDesktopObject(); + //primary interface to fetch the current instance of the class (so only one is running at any given time) + static RootDesktopObject* instance(); + + //QML Read Functions + QList screens(); + +private: + QList s_objects; + +public slots: + void updateScreens(); //rescan/update screen objects + +private slots: + +signals: + void screensChanged(); + +}; +#endif diff --git a/src-qt5/src-qml/RootDesktop.qml b/src-qt5/src-qml/RootDesktop.qml new file mode 100644 index 00000000..d4d7fed7 --- /dev/null +++ b/src-qt5/src-qml/RootDesktop.qml @@ -0,0 +1,39 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the base QML script the launches/controls the desktop interface itself +//=========================================== +// NOTE: This needs to be paired/used with the corresponding C++ class: RootDesktopObject +// Which should be added as the "RootObject" context property to the QML engine +//------------------ +// Example Code: +// RootDesktopObject *rootobj = new RootDesktopObject(); +// QQuickView *root = new QQuickView(); +// root->setResizeMode(QQuickView::SizeRootObjectToView); +// root->engine()->rootContext->setContextProperty("RootObject", rootobj); +//=========================================== +import QtQuick 2.0 +import QtQuick.Window 2.2 + +Rectangle { + id: RootCanvas + color: "black" + + //Setup the wallpapers + Repeater{ + model: RootObject.screens + AnimatedImage { + id: modelData.name + asynchronous: true + clip: true + source: modelData.background + x: modelData.screen.virtualX + y: modelData.screen.virtualY + width: modelData.screen.width + height: modelData.screen.height + } + } +} -- cgit From 27992c407e1d67b14c7d20aa378193d5590b1d52 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 13 Oct 2017 14:00:14 -0400 Subject: Another checkpoint commit - almost ready to start running tests with QML for the desktop background/wallpapers --- src-qt5/src-cpp/Desktop.pri | 9 ++ src-qt5/src-cpp/RootDesktopObject.h | 39 ++------- src-qt5/src-cpp/ScreenObject.h | 50 +++++++++++ src-qt5/src-qml/CPUGaugeStyle.qml | 156 --------------------------------- src-qt5/src-qml/Clock.qml | 101 --------------------- src-qt5/src-qml/RootDesktop.qml | 27 +++++- src-qt5/src-qml/src-qml.pri | 9 ++ src-qt5/src-qml/src-qml.qrc | 5 ++ src-qt5/src-qml/test-basic.qml | 48 ---------- src-qt5/src-qml/test-cpugauge.qml | 108 ----------------------- src-qt5/src-qml/test/CPUGaugeStyle.qml | 156 +++++++++++++++++++++++++++++++++ src-qt5/src-qml/test/Clock.qml | 101 +++++++++++++++++++++ src-qt5/src-qml/test/ListData.h | 41 +++++++++ src-qt5/src-qml/test/ListTest.qml | 19 ++++ src-qt5/src-qml/test/test-basic.qml | 48 ++++++++++ src-qt5/src-qml/test/test-cpugauge.qml | 108 +++++++++++++++++++++++ src-qt5/src-qml/test/testlist.cpp | 37 ++++++++ src-qt5/src-qml/test/testlist.pro | 7 ++ 18 files changed, 623 insertions(+), 446 deletions(-) create mode 100644 src-qt5/src-cpp/Desktop.pri create mode 100644 src-qt5/src-cpp/ScreenObject.h delete mode 100644 src-qt5/src-qml/CPUGaugeStyle.qml delete mode 100644 src-qt5/src-qml/Clock.qml create mode 100644 src-qt5/src-qml/src-qml.pri create mode 100644 src-qt5/src-qml/src-qml.qrc delete mode 100644 src-qt5/src-qml/test-basic.qml delete mode 100644 src-qt5/src-qml/test-cpugauge.qml create mode 100644 src-qt5/src-qml/test/CPUGaugeStyle.qml create mode 100644 src-qt5/src-qml/test/Clock.qml create mode 100644 src-qt5/src-qml/test/ListData.h create mode 100644 src-qt5/src-qml/test/ListTest.qml create mode 100644 src-qt5/src-qml/test/test-basic.qml create mode 100644 src-qt5/src-qml/test/test-cpugauge.qml create mode 100644 src-qt5/src-qml/test/testlist.cpp create mode 100644 src-qt5/src-qml/test/testlist.pro (limited to 'src-qt5') diff --git a/src-qt5/src-cpp/Desktop.pri b/src-qt5/src-cpp/Desktop.pri new file mode 100644 index 00000000..c7da397d --- /dev/null +++ b/src-qt5/src-cpp/Desktop.pri @@ -0,0 +1,9 @@ + +QT *= gui qml quick + +SOURCES *= RootDesktopObject.cpp + +HEADERS *= RootDesktopObject.h \ + ScreenObject.h + +include(../src-qml/src-qml.pri) diff --git a/src-qt5/src-cpp/RootDesktopObject.h b/src-qt5/src-cpp/RootDesktopObject.h index 08c15fa2..b706bcb6 100644 --- a/src-qt5/src-cpp/RootDesktopObject.h +++ b/src-qt5/src-cpp/RootDesktopObject.h @@ -9,38 +9,7 @@ #ifndef _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H #define _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H -class ScreenObject : public QObject{ - Q_OBJECT - Q_PROPERTY( QString name READ name ) - Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) - Q_PROPERTY( QScreen * screen READ screen) - -private: - QScreen* bg_screen; - QString bg; - -public - ScreenObject(QScreen *scrn, QObject *parent = 0) : QObject(parent){ - bg_screen = scrn; - } - - QString name(){ return bg_screen->name(); } - QString background(){ return bg; } - QScreen* screen(){ return screen; } - -public slots: - void setBackground(QString fileOrColor){ - if(bg!=fileOrColor){ - bg = fileOrColor; - emit backgroundChanged(); - } - } - -signals: - void backgroundChanged(); -}; - - +#include "ScreenObject.h" class RootDesktopObject : public QObject{ Q_OBJECT //Define all the QML Properties here (interface between QML and the C++ methods below) @@ -50,12 +19,18 @@ public: //main contructor/destructor RootDesktopObject(QObject *parent = 0); ~RootDesktopObject(); + + static void RegisterType(){ qmlRegisterType("Lumina.Backend.RootDesktopObject",2,0, "RootDesktopObject"); + //primary interface to fetch the current instance of the class (so only one is running at any given time) static RootDesktopObject* instance(); //QML Read Functions QList screens(); + //QML Access Functions + Q_INVOKABLE void logout(); + private: QList s_objects; diff --git a/src-qt5/src-cpp/ScreenObject.h b/src-qt5/src-cpp/ScreenObject.h new file mode 100644 index 00000000..49f266c3 --- /dev/null +++ b/src-qt5/src-cpp/ScreenObject.h @@ -0,0 +1,50 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the base C++ object that is used to pass information to the QML "RootDesktop" object +//=========================================== +#ifndef _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H +#define _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H + +class ScreenObject : public QObject{ + Q_OBJECT + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) + Q_PROPERTY( int x READ x NOTIFY geomChanged) + Q_PROPERTY( int y READ y NOTIFY geomChanged) + Q_PROPERTY( int width READ width NOTIFY geomChanged) + Q_PROPERTY( int height READ height NOTIFY geomChanged) + +private: + QScreen *bg_screen; + QString bg; + +public + ScreenObject(QScreen *scrn, QObject *parent = 0) : QObject(parent){ + bg_screen = scrn; + } + + static void RegisterType(){ qmlRegisterType("Lumina.Backend.ScreenObject",2,0, "ScreenObject"); + + QString name(){ return bg_screen->name(); } + QString background(){ return bg; } + int x(){ return bg_screen->geometry().x(); } + int y(){ return bg_screen->geometry().y(); } + int width(){ return bg_screen->geometry().width(); } + int height(){ return bg_screen->geometry().height(); } + +public slots: + void setBackground(QString fileOrColor){ + if(bg!=fileOrColor){ + bg = fileOrColor; + emit backgroundChanged(); + } + } + +signals: + void backgroundChanged(); + void geomChanged(); +}; diff --git a/src-qt5/src-qml/CPUGaugeStyle.qml b/src-qt5/src-qml/CPUGaugeStyle.qml deleted file mode 100644 index 4728d136..00000000 --- a/src-qt5/src-qml/CPUGaugeStyle.qml +++ /dev/null @@ -1,156 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.2 -import QtQuick.Controls.Styles 1.4 - -CircularGaugeStyle { - id: cpugauge - tickmarkInset: toPixels(0.04) - minorTickmarkInset: tickmarkInset - labelStepSize: 20 - labelInset: toPixels(0.23) - - property real xCenter: outerRadius - property real yCenter: outerRadius - property real needleLength: outerRadius - tickmarkInset * 1.25 - property real needleTipWidth: toPixels(0.02) - property real needleBaseWidth: toPixels(0.06) - property bool halfGauge: false - - function toPixels(percentage) { - return percentage * outerRadius; - } - - function degToRad(degrees) { - return degrees * (Math.PI / 180); - } - - function radToDeg(radians) { - return radians * (180 / Math.PI); - } - - function paintBackground(ctx) { - if (halfGauge) { - ctx.beginPath(); - ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height / 2); - ctx.clip(); - } - - ctx.beginPath(); - ctx.fillStyle = "black"; - ctx.ellipse(0, 0, ctx.canvas.width, ctx.canvas.height); - ctx.fill(); - - ctx.beginPath(); - ctx.lineWidth = tickmarkInset; - ctx.strokeStyle = "black"; - ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); - ctx.stroke(); - - ctx.beginPath(); - ctx.lineWidth = tickmarkInset / 2; - ctx.strokeStyle = "#222"; - ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); - ctx.stroke(); - - ctx.beginPath(); - var gradient = ctx.createRadialGradient(xCenter, yCenter, outerRadius * 0.8, xCenter, yCenter, outerRadius); - gradient.addColorStop(0, Qt.rgba(1, 1, 1, 0)); - gradient.addColorStop(0.7, Qt.rgba(1, 1, 1, 0.13)); - gradient.addColorStop(1, Qt.rgba(1, 1, 1, 1)); - ctx.fillStyle = gradient; - ctx.arc(xCenter, yCenter, outerRadius - tickmarkInset, outerRadius - tickmarkInset, 0, Math.PI * 2); - ctx.fill(); - } - - background: Canvas { - onPaint: { - var ctx = getContext("2d"); - ctx.reset(); - paintBackground(ctx); - } - - } - - needle: Canvas { - implicitWidth: needleBaseWidth - implicitHeight: needleLength - - property real xCenter: width / 2 - property real yCenter: height / 2 - - onPaint: { - var ctx = getContext("2d"); - ctx.reset(); - - ctx.beginPath(); - ctx.moveTo(xCenter, height); - ctx.lineTo(xCenter - needleBaseWidth / 2, height - needleBaseWidth / 2); - ctx.lineTo(xCenter - needleTipWidth / 2, 0); - ctx.lineTo(xCenter, yCenter - needleLength); - ctx.lineTo(xCenter, 0); - ctx.closePath(); - ctx.fillStyle = Qt.rgba(0.66, 0, 0, 0.66); - ctx.fill(); - - ctx.beginPath(); - ctx.moveTo(xCenter, height) - ctx.lineTo(width, height - needleBaseWidth / 2); - ctx.lineTo(xCenter + needleTipWidth / 2, 0); - ctx.lineTo(xCenter, 0); - ctx.closePath(); - ctx.fillStyle = Qt.lighter(Qt.rgba(0.66, 0, 0, 0.66)); - ctx.fill(); - } - } - - foreground: null -} diff --git a/src-qt5/src-qml/Clock.qml b/src-qt5/src-qml/Clock.qml deleted file mode 100644 index 685346cb..00000000 --- a/src-qt5/src-qml/Clock.qml +++ /dev/null @@ -1,101 +0,0 @@ -import QtQuick 2.0 -import QtGraphicalEffects 1.0 - -Item { - id : clock - width: { - if (ListView.view && ListView.view.width >= 400) - return ListView.view.width / Math.floor(ListView.view.width / 400.0); - else - return 400; - } - - height: { - if (ListView.view && ListView.view.height >= 440) - return ListView.view.height; - else - return 440; - } - - property alias city: cityLabel.text - property int hours - property int minutes - property int seconds - property real shift - property bool night: false - property bool internationalTime: true //Unset for local time - - function timeChanged() { - var date = new Date; - hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours() - night = ( hours < 7 || hours > 19 ) - minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes() - seconds = date.getUTCSeconds(); - } - - Timer { - interval: 100; running: true; repeat: true; - onTriggered: clock.timeChanged() - } - - Item { - anchors.centerIn: parent - width: 200; height: 240 - Rectangle { anchors.fill: parent; color: "#80ff0000"; border.color: "red"; } - - Image { id: background; source: "clock.png"; visible: clock.night == false } - Image { source: "clock-night.png"; visible: clock.night == true } - - Image { - x: 92.5; y: 27 - source: "hour.png" - transform: Rotation { - id: hourRotation - origin.x: 7.5; origin.y: 73; - angle: (clock.hours * 30) + (clock.minutes * 0.5) - Behavior on angle { - SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } - } - } - } - - Image { - x: 93.5; y: 17 - source: "minute.png" - transform: Rotation { - id: minuteRotation - origin.x: 6.5; origin.y: 83; - angle: clock.minutes * 6 - Behavior on angle { - SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } - } - } - } - - Image { - x: 97.5; y: 20 - source: "second.png" - transform: Rotation { - id: secondRotation - origin.x: 2.5; origin.y: 80; - angle: clock.seconds * 6 - Behavior on angle { - SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } - } - } - } - - Image { - anchors.centerIn: background; source: "center.png" - } - - Text { - id: cityLabel - y: 210; anchors.horizontalCenter: parent.horizontalCenter - color: "white" - font.family: "Helvetica" - font.bold: true; font.pixelSize: 16 - style: Text.Raised; styleColor: "black" - } - } -} diff --git a/src-qt5/src-qml/RootDesktop.qml b/src-qt5/src-qml/RootDesktop.qml index d4d7fed7..0003366b 100644 --- a/src-qt5/src-qml/RootDesktop.qml +++ b/src-qt5/src-qml/RootDesktop.qml @@ -13,15 +13,40 @@ // RootDesktopObject *rootobj = new RootDesktopObject(); // QQuickView *root = new QQuickView(); // root->setResizeMode(QQuickView::SizeRootObjectToView); -// root->engine()->rootContext->setContextProperty("RootObject", rootobj); +// root->engine()->rootContext()->setContextProperty("RootObject", rootobj); //=========================================== import QtQuick 2.0 import QtQuick.Window 2.2 +import Lumina.Backend.RootDesktopObject 2.0 +import Lumina.Backend.ScreenObject 2.0 + Rectangle { id: RootCanvas color: "black" + //Setup the right-click context menu + MouseArea { + anchors.fill: RootCanvas + acceptedButton: Qt.RightButton + onClicked: { contextMenu.open() } + } + + //Create the context menu itself + Menu { + id: contextMenu + + MenuItem { + test: qtTr("Logout") + indicator: Image{ + asynchronous: true + autoTransform: true + source: "image://theme/system-logout" + } + onTriggered: RootObject.logout() + } + } + //Setup the wallpapers Repeater{ model: RootObject.screens diff --git a/src-qt5/src-qml/src-qml.pri b/src-qt5/src-qml/src-qml.pri new file mode 100644 index 00000000..bcdd439d --- /dev/null +++ b/src-qt5/src-qml/src-qml.pri @@ -0,0 +1,9 @@ +#Show the QML files to lupdate for translation purposes - not for the actual build + +QT *= quick qml + +lupdate_only{ + SOURCES *= RootDesktop.qml +} + +RESOURCES *= src-qml.qrc diff --git a/src-qt5/src-qml/src-qml.qrc b/src-qt5/src-qml/src-qml.qrc new file mode 100644 index 00000000..41f9d54b --- /dev/null +++ b/src-qt5/src-qml/src-qml.qrc @@ -0,0 +1,5 @@ + + + RootDesktop.qml + + diff --git a/src-qt5/src-qml/test-basic.qml b/src-qt5/src-qml/test-basic.qml deleted file mode 100644 index 5d21ae41..00000000 --- a/src-qt5/src-qml/test-basic.qml +++ /dev/null @@ -1,48 +0,0 @@ -import QtQuick 2.0 -import "." as QML - -Rectangle { - id: root - width: 800; height: 600 - color: "#646464" - - ListView { - id: clockview - anchors.fill: parent - orientation: ListView.Horizontal - cacheBuffer: 2000 - snapMode: ListView.SnapOneItem - highlightRangeMode: ListView.ApplyRange - - delegate: QML.Clock { city: cityName; shift: timeShift } - model: ListModel { - ListElement { cityName: "New York"; timeShift: -4 } - ListElement { cityName: "London"; timeShift: 0 } - ListElement { cityName: "Oslo"; timeShift: 1 } - ListElement { cityName: "Mumbai"; timeShift: 5.5 } - ListElement { cityName: "Tokyo"; timeShift: 9 } - ListElement { cityName: "Brisbane"; timeShift: 10 } - ListElement { cityName: "Los Angeles"; timeShift: -8 } - } - } - - Image { - anchors.left: parent.left - anchors.bottom: parent.bottom - anchors.margins: 10 - source: "content/arrow.png" - rotation: -90 - opacity: clockview.atXBeginning ? 0 : 0.5 - Behavior on opacity { NumberAnimation { duration: 500 } } - } - - Image { - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: 10 - source: "content/arrow.png" - rotation: 90 - opacity: clockview.atXEnd ? 0 : 0.5 - Behavior on opacity { NumberAnimation { duration: 500 } } - } -} diff --git a/src-qt5/src-qml/test-cpugauge.qml b/src-qt5/src-qml/test-cpugauge.qml deleted file mode 100644 index 1151c435..00000000 --- a/src-qt5/src-qml/test-cpugauge.qml +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.2 -import QtQuick.Window 2.1 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 -import QtQuick.Extras 1.4 - -import "." as QML - -Rectangle{ - id: rootwindow - visible: true - width: 800 - height: 600 - - color: "#161616" - property alias cpu: cpu - - Item { - id: container - anchors.fill: parent - property real diff: 5.1 - - Row { - id: gaugeRow - spacing: container.width * 0.02 - anchors.centerIn: parent - - CircularGauge { - id: cpu - width: height - height: container.height * 0.9 - gaugeRow.spacing - value: 0 - maximumValue: 100 - anchors.verticalCenter: parent.verticalCenter - - style: QML.CPUGaugeStyle {} - - } - - function updatevalue() { - if( container.diff >0 && cpu.value > (100-container.diff) ){ - cpu.value = 100; - container.diff = 0 - container.diff - } else if( container.diff <0 && cpu.value <(0-container.diff) ){ - cpu.value = 0; - container.diff = 0 - container.diff - } else { - cpu.value = cpu.value + container.diff - } - } - - Timer { - interval: 100; running: true; repeat: true; - onTriggered: gaugeRow.updatevalue() - } - } - } -} diff --git a/src-qt5/src-qml/test/CPUGaugeStyle.qml b/src-qt5/src-qml/test/CPUGaugeStyle.qml new file mode 100644 index 00000000..4728d136 --- /dev/null +++ b/src-qt5/src-qml/test/CPUGaugeStyle.qml @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls.Styles 1.4 + +CircularGaugeStyle { + id: cpugauge + tickmarkInset: toPixels(0.04) + minorTickmarkInset: tickmarkInset + labelStepSize: 20 + labelInset: toPixels(0.23) + + property real xCenter: outerRadius + property real yCenter: outerRadius + property real needleLength: outerRadius - tickmarkInset * 1.25 + property real needleTipWidth: toPixels(0.02) + property real needleBaseWidth: toPixels(0.06) + property bool halfGauge: false + + function toPixels(percentage) { + return percentage * outerRadius; + } + + function degToRad(degrees) { + return degrees * (Math.PI / 180); + } + + function radToDeg(radians) { + return radians * (180 / Math.PI); + } + + function paintBackground(ctx) { + if (halfGauge) { + ctx.beginPath(); + ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height / 2); + ctx.clip(); + } + + ctx.beginPath(); + ctx.fillStyle = "black"; + ctx.ellipse(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.fill(); + + ctx.beginPath(); + ctx.lineWidth = tickmarkInset; + ctx.strokeStyle = "black"; + ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); + ctx.stroke(); + + ctx.beginPath(); + ctx.lineWidth = tickmarkInset / 2; + ctx.strokeStyle = "#222"; + ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); + ctx.stroke(); + + ctx.beginPath(); + var gradient = ctx.createRadialGradient(xCenter, yCenter, outerRadius * 0.8, xCenter, yCenter, outerRadius); + gradient.addColorStop(0, Qt.rgba(1, 1, 1, 0)); + gradient.addColorStop(0.7, Qt.rgba(1, 1, 1, 0.13)); + gradient.addColorStop(1, Qt.rgba(1, 1, 1, 1)); + ctx.fillStyle = gradient; + ctx.arc(xCenter, yCenter, outerRadius - tickmarkInset, outerRadius - tickmarkInset, 0, Math.PI * 2); + ctx.fill(); + } + + background: Canvas { + onPaint: { + var ctx = getContext("2d"); + ctx.reset(); + paintBackground(ctx); + } + + } + + needle: Canvas { + implicitWidth: needleBaseWidth + implicitHeight: needleLength + + property real xCenter: width / 2 + property real yCenter: height / 2 + + onPaint: { + var ctx = getContext("2d"); + ctx.reset(); + + ctx.beginPath(); + ctx.moveTo(xCenter, height); + ctx.lineTo(xCenter - needleBaseWidth / 2, height - needleBaseWidth / 2); + ctx.lineTo(xCenter - needleTipWidth / 2, 0); + ctx.lineTo(xCenter, yCenter - needleLength); + ctx.lineTo(xCenter, 0); + ctx.closePath(); + ctx.fillStyle = Qt.rgba(0.66, 0, 0, 0.66); + ctx.fill(); + + ctx.beginPath(); + ctx.moveTo(xCenter, height) + ctx.lineTo(width, height - needleBaseWidth / 2); + ctx.lineTo(xCenter + needleTipWidth / 2, 0); + ctx.lineTo(xCenter, 0); + ctx.closePath(); + ctx.fillStyle = Qt.lighter(Qt.rgba(0.66, 0, 0, 0.66)); + ctx.fill(); + } + } + + foreground: null +} diff --git a/src-qt5/src-qml/test/Clock.qml b/src-qt5/src-qml/test/Clock.qml new file mode 100644 index 00000000..685346cb --- /dev/null +++ b/src-qt5/src-qml/test/Clock.qml @@ -0,0 +1,101 @@ +import QtQuick 2.0 +import QtGraphicalEffects 1.0 + +Item { + id : clock + width: { + if (ListView.view && ListView.view.width >= 400) + return ListView.view.width / Math.floor(ListView.view.width / 400.0); + else + return 400; + } + + height: { + if (ListView.view && ListView.view.height >= 440) + return ListView.view.height; + else + return 440; + } + + property alias city: cityLabel.text + property int hours + property int minutes + property int seconds + property real shift + property bool night: false + property bool internationalTime: true //Unset for local time + + function timeChanged() { + var date = new Date; + hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours() + night = ( hours < 7 || hours > 19 ) + minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes() + seconds = date.getUTCSeconds(); + } + + Timer { + interval: 100; running: true; repeat: true; + onTriggered: clock.timeChanged() + } + + Item { + anchors.centerIn: parent + width: 200; height: 240 + Rectangle { anchors.fill: parent; color: "#80ff0000"; border.color: "red"; } + + Image { id: background; source: "clock.png"; visible: clock.night == false } + Image { source: "clock-night.png"; visible: clock.night == true } + + Image { + x: 92.5; y: 27 + source: "hour.png" + transform: Rotation { + id: hourRotation + origin.x: 7.5; origin.y: 73; + angle: (clock.hours * 30) + (clock.minutes * 0.5) + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + x: 93.5; y: 17 + source: "minute.png" + transform: Rotation { + id: minuteRotation + origin.x: 6.5; origin.y: 83; + angle: clock.minutes * 6 + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + x: 97.5; y: 20 + source: "second.png" + transform: Rotation { + id: secondRotation + origin.x: 2.5; origin.y: 80; + angle: clock.seconds * 6 + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + anchors.centerIn: background; source: "center.png" + } + + Text { + id: cityLabel + y: 210; anchors.horizontalCenter: parent.horizontalCenter + color: "white" + font.family: "Helvetica" + font.bold: true; font.pixelSize: 16 + style: Text.Raised; styleColor: "black" + } + } +} diff --git a/src-qt5/src-qml/test/ListData.h b/src-qt5/src-qml/test/ListData.h new file mode 100644 index 00000000..7dd6f6e2 --- /dev/null +++ b/src-qt5/src-qml/test/ListData.h @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +class ListData : public QObject{ + Q_OBJECT + Q_PROPERTY(QList list READ list NOTIFY listchanged); +signals: + void listchanged(); + +private: + QStringList m_list; + //QTimer *timer; + //bool increasing; + +private slots: + void changeList(){ + /*if(m_list.isEmpty()){ increasing = true; } + else if(m_list.length() == 5){ increasing = false; } + if(increasing){ m_list << "Text - "+QString::number( m_list.length()+1 ); } + else{ m_list.takeAt(m_list.count()-1); } + emit listchanged();*/ + } + +public: + ListData() : QObject(){ + /*increasing = true; + timer = new QTimer(this); + timer->setInterval(1000); + timer->setSingleShot(false); + connect(timer, SIGNAL(timeout()), this, SLOT(changeList()) ); + timer->start();*/ + } + + QList list() { return QApplication::screens(); } //m_list; } +}; diff --git a/src-qt5/src-qml/test/ListTest.qml b/src-qt5/src-qml/test/ListTest.qml new file mode 100644 index 00000000..e6b6ba35 --- /dev/null +++ b/src-qt5/src-qml/test/ListTest.qml @@ -0,0 +1,19 @@ +import QtQuick 2.2 +import QtQuick.Layouts 1.3 + +Rectangle { + id: canvas + color: "black" + + ColumnLayout{ + anchors.fill: canvas + + Repeater{ + model: cppdata.list + Text{ + color: "white" + text: modelData + } + } + } //end row layout +} diff --git a/src-qt5/src-qml/test/test-basic.qml b/src-qt5/src-qml/test/test-basic.qml new file mode 100644 index 00000000..5d21ae41 --- /dev/null +++ b/src-qt5/src-qml/test/test-basic.qml @@ -0,0 +1,48 @@ +import QtQuick 2.0 +import "." as QML + +Rectangle { + id: root + width: 800; height: 600 + color: "#646464" + + ListView { + id: clockview + anchors.fill: parent + orientation: ListView.Horizontal + cacheBuffer: 2000 + snapMode: ListView.SnapOneItem + highlightRangeMode: ListView.ApplyRange + + delegate: QML.Clock { city: cityName; shift: timeShift } + model: ListModel { + ListElement { cityName: "New York"; timeShift: -4 } + ListElement { cityName: "London"; timeShift: 0 } + ListElement { cityName: "Oslo"; timeShift: 1 } + ListElement { cityName: "Mumbai"; timeShift: 5.5 } + ListElement { cityName: "Tokyo"; timeShift: 9 } + ListElement { cityName: "Brisbane"; timeShift: 10 } + ListElement { cityName: "Los Angeles"; timeShift: -8 } + } + } + + Image { + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.margins: 10 + source: "content/arrow.png" + rotation: -90 + opacity: clockview.atXBeginning ? 0 : 0.5 + Behavior on opacity { NumberAnimation { duration: 500 } } + } + + Image { + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 10 + source: "content/arrow.png" + rotation: 90 + opacity: clockview.atXEnd ? 0 : 0.5 + Behavior on opacity { NumberAnimation { duration: 500 } } + } +} diff --git a/src-qt5/src-qml/test/test-cpugauge.qml b/src-qt5/src-qml/test/test-cpugauge.qml new file mode 100644 index 00000000..1151c435 --- /dev/null +++ b/src-qt5/src-qml/test/test-cpugauge.qml @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Window 2.1 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Extras 1.4 + +import "." as QML + +Rectangle{ + id: rootwindow + visible: true + width: 800 + height: 600 + + color: "#161616" + property alias cpu: cpu + + Item { + id: container + anchors.fill: parent + property real diff: 5.1 + + Row { + id: gaugeRow + spacing: container.width * 0.02 + anchors.centerIn: parent + + CircularGauge { + id: cpu + width: height + height: container.height * 0.9 - gaugeRow.spacing + value: 0 + maximumValue: 100 + anchors.verticalCenter: parent.verticalCenter + + style: QML.CPUGaugeStyle {} + + } + + function updatevalue() { + if( container.diff >0 && cpu.value > (100-container.diff) ){ + cpu.value = 100; + container.diff = 0 - container.diff + } else if( container.diff <0 && cpu.value <(0-container.diff) ){ + cpu.value = 0; + container.diff = 0 - container.diff + } else { + cpu.value = cpu.value + container.diff + } + } + + Timer { + interval: 100; running: true; repeat: true; + onTriggered: gaugeRow.updatevalue() + } + } + } +} diff --git a/src-qt5/src-qml/test/testlist.cpp b/src-qt5/src-qml/test/testlist.cpp new file mode 100644 index 00000000..cc54c501 --- /dev/null +++ b/src-qt5/src-qml/test/testlist.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ListData.h" + +int main(int argc, char** argv){ + QString QMLFile; + for(int i=1; irootContext()->setContextProperty("cppdata", &data); + qDebug() << "Load QML File:" << QMLFile; + base.setSource(QUrl::fromLocalFile(QMLFile)); + qDebug() << "Start Event loop"; + base.show(); + int ret = A.exec(); + qDebug() << " - Finished"; + return ret; +} diff --git a/src-qt5/src-qml/test/testlist.pro b/src-qt5/src-qml/test/testlist.pro new file mode 100644 index 00000000..69c7bc23 --- /dev/null +++ b/src-qt5/src-qml/test/testlist.pro @@ -0,0 +1,7 @@ +QT = core gui widgets quick quickwidgets qml + +TARGET = test + +SOURCES += testlist.cpp + +HEADERS += ListData.h -- cgit From d04f35ab9b827085d1cbee0bc2f7cae7787557ef Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 13 Oct 2017 16:25:18 -0400 Subject: Another checkpoint commit for Lumina 2 Almost have the QML-based desktop canvas working - still tracking down some QML syntax issues. --- src-qt5/core/libLumina/LDesktopUtils.pri | 1 + src-qt5/core/libLumina/NativeEmbedWidget.cpp | 423 --------- src-qt5/core/libLumina/NativeEmbedWidget.h | 74 -- src-qt5/core/libLumina/NativeEventFilter.cpp | 300 ------- src-qt5/core/libLumina/NativeEventFilter.h | 71 -- src-qt5/core/libLumina/NativeKeyToQt.cpp | 528 ----------- src-qt5/core/libLumina/NativeWindow.cpp | 123 --- src-qt5/core/libLumina/NativeWindow.h | 118 --- src-qt5/core/libLumina/NativeWindow.pri | 18 - src-qt5/core/libLumina/NativeWindowSystem.cpp | 986 --------------------- src-qt5/core/libLumina/NativeWindowSystem.h | 139 --- .../core/libLumina/RootSubWindow-animations.cpp | 116 --- src-qt5/core/libLumina/RootSubWindow.cpp | 601 ------------- src-qt5/core/libLumina/RootSubWindow.h | 109 --- src-qt5/core/libLumina/RootWindow-mgmt.cpp | 95 -- src-qt5/core/libLumina/RootWindow.cpp | 283 ------ src-qt5/core/libLumina/RootWindow.h | 92 -- src-qt5/core/libLumina/RootWindow.pri | 17 - .../obsolete/RootSubWindow-animations.cpp | 116 +++ src-qt5/core/libLumina/obsolete/RootSubWindow.cpp | 601 +++++++++++++ src-qt5/core/libLumina/obsolete/RootSubWindow.h | 109 +++ .../core/libLumina/obsolete/RootWindow-mgmt.cpp | 95 ++ src-qt5/core/libLumina/obsolete/RootWindow.cpp | 283 ++++++ src-qt5/core/libLumina/obsolete/RootWindow.h | 92 ++ src-qt5/core/libLumina/obsolete/RootWindow.pri | 17 + src-qt5/core/lumina-desktop-unified/LSession.cpp | 9 +- .../core/lumina-desktop-unified/global-includes.h | 9 +- .../core/lumina-desktop-unified/global-objects.h | 4 + .../core/lumina-desktop-unified/lumina-desktop.pro | 10 +- .../src-desktop/RootWindow.cpp | 33 + .../src-desktop/RootWindow.h | 32 + .../lumina-desktop-unified/src-desktop/desktop.pri | 8 +- src-qt5/src-cpp/Desktop.pri | 11 +- src-qt5/src-cpp/NativeEmbedWidget.cpp | 423 +++++++++ src-qt5/src-cpp/NativeEmbedWidget.h | 74 ++ src-qt5/src-cpp/NativeEventFilter.cpp | 300 +++++++ src-qt5/src-cpp/NativeEventFilter.h | 71 ++ src-qt5/src-cpp/NativeKeyToQt.cpp | 528 +++++++++++ src-qt5/src-cpp/NativeWindow.cpp | 123 +++ src-qt5/src-cpp/NativeWindow.h | 118 +++ src-qt5/src-cpp/NativeWindow.pri | 17 + src-qt5/src-cpp/NativeWindowSystem.cpp | 986 +++++++++++++++++++++ src-qt5/src-cpp/NativeWindowSystem.h | 139 +++ src-qt5/src-cpp/RootDesktopObject.cpp | 30 +- src-qt5/src-cpp/RootDesktopObject.h | 11 +- src-qt5/src-cpp/ScreenObject.cpp | 30 + src-qt5/src-cpp/ScreenObject.h | 40 +- src-qt5/src-qml/RootDesktop.qml | 6 +- src-qt5/src-qml/src-qml.pri | 4 +- src-qt5/src-qml/src-qml.qrc | 2 +- 50 files changed, 4275 insertions(+), 4150 deletions(-) delete mode 100644 src-qt5/core/libLumina/NativeEmbedWidget.cpp delete mode 100644 src-qt5/core/libLumina/NativeEmbedWidget.h delete mode 100644 src-qt5/core/libLumina/NativeEventFilter.cpp delete mode 100644 src-qt5/core/libLumina/NativeEventFilter.h delete mode 100644 src-qt5/core/libLumina/NativeKeyToQt.cpp delete mode 100644 src-qt5/core/libLumina/NativeWindow.cpp delete mode 100644 src-qt5/core/libLumina/NativeWindow.h delete mode 100644 src-qt5/core/libLumina/NativeWindow.pri delete mode 100644 src-qt5/core/libLumina/NativeWindowSystem.cpp delete mode 100644 src-qt5/core/libLumina/NativeWindowSystem.h delete mode 100644 src-qt5/core/libLumina/RootSubWindow-animations.cpp delete mode 100644 src-qt5/core/libLumina/RootSubWindow.cpp delete mode 100644 src-qt5/core/libLumina/RootSubWindow.h delete mode 100644 src-qt5/core/libLumina/RootWindow-mgmt.cpp delete mode 100644 src-qt5/core/libLumina/RootWindow.cpp delete mode 100644 src-qt5/core/libLumina/RootWindow.h delete mode 100644 src-qt5/core/libLumina/RootWindow.pri create mode 100644 src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp create mode 100644 src-qt5/core/libLumina/obsolete/RootSubWindow.cpp create mode 100644 src-qt5/core/libLumina/obsolete/RootSubWindow.h create mode 100644 src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp create mode 100644 src-qt5/core/libLumina/obsolete/RootWindow.cpp create mode 100644 src-qt5/core/libLumina/obsolete/RootWindow.h create mode 100644 src-qt5/core/libLumina/obsolete/RootWindow.pri create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h create mode 100644 src-qt5/src-cpp/NativeEmbedWidget.cpp create mode 100644 src-qt5/src-cpp/NativeEmbedWidget.h create mode 100644 src-qt5/src-cpp/NativeEventFilter.cpp create mode 100644 src-qt5/src-cpp/NativeEventFilter.h create mode 100644 src-qt5/src-cpp/NativeKeyToQt.cpp create mode 100644 src-qt5/src-cpp/NativeWindow.cpp create mode 100644 src-qt5/src-cpp/NativeWindow.h create mode 100644 src-qt5/src-cpp/NativeWindow.pri create mode 100644 src-qt5/src-cpp/NativeWindowSystem.cpp create mode 100644 src-qt5/src-cpp/NativeWindowSystem.h create mode 100644 src-qt5/src-cpp/ScreenObject.cpp (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.pri b/src-qt5/core/libLumina/LDesktopUtils.pri index 80bbcfa8..fcacc586 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.pri +++ b/src-qt5/core/libLumina/LDesktopUtils.pri @@ -5,3 +5,4 @@ INCLUDEPATH *= ${PWD} #Now the other dependendies of it include(LUtils.pri) +include(LuminaThemes.pri) diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.cpp b/src-qt5/core/libLumina/NativeEmbedWidget.cpp deleted file mode 100644 index 57b6edde..00000000 --- a/src-qt5/core/libLumina/NativeEmbedWidget.cpp +++ /dev/null @@ -1,423 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "NativeEmbedWidget.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -//#include -//#include -#include -#include - -#define DISABLE_COMPOSITING true - -/*inline xcb_render_pictformat_t get_pictformat(){ - static xcb_render_pictformat_t format = 0; - if(format==0){ - xcb_render_query_pict_formats_reply_t *reply = xcb_render_query_pict_formats_reply( QX11Info::connection(), xcb_render_query_pict_formats(QX11Info::connection()), NULL); - format = xcb_render_util_find_standard_format(reply, XCB_PICT_STANDARD_ARGB_32)->id; - free(reply); - } - return format; -} - - -inline void renderWindowToWidget(WId id, QWidget *widget, bool hastransparency = true){ - //window and widget are assumed to be the same size - //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; } - - xcb_render_picture_t pic_id = xcb_generate_id(QX11Info::connection()); - xcb_render_create_picture_aux(QX11Info::connection(), pic_id, pix, get_pictformat() , 0, NULL); - // - xcb_render_composite(QX11Info::connection(), hastransparency ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC, pic_id, XCB_RENDER_PICTURE_NONE, widget->x11RenderHandle(), - 0, 0, 0, 0, 0, 0, (uint16_t) widget->width(), (uint16_t) widget->height() ); -}*/ - -#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_FOCUS_CHANGE | \ - XCB_EVENT_MASK_POINTER_MOTION) - -#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ - XCB_EVENT_MASK_BUTTON_RELEASE | \ - XCB_EVENT_MASK_POINTER_MOTION | \ - XCB_EVENT_MASK_EXPOSURE | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_ENTER_WINDOW) - -inline void registerClientEvents(WId id, bool client = true){ - uint32_t values[] = {XCB_NONE}; - values[0] = client ? CLIENT_EVENT_MASK : FRAME_EVENT_MASK ; - /*{ (XCB_EVENT_MASK_PROPERTY_CHANGE - | XCB_EVENT_MASK_BUTTON_PRESS - | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_POINTER_MOTION - | XCB_EVENT_MASK_BUTTON_MOTION - | XCB_EVENT_MASK_EXPOSURE - | XCB_EVENT_MASK_STRUCTURE_NOTIFY - | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT - | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY - | XCB_EVENT_MASK_ENTER_WINDOW) - };*/ - xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, values); -} - -// ============ -// PRIVATE -// ============ -//Simplification functions for the XCB/XLib interactions -void NativeEmbedWidget::syncWinSize(QSize sz){ - if(WIN==0){ return; } - else if(!sz.isValid()){ sz = this->size(); } //use the current widget size - //qDebug() << "Sync Window Size:" << sz; - //if(sz == winSize){ return; } //no change - QPoint pt(0,0); - if(!DISABLE_COMPOSITING){ pt = this->mapToGlobal(QPoint(0,0)); } - const uint32_t valList[4] = {(uint32_t) pt.x(), (uint32_t) pt.y(), (uint32_t) sz.width(), (uint32_t) sz.height()}; - const uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; - xcb_configure_window(QX11Info::connection(), WIN->id(), mask, valList); - winSize = sz; //save this for checking later -} - -void NativeEmbedWidget::syncWidgetSize(QSize sz){ - //qDebug() << "Sync Widget Size:" << sz; - this->resize(sz); -} - -void NativeEmbedWidget::hideWindow(){ - //qDebug() << "Hide Embed Window"; - xcb_unmap_window(QX11Info::connection(), WIN->id()); -} - -void NativeEmbedWidget::showWindow(){ - //qDebug() << "Show Embed Window"; - xcb_map_window(QX11Info::connection(), WIN->id()); - reregisterEvents(); - if(!DISABLE_COMPOSITING){ - QTimer::singleShot(0,this, SLOT(repaintWindow())); - } -} - -QImage NativeEmbedWidget::windowImage(QRect geom){ - //if(DISABLE_COMPOSITING){ - if(!this->isVisible()){ return QImage(); } //nothing to grab yet - QList screens = static_cast( QApplication::instance() )->screens(); - //for(int i=0; icontains(this)){ - if(!screens.isEmpty()){ - return screens[0]->grabWindow(WIN->id(), geom.x(), geom.y(), geom.width(), geom.height()).toImage(); - } - //} - //} - return QImage(); - /*}else{ - //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 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 QImage(); } - QImage img(ximg->data, ximg->width, ximg->height, ximg->stride, QImage::Format_ARGB32_Premultiplied); - img = img.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); - - //Cleanup the XCB data structures - xcb_free_pixmap(QX11Info::connection(), pix); - - return img; - }*/ -} -void NativeEmbedWidget::setWinUnpaused(){ - paused = false; - winImage = QImage(); - if(!DISABLE_COMPOSITING){ - repaintWindow(); //update the cached image right away - }else if(this->isVisible()){ - showWindow(); - } - resyncWindow(); //make sure the window knows about the new location -} -// ============ -// PUBLIC -// ============ -NativeEmbedWidget::NativeEmbedWidget(QWidget *parent) : QWidget(parent){ - WIN = 0; //nothing embedded yet - paused = false; - this->setMouseTracking(true); - //this->setSizeIncrement(2,2); -} - -bool NativeEmbedWidget::embedWindow(NativeWindow *window){ - WIN = window; - - //Now send the embed event to the app - //qDebug() << " - send _XEMBED event"; - /*xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.window = WIN->id(); - event.type = obj->ATOMS["_XEMBED"]; //_XEMBED - event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; - event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY - event.data.data32[2] = 0; - event.data.data32[3] = this->winId(); //WID of the container - event.data.data32[4] = 0; - - xcb_send_event(QX11Info::connection(), 0, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); - */ - //Now setup any redirects and return - if(!DISABLE_COMPOSITING){ - xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); - xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //AUTOMATIC); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); - - //Now create/register the damage handler - // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore) - // -- Retested 6/29/17 (no change) Ken Moore - //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer - //xcb_damage_create(QX11Info::connection(), dmgID, WIN->id(), XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); - // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself). - Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles); - - WIN->addDamageID( (uint) dmgID); //save this for later - connect(WIN, SIGNAL(VisualChanged()), this, SLOT(repaintWindow()) ); //make sure we repaint the widget on visual change - }else{ - xcb_reparent_window(QX11Info::connection(), WIN->id(), this->winId(), 0, 0); - registerClientEvents(this->winId()); //child events get forwarded through the frame - watch this for changes too - //Also use a partial-composite here - make sure the window pixmap is available even when the window is obscured - xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_AUTOMATIC); - //xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); - //Also alert us when the window visual changes - Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles); - - WIN->addDamageID( (uint) dmgID); //save this for later - connect(WIN, SIGNAL(VisualChanged()), this, SLOT(repaintWindow()) ); //make sure we repaint the widget on visual change - } - WIN->addFrameWinID(this->winId()); - registerClientEvents(WIN->id()); - //qDebug() << "Events Registered:" << WIN->id() << this->winId(); - return true; -} - -bool NativeEmbedWidget::detachWindow(){ - xcb_reparent_window(QX11Info::connection(), WIN->id(), QX11Info::appRootWindow(), -1, -1); - //WIN = 0; - return true; -} - -bool NativeEmbedWidget::isEmbedded(){ - return (WIN!=0); -} - -void NativeEmbedWidget::raiseWindow(){ - if(DISABLE_COMPOSITING){ return; } - uint32_t val = XCB_STACK_MODE_ABOVE; - xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); -} - -void NativeEmbedWidget::lowerWindow(){ - if(DISABLE_COMPOSITING){ return; } - uint32_t val = XCB_STACK_MODE_BELOW; - xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); -} - -// ============== -// PUBLIC SLOTS -// ============== -//Pause/resume -void NativeEmbedWidget::pause(){ - if(DISABLE_COMPOSITING){ - winImage = windowImage(QRect(QPoint(0,0), this->size())); - hideWindow(); - }else{ - if(winImage.isNull()){ repaintWindow(); } //make sure we have one image already cached first - } - paused = true; -} - -void NativeEmbedWidget::resume(){ - //paused = false; - syncWinSize(); - if(DISABLE_COMPOSITING){ - //showWindow(); - }else{ - repaintWindow(); //update the cached image right away - } - QTimer::singleShot(10, this, SLOT(setWinUnpaused()) ); -} - -void NativeEmbedWidget::resyncWindow(){ - if(WIN==0){ return; } - //syncWinSize(); - //if(DISABLE_COMPOSITING){ - // Specs say to send an artificial configure event to the window if the window was reparented into the frame - QPoint loc = this->mapToGlobal( QPoint(0,0) ); - //Send an artificial configureNotify event to the window with the global position/size included - xcb_configure_notify_event_t *event = (xcb_configure_notify_event_t*) calloc(32,1); //always 32-byes long, even if we don't need all of it - event->x = loc.x(); - event->y = loc.y(); - event->width = this->width(); - event->height = this->height(); - event->border_width = 0; - event->above_sibling = XCB_NONE; - event->override_redirect = false; - event->window = WIN->id(); - event->event = WIN->id(); - event->response_type = XCB_CONFIGURE_NOTIFY; - xcb_send_event(QX11Info::connection(), false, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, (char *) event); - xcb_flush(QX11Info::connection()); - free(event); - /*}else{ - //Window is floating invisibly - make sure it is in the right place - //Make sure the window size is syncronized and visual up to date - //syncWinSize(); - QTimer::singleShot(10, this, SLOT(repaintWindow()) ); - }*/ - -} - -void NativeEmbedWidget::repaintWindow(){ - //if(DISABLE_COMPOSITING){ return; } - //qDebug() << "Update Window Image:" << !paused; - if(paused){ return; } - /*QImage tmp = windowImage( QRect(QPoint(0,0), this->size()) ); - if(!tmp.isNull()){ - winImage = tmp; - }else{ qDebug() << "Got Null Image!!"; }*/ - this->parentWidget()->update(); //visual changed - need to update the image on the widget -} - -void NativeEmbedWidget::reregisterEvents(){ - if(WIN!=0){ registerClientEvents(WIN->id()); } -} - -// ============== -// PROTECTED -// ============== -void NativeEmbedWidget::resizeEvent(QResizeEvent *ev){ - QWidget::resizeEvent(ev); - if(WIN!=0 && !paused){ - syncWinSize(ev->size()); - } //syncronize the window with the new widget size -} - -void NativeEmbedWidget::showEvent(QShowEvent *ev){ - if(WIN!=0){ showWindow(); } - QWidget::showEvent(ev); -} - -void NativeEmbedWidget::hideEvent(QHideEvent *ev){ - if(WIN!=0){ hideWindow(); } - QWidget::hideEvent(ev); -} - -void NativeEmbedWidget::paintEvent(QPaintEvent *ev){ - QPainter P(this); - P.setClipping(true); - P.setClipRect(0,0,this->width(), this->height()); - P.fillRect(ev->rect(), Qt::transparent); - if(WIN==0){ return; } - QRect geom = ev->rect(); //atomic updates - //qDebug() << "Paint Rect:" << geom; - QImage img; - if(!paused){ img = windowImage(geom); } - else if(!winImage.isNull()){ - if(winImage.size() == this->size()){ img = winImage.copy(geom); } - else{ img = winImage.scaled(geom.size()); } //this is a fast transformation - might be slightly distorted - } - //Need to paint the image from the window onto the widget as an overlay - P.drawImage( geom , img, QRect(QPoint(0,0), img.size()), Qt::NoOpaqueDetection); //1-to-1 mapping - - -} - -void NativeEmbedWidget::enterEvent(QEvent *ev){ - QWidget::enterEvent(ev); - //qDebug() << "Enter Embed Widget"; - //raiseWindow(); //this->grabMouse(); -} - -void NativeEmbedWidget::leaveEvent(QEvent *ev){ - QWidget::leaveEvent(ev); - /*qDebug() << "Leave Embed Widget"; - QPoint pt = QCursor::pos(); - QPoint relpt = this->parentWidget()->mapFromGlobal(pt); - qDebug() << " - Geom:" << this->geometry() << "Global pt:" << pt << "Relative pt:" << relpt; - if(!this->geometry().contains(relpt) ){ lowerWindow(); }*/ -} - -void NativeEmbedWidget::mouseMoveEvent(QMouseEvent *ev){ - QWidget::mouseMoveEvent(ev); - //Forward this event on to the window -} - -void NativeEmbedWidget::mousePressEvent(QMouseEvent *ev){ - QWidget::mousePressEvent(ev); - //Forward this event on to the window -} - -void NativeEmbedWidget::mouseReleaseEvent(QMouseEvent *ev){ - QWidget::mouseReleaseEvent(ev); - //Forward this event on to the window -} - -/*bool NativeEmbedWidget::nativeEvent(const QByteArray &eventType, void *message, long *result){ - if(eventType=="xcb_generic_event_t" && WIN!=0){ - //Convert to known event type (for X11 systems) - xcb_generic_event_t *ev = static_cast(message); - //qDebug() << "Got Embed Window Event:" << xcb_event_get_label(ev->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) << xcb_event_get_request_label(ev->response_type); - uint32_t mask = 0; - switch( ev->response_type & XCB_EVENT_RESPONSE_TYPE_MASK){ - case XCB_BUTTON_PRESS: - //This is a mouse button press - mask = XCB_EVENT_MASK_BUTTON_PRESS; - break; - case XCB_BUTTON_RELEASE: - //This is a mouse button release - //qDebug() << "Button Release Event"; - mask = XCB_EVENT_MASK_BUTTON_RELEASE; - break; - case XCB_MOTION_NOTIFY: - //This is a mouse movement event - mask = XCB_EVENT_MASK_POINTER_MOTION; - break; - case XCB_ENTER_NOTIFY: - //This is a mouse movement event when mouse goes over a new window - mask = XCB_EVENT_MASK_ENTER_WINDOW; - break; - case XCB_LEAVE_NOTIFY: - //This is a mouse movement event when mouse goes leaves a window - mask = XCB_EVENT_MASK_LEAVE_WINDOW; - break; - default: - mask = 0; - } - - //Now forward this event on to the embedded window - if(mask!=0){ - qDebug() << " - Got a mouse event"; - xcb_send_event(QX11Info::connection(), true, WIN->id(),mask, (char*) ev); - return true; - } - } - return false; -}*/ diff --git a/src-qt5/core/libLumina/NativeEmbedWidget.h b/src-qt5/core/libLumina/NativeEmbedWidget.h deleted file mode 100644 index 16bb46dc..00000000 --- a/src-qt5/core/libLumina/NativeEmbedWidget.h +++ /dev/null @@ -1,74 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This is a container object for embedding a native window into a QWidget -// and maintaining a 1-to-1 mapping of sizing and other properties -// while also providing compositing effects between the two windows -//=========================================== -#ifndef _LUMINA_NATIVE_EMBED_WIDGET_H -#define _LUMINA_NATIVE_EMBED_WIDGET_H - -#include "NativeWindow.h" -#include -#include -#include -#include -#include -#include -#include - -class NativeEmbedWidget : public QWidget{ - Q_OBJECT -private: - NativeWindow *WIN; - QSize winSize; - QImage winImage; - bool paused, hasAlphaChannel; - -private slots: - //Simplification functions - void syncWinSize(QSize sz = QSize()); - void syncWidgetSize(QSize sz); - void hideWindow(); - void showWindow(); - QImage windowImage(QRect geom); - - void setWinUnpaused(); - -public: - NativeEmbedWidget(QWidget *parent); - - bool embedWindow(NativeWindow *window); - bool detachWindow(); - bool isEmbedded(); //status of the embed - bool isPaused(){ return paused; } - -public slots: - void raiseWindow(); - void lowerWindow(); - - //Pause/resume - void pause(); - void resume(); - - void resyncWindow(); - void repaintWindow(); - void reregisterEvents(); - -protected: - void resizeEvent(QResizeEvent *ev); - void showEvent(QShowEvent *ev); - void hideEvent(QHideEvent *ev); - void paintEvent(QPaintEvent *ev); - void enterEvent(QEvent *ev); - void leaveEvent(QEvent *ev); - void mouseMoveEvent(QMouseEvent *ev); - void mousePressEvent(QMouseEvent *ev); - void mouseReleaseEvent(QMouseEvent *ev); - //bool nativeEvent(const QByteArray &eventType, void *message, long *result); -}; - -#endif diff --git a/src-qt5/core/libLumina/NativeEventFilter.cpp b/src-qt5/core/libLumina/NativeEventFilter.cpp deleted file mode 100644 index c13c1fc8..00000000 --- a/src-qt5/core/libLumina/NativeEventFilter.cpp +++ /dev/null @@ -1,300 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2015-2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "NativeEventFilter.h" -#include -#include - -//#include -//#include - -//================================================== -// NOTE: All the XCB interactions and atoms are accessed via: -// obj->XCB->EWMH.(atom name) -// obj->XCB->(do something) -//================================================== - -/* -List of XCB response types (since almost impossible to find good docs on XCB) -switch (xcb_generic_event_t*->response_type & ~0x80) -case values: -XCB_KEY_[PRESS | RELEASE] -XCB_BUTTON_[PRESS | RELEASE] -XCB_MOTION_NOTIFY -XCB_ENTER_NOTIFY -XCB_LEAVE_NOTIFY -XCB_FOCUS_[IN | OUT] -XCB_KEYMAP_NOTIFY -XCB_EXPOSE -XCB_GRAPHICS_EXPOSURE -XCB_VISIBILITY_NOTIFY -XCB_CREATE_NOTIFY -XCB_DESTROY_NOTIFY -XCB_UNMAP_NOTIFY -XCB_MAP_[NOTIFY | REQUEST] -XCB_REPARENT_NOTIFY -XCB_CONFIGURE_[NOTIFY | REQUEST] -XCB_GRAVITY_NOTIFY -XCB_RESIZE_REQUEST -XCB_CIRCULATE_[NOTIFY | REQUEST] -XCB_PROPERTY_NOTIFY -XCB_SELECTION_[CLEAR | REQUEST | NOTIFY] -XCB_COLORMAP_NOTIFY -XCB_CLIENT_MESSAGE -*/ - -//SYSTEM TRAY STANDARD DEFINITIONS -#define SYSTEM_TRAY_REQUEST_DOCK 0 -#define SYSTEM_TRAY_BEGIN_MESSAGE 1 -#define SYSTEM_TRAY_CANCEL_MESSAGE 2 - -//#include -#include -#include -#include -#include - -#define DEBUG 0 - -//Special objects/variables for XCB parsing -static xcb_ewmh_connection_t EWMH; -//static LXCB *XCB = 0; -static xcb_atom_t _NET_SYSTEM_TRAY_OPCODE = 0; - -inline void ParsePropertyEvent(xcb_property_notify_event_t *ev, NativeEventFilter *obj){ - //qDebug() << "Got Property Event:" << ev->window << ev->atom; - NativeWindow::Property prop = NativeWindow::None; - //Now determine which properties are getting changed, and update the native window as appropriate - if(ev->atom == EWMH._NET_WM_NAME){ prop = NativeWindow::Title; } - else if(ev->atom == EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; } - else if(ev->atom == EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; } - else if(ev->atom == EWMH._NET_WM_DESKTOP){ prop = NativeWindow::Workspace; } - else if(ev->atom == EWMH._NET_WM_WINDOW_TYPE ){ prop = NativeWindow::WinTypes; } - else if( ev->atom == EWMH._NET_WM_STATE){ prop = NativeWindow::States; } - //Send out the signal if necessary - if(prop!=NativeWindow::None){ - //if(DEBUG){ - //qDebug() << "Detected Property Change:" << ev->window << prop; - //} - obj->emit WindowPropertyChanged(ev->window, prop); - }else{ - //Quick re-check of the simple properties (nothing like the icon or other graphics) - obj->emit WindowPropertiesChanged(ev->window, QList() << NativeWindow::Title - << NativeWindow::ShortTitle << NativeWindow::Workspace ); - //qDebug() << "Unknown Property Change:" << ev->window << ev->atom; - } -} - -inline void ParseClientMessageEvent(xcb_client_message_event_t *ev, NativeEventFilter *obj){ - NativeWindow::Property prop = NativeWindow::None; - QVariant val; - if(ev->type==EWMH._NET_WM_NAME){ prop = NativeWindow::Title; } - else if(ev->type==EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; } - else if(ev->type==EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; } - else if(ev->type==EWMH._NET_WM_DESKTOP){ - prop = NativeWindow::Workspace; - val = QVariant( (int) ev->data.data32[0] ); - }else if(ev->type==EWMH._NET_WM_WINDOW_TYPE){ prop = NativeWindow::WinTypes; } - else if(ev->type==EWMH._NET_WM_STATE){ prop = NativeWindow::States; } - - if(prop!=NativeWindow::None){ - //if(DEBUG){ - qDebug() << "Detected Property Change Request:" << ev->window << prop; //} - if(val.isNull()){ obj->emit WindowPropertyChanged(ev->window, prop); } - else{ obj->emit RequestWindowPropertyChange(ev->window, prop, val); } - } - -} - - -//Constructor for the Event Filter wrapper -NativeEventFilter::NativeEventFilter() : QObject(){ - EF = new EventFilter(this); - if(EWMH.nb_screens <=0){ - xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH); - if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){ - qDebug() << "Error with XCB atom initializations"; - } - } - if(_NET_SYSTEM_TRAY_OPCODE==0){ - //_NET_SYSTEM_TRAY_OPCODE - xcb_intern_atom_cookie_t cookie = xcb_intern_atom(QX11Info::connection(), 0, 23,"_NET_SYSTEM_TRAY_OPCODE"); - xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(QX11Info::connection(), cookie, NULL); - if(r){ - _NET_SYSTEM_TRAY_OPCODE = r->atom; - free(r); - } - } -} - -void NativeEventFilter::start(){ - if(DEBUG){ qDebug() << " - Install event filter..."; } - QCoreApplication::instance()->installNativeEventFilter(EF); - if(DEBUG){ qDebug() << " - Run request check..."; } - -} - -void NativeEventFilter::stop(){ - QCoreApplication::instance()->installNativeEventFilter(0); -} - -//============================= -// EventFilter Class -//============================= - -//Constructor for the XCB event filter -EventFilter::EventFilter(NativeEventFilter *parent) : QAbstractNativeEventFilter(){ - obj = parent; -} - -//This function format taken directly from the Qt5.3 documentation -bool EventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *){ - //qDebug() << "New Event"; - if(eventType=="xcb_generic_event_t"){ - //Convert to known event type (for X11 systems) - xcb_generic_event_t *ev = static_cast(message); - //Now parse the event and emit signals as necessary - switch( ev->response_type & ~0x80){ -//============================== -// INTERACTIVITY EVENTS -//============================== - case XCB_KEY_PRESS: - //This is a keyboard key press - //qDebug() << "Key Press Event" - obj->emit KeyPressed( ((xcb_key_press_event_t *) ev)->detail, ((xcb_key_press_event_t *) ev)->root ); - break; - case XCB_KEY_RELEASE: - //This is a keyboard key release - //qDebug() << "Key Release Event"; - obj->emit KeyReleased( ((xcb_key_release_event_t *) ev)->detail, ((xcb_key_release_event_t *) ev)->root ); - break; - case XCB_BUTTON_PRESS: - //This is a mouse button press - //qDebug() << "Button Press Event"; - obj->emit MousePressed( ((xcb_button_press_event_t *) ev)->detail, ((xcb_button_press_event_t *) ev)->root ); - break; - case XCB_BUTTON_RELEASE: - //This is a mouse button release - //qDebug() << "Button Release Event"; - obj->emit MouseReleased( ((xcb_button_release_event_t *) ev)->detail, ((xcb_button_release_event_t *) ev)->root ); - break; - case XCB_MOTION_NOTIFY: - //This is a mouse movement event - if(DEBUG){ qDebug() << "Motion Notify Event"; } - obj->emit MouseMovement(); - break; - case XCB_ENTER_NOTIFY: - //This is a mouse movement event when mouse goes over a new window - //qDebug() << "Enter Notify Event"; - obj->emit MouseEnterWindow( ((xcb_enter_notify_event_t *) ev)->root ); - break; - case XCB_LEAVE_NOTIFY: - //This is a mouse movement event when mouse goes leaves a window - //qDebug() << "Leave Notify Event"; - obj->emit MouseLeaveWindow( ((xcb_leave_notify_event_t *) ev)->root ); - break; -//============================== - case XCB_EXPOSE: - //qDebug() << "Expose Notify Event:"; - //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window; - break; -//============================== - case XCB_MAP_NOTIFY: - //qDebug() << "Window Map Event:" << ((xcb_map_notify_event_t *)ev)->window; - obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, true); - break; //This is just a notification that a window was mapped - nothing needs to change here - case XCB_MAP_REQUEST: - //qDebug() << "Window Map Request Event"; - obj->emit WindowCreated( ((xcb_map_request_event_t *) ev)->window ); - break; -//============================== - case XCB_CREATE_NOTIFY: - //qDebug() << "Window Create Event"; - break; -//============================== - case XCB_UNMAP_NOTIFY: - //qDebug() << "Window Unmap Event:" << ((xcb_unmap_notify_event_t *)ev)->window; - obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, false); - break; -//============================== - case XCB_DESTROY_NOTIFY: - //qDebug() << "Window Closed Event:" << ((xcb_destroy_notify_event_t *)ev)->window; - obj->emit WindowDestroyed( ((xcb_destroy_notify_event_t *) ev)->window ); - break; -//============================== - case XCB_FOCUS_IN: - //qDebug() << "Focus In Event:"; - break; -//============================== - case XCB_FOCUS_OUT: - //qDebug() << "Focus Out Event:"; - break; -//============================== - case XCB_PROPERTY_NOTIFY: - //qDebug() << "Property Notify Event:"; - ParsePropertyEvent((xcb_property_notify_event_t*)ev, obj); - break; -//============================== - case XCB_CLIENT_MESSAGE: - //qDebug() << "Client Message Event"; - //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window; - if( ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){ - //data32[0] is timestamp, [1] is opcode, [2] is window handle - if(SYSTEM_TRAY_REQUEST_DOCK == ((xcb_client_message_event_t*)ev)->data.data32[1]){ - obj->emit TrayWindowCreated( ((xcb_client_message_event_t*)ev)->data.data32[2] ); - //addTrayApp( ((xcb_client_message_event_t*)ev)->data.data32[2] ); - } - //Ignore the System Tray messages at the moment - }else if(((xcb_client_message_event_t*)ev)->window != QX11Info::appRootWindow()){ - ParseClientMessageEvent((xcb_client_message_event_t*)ev, obj); - } - break; -//============================== - case XCB_CONFIGURE_NOTIFY: - //qDebug() << "Configure Notify Event"; - /*obj->emit WindowPropertiesChanged( ((xcb_configure_notify_event_t*)ev)->window, - QList() << NativeWindow::GlobalPos << NativeWindow::Size, - QList() << QPoint(((xcb_configure_notify_event_t*)ev)->x, ((xcb_configure_notify_event_t*)ev)->y) << - QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );*/ - obj->emit WindowPropertyChanged( ((xcb_configure_notify_event_t*)ev)->window, NativeWindow::Size, - QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) ); - break; -//============================== - case XCB_CONFIGURE_REQUEST: - //qDebug() << "Configure Request Event"; - obj->emit RequestWindowPropertiesChange( ((xcb_configure_request_event_t*)ev)->window, - QList() << NativeWindow::GlobalPos << NativeWindow::Size, - QList() << QPoint(((xcb_configure_request_event_t*)ev)->x, ((xcb_configure_request_event_t*)ev)->y) << - QSize(((xcb_configure_request_event_t*)ev)->width, ((xcb_configure_request_event_t*)ev)->height) ); - break; -//============================== - case XCB_RESIZE_REQUEST: - //qDebug() << "Resize Request Event"; - obj->emit RequestWindowPropertyChange( ((xcb_resize_request_event_t*)ev)->window, - NativeWindow::Size, QSize(((xcb_resize_request_event_t*)ev)->width, ((xcb_resize_request_event_t*)ev)->height) ); - break; -//============================== - case XCB_SELECTION_CLEAR: - //qDebug() << "Selection Clear Event"; - break; -//============================== - case 85: //not sure what event this is - but it seems to come up very often (just hide the notice) - case 0: - case XCB_GE_GENERIC: - break; //generic event - don't do anything special - default: - //if( (ev->response_type & ~0x80)==TrayDmgID){ - obj->emit PossibleDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable ); - //checkDamageID( ((xcb_damage_notify_event_t*)ev)->drawable ); - //}else{ - //qDebug() << "Default Event:" << (ev->response_type & ~0x80); - //} -//============================== - } - } - return false; - //never stop event handling (this will not impact the X events themselves - just the internal Qt application) -} diff --git a/src-qt5/core/libLumina/NativeEventFilter.h b/src-qt5/core/libLumina/NativeEventFilter.h deleted file mode 100644 index a3be3ef1..00000000 --- a/src-qt5/core/libLumina/NativeEventFilter.h +++ /dev/null @@ -1,71 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2012-2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This class provides the XCB event handling/registrations that are needed -//=========================================== -#ifndef _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H -#define _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H - -#include -#include -#include - -#include "NativeWindow.h" - - -class NativeEventFilter : public QObject{ - Q_OBJECT -private: - QAbstractNativeEventFilter* EF; - WId WMFlag; //used to flag a running WM process - -public: - NativeEventFilter(); - ~NativeEventFilter(){} - - void start(); - void stop(); - -signals: - //Window Signals - void WindowCreated(WId); - void WindowDestroyed(WId); - void WindowPropertyChanged(WId, NativeWindow::Property); - void WindowPropertiesChanged(WId, QList); - void WindowPropertyChanged(WId, NativeWindow::Property, QVariant); - void WindowPropertiesChanged(WId, QList, QList); - void RequestWindowPropertyChange(WId, NativeWindow::Property, QVariant); - void RequestWindowPropertiesChange(WId, QList, QList); - - //System Tray Signals - void TrayWindowCreated(WId); - void TrayWindowDestroyed(WId); - - //Miscellaneos Signals - void PossibleDamageEvent(WId); - - //Input Event Signals - void KeyPressed(int, WId); - void KeyReleased(int, WId); - void MousePressed(int, WId); - void MouseReleased(int, WId); - void MouseMovement(); - void MouseEnterWindow(WId); - void MouseLeaveWindow(WId); -}; - -class EventFilter : public QAbstractNativeEventFilter{ -public: - EventFilter(NativeEventFilter *parent); - ~EventFilter(){} - - virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *); - -private: - NativeEventFilter *obj; -}; - -#endif diff --git a/src-qt5/core/libLumina/NativeKeyToQt.cpp b/src-qt5/core/libLumina/NativeKeyToQt.cpp deleted file mode 100644 index 06056be7..00000000 --- a/src-qt5/core/libLumina/NativeKeyToQt.cpp +++ /dev/null @@ -1,528 +0,0 @@ - -#include - -#include -#include - -// XCB/X11 Includes -#define XK_MISCELLANY -#define XK_XKB_KEYS -#define XK_LATIN1 -#define XK_LATIN2 -#define XK_LATIN3 -#define XK_LATIN4 -#define XK_LATIN8 -#define XK_LATIN9 -//NOTE: Look at the keysymdef.h file for additional define/characters which we may need later -#include -#include - - -//Small simplification functions -Qt::Key NativeWindowSystem::KeycodeToQt(int keycode){ - static xcb_key_symbols_t *SYM = 0; - if(SYM==0){ SYM = xcb_key_symbols_alloc(QX11Info::connection()); } - xcb_keysym_t symbol = xcb_key_symbols_get_keysym(SYM, keycode,0); - //not sure about the "column" input - we want raw keys though so ignore the "modified" key states (columns) for now - //qDebug() << "Try to convert keycode to Qt::Key:" << keycode << symbol; - //Now map this symbol to the appropriate Qt::Key enumeration - switch(symbol){ - //FUNCTION KEYS - case XK_F1: return Qt::Key_F1; - case XK_F2: return Qt::Key_F2; - case XK_F3: return Qt::Key_F3; - case XK_F4: return Qt::Key_F4; - case XK_F5: return Qt::Key_F5; - case XK_F6: return Qt::Key_F6; - case XK_F7: return Qt::Key_F7; - case XK_F8: return Qt::Key_F8; - case XK_F9: return Qt::Key_F9; - case XK_F10: return Qt::Key_F10; - case XK_F11: return Qt::Key_F11; - case XK_F12: return Qt::Key_F12; - case XK_F13: return Qt::Key_F13; - case XK_F14: return Qt::Key_F14; - case XK_F15: return Qt::Key_F15; - case XK_F16: return Qt::Key_F16; - case XK_F17: return Qt::Key_F17; - case XK_F18: return Qt::Key_F18; - case XK_F19: return Qt::Key_F19; - case XK_F20: return Qt::Key_F20; - case XK_F21: return Qt::Key_F21; - case XK_F22: return Qt::Key_F22; - case XK_F23: return Qt::Key_F23; - case XK_F24: return Qt::Key_F24; - case XK_F25: return Qt::Key_F25; - case XK_F26: return Qt::Key_F26; - case XK_F27: return Qt::Key_F27; - case XK_F28: return Qt::Key_F28; - case XK_F29: return Qt::Key_F29; - case XK_F30: return Qt::Key_F30; - case XK_F31: return Qt::Key_F31; - case XK_F32: return Qt::Key_F32; - case XK_F33: return Qt::Key_F33; - case XK_F34: return Qt::Key_F34; - case XK_F35: return Qt::Key_F35; - //Miscellaneous Keys - case XK_BackSpace: return Qt::Key_Backspace; - case XK_Delete: return Qt::Key_Delete; - //case XK_LineFeed: return Qt::Key_Backspace; - case XK_Clear: return Qt::Key_Clear; - case XK_Return: return Qt::Key_Return; - case XK_Pause: return Qt::Key_Pause; - case XK_Scroll_Lock: return Qt::Key_ScrollLock; - case XK_Sys_Req: return Qt::Key_SysReq; - case XK_Escape: return Qt::Key_Escape; - case XK_Select: return Qt::Key_Select; - case XK_Print: return Qt::Key_Print; - //case XK_Execute: return Qt::Key_Execute; - case XK_Insert: return Qt::Key_Insert; - case XK_Undo: return Qt::Key_Undo; - case XK_Redo: return Qt::Key_Redo; - case XK_Menu: return Qt::Key_Menu; - case XK_Find: return Qt::Key_Find; - case XK_Cancel: return Qt::Key_Cancel; - case XK_Help: return Qt::Key_Help; - //case XK_Break: return Qt::Key_Break; - //case XK_Mode_switch: return Qt::Key_Backspace; - //case XK_script_switch: return Qt::Key_Backspace; - case XK_Num_Lock: return Qt::Key_NumLock; - //Cursor Controls - case XK_Home: return Qt::Key_Home; - case XK_Left: return Qt::Key_Left; - case XK_Up: return Qt::Key_Up; - case XK_Right: return Qt::Key_Right; - case XK_Down: return Qt::Key_Down; - //case XK_Prior: return Qt::Key_Backspace; - case XK_Page_Up: return Qt::Key_PageUp; - case XK_Page_Down: return Qt::Key_PageDown; - //case XK_Next: return Qt::Key_Backspace; - case XK_End: return Qt::Key_End; - //case XK_Begin: return Qt::Key_Backspace; - // Keypad Functions and numbers - case XK_KP_Space: return Qt::Key_Space; - case XK_KP_Tab: return Qt::Key_Tab; - case XK_KP_Enter: return Qt::Key_Enter; - case XK_KP_F1: return Qt::Key_F1; - case XK_KP_F2: return Qt::Key_F2; - case XK_KP_F3: return Qt::Key_F3; - case XK_KP_F4: return Qt::Key_F4; - case XK_KP_Home: return Qt::Key_Home; - case XK_KP_Left: return Qt::Key_Left; - case XK_KP_Up: return Qt::Key_Up; - case XK_KP_Right: return Qt::Key_Right; - case XK_KP_Down: return Qt::Key_Down; - //case XK_KP_Prior: return Qt::Key_ - case XK_KP_Page_Up: return Qt::Key_PageUp; - //case XK_KP_Next: return Qt::Key_ - case XK_KP_Page_Down: return Qt::Key_PageDown; - case XK_KP_End: return Qt::Key_End; - //case XK_KP_Begin: return Qt::Key_ - case XK_KP_Insert: return Qt::Key_Insert; - case XK_KP_Delete: return Qt::Key_Delete; - case XK_KP_Equal: return Qt::Key_Equal; - case XK_KP_Multiply: return Qt::Key_Asterisk; - case XK_KP_Add: return Qt::Key_Plus; - case XK_KP_Separator: return Qt::Key_Comma; //X11 definitions say this is often comma - case XK_KP_Subtract: return Qt::Key_Minus; - case XK_KP_Decimal: return Qt::Key_Period; - case XK_KP_Divide: return Qt::Key_Slash; - case XK_KP_0: return Qt::Key_0; - case XK_KP_1: return Qt::Key_1; - case XK_KP_2: return Qt::Key_2; - case XK_KP_3: return Qt::Key_3; - case XK_KP_4: return Qt::Key_4; - case XK_KP_5: return Qt::Key_5; - case XK_KP_6: return Qt::Key_6; - case XK_KP_7: return Qt::Key_7; - case XK_KP_8: return Qt::Key_8; - case XK_KP_9: return Qt::Key_9; - // Modifier Keys - case XK_Shift_L: return Qt::Key_Shift; - case XK_Shift_R: return Qt::Key_Shift; - case XK_Control_L: return Qt::Key_Control; - case XK_Control_R: return Qt::Key_Control; - case XK_Caps_Lock: return Qt::Key_CapsLock; - //case XK_Shift_Lock: return Qt::Key_ShiftLock; - case XK_Meta_L: return Qt::Key_Meta; - case XK_Meta_R: return Qt::Key_Meta; - case XK_Alt_L: return Qt::Key_Alt; - case XK_Alt_R: return Qt::Key_Alt; - case XK_Super_L: return Qt::Key_Super_L; - case XK_Super_R: return Qt::Key_Super_R; - case XK_Hyper_L: return Qt::Key_Hyper_L; - case XK_Hyper_R: return Qt::Key_Hyper_R; - case XK_space: return Qt::Key_Space; - case XK_exclam: return Qt::Key_Exclam; - case XK_quotedbl: return Qt::Key_QuoteDbl; - case XK_numbersign: return Qt::Key_NumberSign; - case XK_dollar: return Qt::Key_Dollar; - case XK_percent: return Qt::Key_Percent; - case XK_ampersand: return Qt::Key_Ampersand; - case XK_apostrophe: return Qt::Key_Apostrophe; - case XK_parenleft: return Qt::Key_ParenLeft; - case XK_parenright: return Qt::Key_ParenRight; - case XK_asterisk: return Qt::Key_Asterisk; - case XK_plus: return Qt::Key_Plus; - case XK_comma: return Qt::Key_Comma; - case XK_minus: return Qt::Key_Minus; - case XK_period: return Qt::Key_Period; - case XK_slash: return Qt::Key_Slash; - case XK_0: return Qt::Key_0; - case XK_1: return Qt::Key_1; - case XK_2: return Qt::Key_2; - case XK_3: return Qt::Key_3; - case XK_4: return Qt::Key_4; - case XK_5: return Qt::Key_5; - case XK_6: return Qt::Key_6; - case XK_7: return Qt::Key_7; - case XK_8: return Qt::Key_8; - case XK_9: return Qt::Key_9; - case XK_colon: return Qt::Key_Colon; - case XK_semicolon: return Qt::Key_Semicolon; - case XK_less: return Qt::Key_Less; - case XK_equal: return Qt::Key_Equal; - case XK_greater: return Qt::Key_Greater; - case XK_question: return Qt::Key_Question; - case XK_at: return Qt::Key_At; - case XK_A: return Qt::Key_A; - case XK_B: return Qt::Key_B; - case XK_C: return Qt::Key_C; - case XK_D: return Qt::Key_D; - case XK_E: return Qt::Key_E; - case XK_F: return Qt::Key_F; - case XK_G: return Qt::Key_G; - case XK_H: return Qt::Key_H; - case XK_I: return Qt::Key_I; - case XK_J: return Qt::Key_J; - case XK_K: return Qt::Key_K; - case XK_L: return Qt::Key_L; - case XK_M: return Qt::Key_M; - case XK_N: return Qt::Key_N; - case XK_O: return Qt::Key_O; - case XK_P: return Qt::Key_P; - case XK_Q: return Qt::Key_Q; - case XK_R: return Qt::Key_R; - case XK_S: return Qt::Key_S; - case XK_T: return Qt::Key_T; - case XK_U: return Qt::Key_U; - case XK_V: return Qt::Key_V; - case XK_W: return Qt::Key_W; - case XK_X: return Qt::Key_X; - case XK_Y : return Qt::Key_Y; - case XK_Z: return Qt::Key_Z; - case XK_bracketleft: return Qt::Key_BracketLeft; - case XK_backslash: return Qt::Key_Backslash; - case XK_bracketright: return Qt::Key_BracketRight; - case XK_asciicircum: return Qt::Key_AsciiCircum; - case XK_underscore: return Qt::Key_Underscore; - case XK_grave: return Qt::Key_Agrave; - case XK_a: return Qt::Key_A; - case XK_b: return Qt::Key_B; - case XK_c: return Qt::Key_C; - case XK_d: return Qt::Key_D; - case XK_e: return Qt::Key_E; - case XK_f : return Qt::Key_F; - case XK_g: return Qt::Key_G; - case XK_h: return Qt::Key_H; - case XK_i: return Qt::Key_I; - case XK_j: return Qt::Key_J; - case XK_k: return Qt::Key_K; - case XK_l: return Qt::Key_L; - case XK_m: return Qt::Key_M; - case XK_n: return Qt::Key_N; - case XK_o: return Qt::Key_O; - case XK_p: return Qt::Key_P; - case XK_q: return Qt::Key_Q; - case XK_r: return Qt::Key_R; - case XK_s: return Qt::Key_S; - case XK_t : return Qt::Key_T; - case XK_u: return Qt::Key_U; - case XK_v: return Qt::Key_V; - case XK_w: return Qt::Key_W; - case XK_x: return Qt::Key_X; - case XK_y: return Qt::Key_Y; - case XK_z: return Qt::Key_Z; - case XK_braceleft: return Qt::Key_BraceLeft; - case XK_bar: return Qt::Key_Bar; - case XK_braceright: return Qt::Key_BraceRight; - case XK_asciitilde: return Qt::Key_AsciiTilde; - - case XK_nobreakspace: return Qt::Key_nobreakspace; - case XK_exclamdown: return Qt::Key_exclamdown; - case XK_cent: return Qt::Key_cent; - case XK_sterling: return Qt::Key_sterling; - case XK_currency: return Qt::Key_currency; - case XK_yen: return Qt::Key_yen; - case XK_brokenbar: return Qt::Key_brokenbar; - case XK_section: return Qt::Key_section; - case XK_diaeresis: return Qt::Key_diaeresis; - case XK_copyright: return Qt::Key_copyright; - case XK_ordfeminine: return Qt::Key_ordfeminine; - case XK_guillemotleft: return Qt::Key_guillemotleft; - case XK_notsign: return Qt::Key_notsign; - case XK_hyphen: return Qt::Key_hyphen; - case XK_registered: return Qt::Key_registered; - case XK_macron: return Qt::Key_macron; - case XK_degree: return Qt::Key_degree; - case XK_plusminus: return Qt::Key_plusminus; - case XK_twosuperior: return Qt::Key_twosuperior; - case XK_threesuperior: return Qt::Key_threesuperior; - case XK_acute: return Qt::Key_acute; - case XK_mu: return Qt::Key_mu; - case XK_paragraph: return Qt::Key_paragraph; - case XK_periodcentered: return Qt::Key_periodcentered; - case XK_cedilla: return Qt::Key_cedilla; - case XK_onesuperior: return Qt::Key_onesuperior; - case XK_masculine: return Qt::Key_masculine; - case XK_guillemotright: return Qt::Key_guillemotright; - case XK_onequarter: return Qt::Key_onequarter; - case XK_onehalf: return Qt::Key_onehalf; - case XK_threequarters: return Qt::Key_threequarters; - case XK_questiondown: return Qt::Key_questiondown; - case XK_Agrave: return Qt::Key_Agrave; - case XK_Aacute: return Qt::Key_Aacute; - case XK_Acircumflex: return Qt::Key_Acircumflex; - case XK_Atilde: return Qt::Key_Atilde; - case XK_Adiaeresis: return Qt::Key_Adiaeresis; - case XK_Aring: return Qt::Key_Aring; - case XK_AE: return Qt::Key_AE; - case XK_Ccedilla: return Qt::Key_Ccedilla; - case XK_Egrave: return Qt::Key_Egrave; - case XK_Eacute: return Qt::Key_Eacute; - case XK_Ecircumflex: return Qt::Key_Ecircumflex; - case XK_Ediaeresis: return Qt::Key_Ediaeresis; - case XK_Igrave: return Qt::Key_Igrave; - case XK_Iacute: return Qt::Key_Iacute; - case XK_Icircumflex: return Qt::Key_Icircumflex; - case XK_Idiaeresis: return Qt::Key_Idiaeresis; - case XK_ETH: return Qt::Key_ETH; - //case XK_Eth: return Qt::Key_Eth; - case XK_Ntilde: return Qt::Key_Ntilde; - case XK_Ograve: return Qt::Key_Ograve; - case XK_Oacute: return Qt::Key_Oacute; - case XK_Ocircumflex: return Qt::Key_Ocircumflex; - case XK_Otilde: return Qt::Key_Otilde; - case XK_Odiaeresis: return Qt::Key_Odiaeresis; - case XK_multiply: return Qt::Key_multiply; - //case XK_Oslash: return Qt::Key_AsciiTilde; - case XK_Ooblique: return Qt::Key_Ooblique; - case XK_Ugrave: return Qt::Key_Ugrave; - case XK_Uacute: return Qt::Key_Uacute; - case XK_Ucircumflex: return Qt::Key_Ucircumflex; - case XK_Udiaeresis: return Qt::Key_Udiaeresis; - case XK_Yacute: return Qt::Key_Yacute; - case XK_THORN: return Qt::Key_THORN; - //case XK_Thorn: return Qt::Key_AsciiTilde; - case XK_ssharp: return Qt::Key_ssharp; - /*case XK_agrave: return Qt::Key_AsciiTilde; - case XK_aacute: return Qt::Key_AsciiTilde; - case XK_acircumflex: return Qt::Key_AsciiTilde; - case XK_atilde: return Qt::Key_AsciiTilde; - case XK_adiaeresis: return Qt::Key_AsciiTilde; - case XK_aring: return Qt::Key_AsciiTilde; - case XK_ae: return Qt::Key_AsciiTilde; - case XK_ccedilla: return Qt::Key_AsciiTilde; - case XK_egrave: return Qt::Key_AsciiTilde; - case XK_eacute: return Qt::Key_AsciiTilde; - case XK_ecircumflex: return Qt::Key_AsciiTilde; - case XK_ediaeresis: return Qt::Key_AsciiTilde; - case XK_igrave: return Qt::Key_AsciiTilde; - case XK_iacute: return Qt::Key_AsciiTilde; - case XK_icircumflex: return Qt::Key_AsciiTilde; - case XK_idiaeresis: return Qt::Key_AsciiTilde; - case XK_eth: return Qt::Key_AsciiTilde; - case XK_ntilde: return Qt::Key_AsciiTilde; - case XK_ograve: return Qt::Key_AsciiTilde; - case XK_oacute: return Qt::Key_AsciiTilde; - case XK_ocircumflex: return Qt::Key_AsciiTilde; - case XK_otilde: return Qt::Key_AsciiTilde; - case XK_odiaeresis: return Qt::Key_AsciiTilde; - case XK_division: return Qt::Key_AsciiTilde; - case XK_oslash: return Qt::Key_AsciiTilde; - case XK_ooblique: return Qt::Key_AsciiTilde; - case XK_ugrave: return Qt::Key_AsciiTilde; - case XK_uacute: return Qt::Key_AsciiTilde; - case XK_ucircumflex: return Qt::Key_AsciiTilde; - case XK_udiaeresis: return Qt::Key_AsciiTilde; - case XK_yacute: return Qt::Key_AsciiTilde; - case XK_thorn: return Qt::Key_AsciiTilde; - case XK_ydiaeresis: return Qt::Key_AsciiTilde; - - case: XK_Agonek: return Qt::Key_AsciiTilde; - case XK_breve: return Qt::Key_AsciiTilde; - case XK_Lstroke: return Qt::Key_AsciiTilde; - case XK_Lcaron: return Qt::Key_AsciiTilde; - case XK_Sacute: return Qt::Key_AsciiTilde; - case XK_Scaron: return Qt::Key_AsciiTilde; - case XK_Scedilla: return Qt::Key_AsciiTilde; - case XK_Tcaron: return Qt::Key_AsciiTilde; - case XK_Zacute: return Qt::Key_AsciiTilde; - case XK_Zcaron: return Qt::Key_AsciiTilde; - case XK_Zabovedot: return Qt::Key_AsciiTilde; - case XK_aogonek: return Qt::Key_AsciiTilde; - case XK_ogonek: return Qt::Key_AsciiTilde; - case XK_lstroke: return Qt::Key_AsciiTilde; - case XK_lcaron: return Qt::Key_AsciiTilde; - case XK_sacute: return Qt::Key_AsciiTilde; - case XK_caron: return Qt::Key_AsciiTilde; - case XK_scaron: return Qt::Key_AsciiTilde; - case XK_scedilla: return Qt::Key_AsciiTilde; - case XK_tcaron: return Qt::Key_AsciiTilde; - case XK_zacute: return Qt::Key_AsciiTilde; - case XK_doubleacute: return Qt::Key_AsciiTilde; - case XK_zcaron: return Qt::Key_AsciiTilde; - case XK_zabovedot: return Qt::Key_AsciiTilde; - case XK_Racute: return Qt::Key_AsciiTilde; - case XK_Abreve: return Qt::Key_AsciiTilde; - case XK_Lacute: return Qt::Key_AsciiTilde; - case XK_Cacute: return Qt::Key_AsciiTilde; - case XK_Ccaron: return Qt::Key_AsciiTilde; - case XK_Eogonek: return Qt::Key_AsciiTilde; - case XK_Ecaron: return Qt::Key_AsciiTilde; - case XK_Dcaron: return Qt::Key_AsciiTilde; - case XK_Dstroke: return Qt::Key_AsciiTilde; - case XK_Nacute: return Qt::Key_AsciiTilde; - case XK_Ncaron: return Qt::Key_AsciiTilde; - case XK_Odoubleacute: return Qt::Key_AsciiTilde; - case XK_Rcaron: return Qt::Key_AsciiTilde; - case XK_Uring: return Qt::Key_AsciiTilde; - case XK_Udoubleacute: return Qt::Key_AsciiTilde; - case XK_Tcedilla: return Qt::Key_AsciiTilde; - case XK_racute: return Qt::Key_AsciiTilde; - case XK_abreve: return Qt::Key_AsciiTilde; - case XK_lacute: return Qt::Key_AsciiTilde; - case XK_cacute: return Qt::Key_AsciiTilde; - case XK_ccaron: return Qt::Key_AsciiTilde; - case XK_eogonek: return Qt::Key_AsciiTilde; - case XK_ecaron: return Qt::Key_AsciiTilde; - case XK_dcaron: return Qt::Key_AsciiTilde; - case XK_dstroke: return Qt::Key_AsciiTilde; - case XK_nacute: return Qt::Key_AsciiTilde; - case XK_ncaron: return Qt::Key_AsciiTilde; - case XK_odoubleacute: return Qt::Key_AsciiTilde; - case XK_rcaron: return Qt::Key_AsciiTilde; - case XK_uring: return Qt::Key_AsciiTilde; - case XK_udoubleacute: return Qt::Key_AsciiTilde; - case XK_tcedilla: return Qt::Key_AsciiTilde; - case XK_abovedot: return Qt::Key_AsciiTilde; - case XK_Hstroke: return Qt::Key_AsciiTilde; - case XK_Hcircumflex: return Qt::Key_AsciiTilde; - case XK_Iabovedot: return Qt::Key_AsciiTilde; - case XK_Gbreve: return Qt::Key_AsciiTilde; - case XK_Jcircumflex: return Qt::Key_AsciiTilde; - case XK_hstroke: return Qt::Key_AsciiTilde; - case XK_hcircumflex: return Qt::Key_AsciiTilde; - case XK_idotless: return Qt::Key_AsciiTilde; - case XK_gbreve: return Qt::Key_AsciiTilde; - case XK_jcircumflex: return Qt::Key_AsciiTilde; - case XK_Cabovedot: return Qt::Key_AsciiTilde; - case XK_Ccircumflex: return Qt::Key_AsciiTilde; - case XK_Gabovedot: return Qt::Key_AsciiTilde; - case XK_Gcircumflex: return Qt::Key_AsciiTilde; - case XK_Ubreve: return Qt::Key_AsciiTilde; - case XK_Scircumflex: return Qt::Key_AsciiTilde; - case XK_cabovedot: return Qt::Key_AsciiTilde; - case XK_ccircumflex: return Qt::Key_AsciiTilde; - case XK_gabovedot: return Qt::Key_AsciiTilde; - case XK_gcircumflex: return Qt::Key_AsciiTilde; - case XK_ubreve: return Qt::Key_AsciiTilde; - case XK_scircumflex: return Qt::Key_AsciiTilde; - case XK_kra: return Qt::Key_AsciiTilde; - case XK_kappa: return Qt::Key_AsciiTilde; - case XK_Rcedilla: return Qt::Key_AsciiTilde; - case XK_Itilde: return Qt::Key_AsciiTilde; - case XK_Lcedilla: return Qt::Key_AsciiTilde; - case XK_Emacron: return Qt::Key_AsciiTilde; - case XK_Gcedilla: return Qt::Key_AsciiTilde; - case XK_Tslash: return Qt::Key_AsciiTilde; - case XK_rcedilla: return Qt::Key_AsciiTilde; - case XK_itilde: return Qt::Key_AsciiTilde; - case XK_lcedilla: return Qt::Key_AsciiTilde; - case XK_emacron: return Qt::Key_AsciiTilde; - case XK_gcedilla: return Qt::Key_AsciiTilde; - case XK_tslash: return Qt::Key_AsciiTilde; - case XK_ENG: return Qt::Key_AsciiTilde; - case XK_eng: return Qt::Key_AsciiTilde; - case XK_Amacron: return Qt::Key_AsciiTilde; - case XK_Iogonek: return Qt::Key_AsciiTilde; - case XK_Eabovedot: return Qt::Key_AsciiTilde; - case XK_Imacron: return Qt::Key_AsciiTilde; - case XK_Ncedilla: return Qt::Key_AsciiTilde; - case XK_Omacron: return Qt::Key_AsciiTilde; - case XK_Kcedilla: return Qt::Key_AsciiTilde; - case XK_Uogonek: return Qt::Key_AsciiTilde; - case XK_Utilde: return Qt::Key_AsciiTilde; - case XK_Umacron: return Qt::Key_AsciiTilde; - case XK_amacron: return Qt::Key_AsciiTilde; - case XK_iogonek: return Qt::Key_AsciiTilde; - case XK_eabovedot: return Qt::Key_AsciiTilde; - case XK_imacron: return Qt::Key_AsciiTilde; - case XK_ncedilla: return Qt::Key_AsciiTilde; - case XK_omacron: return Qt::Key_AsciiTilde; - case XK_kcedilla: return Qt::Key_AsciiTilde; - case XK_uogonek: return Qt::Key_AsciiTilde; - case XK_utilde: return Qt::Key_AsciiTilde; - case XK_umacron: return Qt::Key_AsciiTilde; - case XK_Wcircumflex: return Qt::Key_AsciiTilde; - case XK_wcircumflex: return Qt::Key_AsciiTilde; - case XK_Ycircumflex: return Qt::Key_AsciiTilde; - case XK_ycircumflex: return Qt::Key_AsciiTilde; - case XK_Babovedot: return Qt::Key_AsciiTilde; - case XK_babovedot: return Qt::Key_AsciiTilde; - case XK_Dabovedot: return Qt::Key_AsciiTilde; - case XK_dabovedot: return Qt::Key_AsciiTilde; - case XK_Fabovedot: return Qt::Key_AsciiTilde; - case XK_fabovedot: return Qt::Key_AsciiTilde; - case XK_Mabovedot: return Qt::Key_AsciiTilde; - case XK_mabovedot: return Qt::Key_AsciiTilde; - case XK_Pabovedot: return Qt::Key_AsciiTilde; - case XK_pabovedot: return Qt::Key_AsciiTilde; - case XK_Sabovedot: return Qt::Key_AsciiTilde; - case XK_sabovedot: return Qt::Key_AsciiTilde; - case XK_Tabovedot: return Qt::Key_AsciiTilde; - case XK_tabovedot: return Qt::Key_AsciiTilde; - case XK_Wgrave: return Qt::Key_AsciiTilde; - case XK_wgrave: return Qt::Key_AsciiTilde; - case XK_Wacute: return Qt::Key_AsciiTilde; - case XK_wacute: return Qt::Key_AsciiTilde; - case XK_Wdiaeresis: return Qt::Key_AsciiTilde; - case XK_wdiaeresis: return Qt::Key_AsciiTilde; - case XK_Ygrave: return Qt::Key_AsciiTilde; - case XK_ygrave: return Qt::Key_AsciiTilde; - case XK_OE: return Qt::Key_AsciiTilde; - case XK_oe: return Qt::Key_AsciiTilde; - case XK_Ydiaeresis: return Qt::Key_AsciiTilde;*/ - default: - qDebug() << "Unknown Key"; - } - qDebug() << " -- Simple Qt Map:" << (Qt::Key)(symbol); - qDebug() << " -- Key Sequence Map:" << QKeySequence(symbol); - qDebug() << " - Not implemented yet"; - return Qt::Key_unknown; -} - -NativeWindowSystem::MouseButton NativeWindowSystem::MouseToQt(int keycode){ - switch(keycode){ - case 1: - return NativeWindowSystem::LeftButton; - case 3: - return NativeWindowSystem::RightButton; - case 2: - return NativeWindowSystem::MidButton; - case 4: - return NativeWindowSystem::WheelUp; - case 5: - return NativeWindowSystem::WheelDown; - case 6: - return NativeWindowSystem::WheelLeft; - case 7: - return NativeWindowSystem::WheelRight; - case 8: - return NativeWindowSystem::BackButton; //Not sure if this is correct yet (1/27/17) - case 9: - return NativeWindowSystem::ForwardButton; //Not sure if this is correct yet (1/27/17) - default: - return NativeWindowSystem::NoButton; - } -} diff --git a/src-qt5/core/libLumina/NativeWindow.cpp b/src-qt5/core/libLumina/NativeWindow.cpp deleted file mode 100644 index 02cc001e..00000000 --- a/src-qt5/core/libLumina/NativeWindow.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "NativeWindow.h" - -#include - -// === PUBLIC === -NativeWindow::NativeWindow(WId id) : QObject(){ - winid = id; - frameid = 0; - dmgID = 0; -} - -NativeWindow::~NativeWindow(){ - hash.clear(); -} - -void NativeWindow::addFrameWinID(WId fid){ - frameid = fid; -} - -void NativeWindow::addDamageID(unsigned int dmg){ - dmgID = dmg; -} - -bool NativeWindow::isRelatedTo(WId tmp){ - return (relatedTo.contains(tmp) || winid == tmp || frameid == tmp); -} - -WId NativeWindow::id(){ - return winid; -} - -WId NativeWindow::frameId(){ - return frameid; -} - -unsigned int NativeWindow::damageId(){ - return dmgID; -} - -QVariant NativeWindow::property(NativeWindow::Property prop){ - if(hash.contains(prop)){ return hash.value(prop); } - else if(prop == NativeWindow::RelatedWindows){ return QVariant::fromValue(relatedTo); } - return QVariant(); //null variant -} - -void NativeWindow::setProperty(NativeWindow::Property prop, QVariant val, bool force){ - if(prop == NativeWindow::RelatedWindows){ relatedTo = val.value< QList >(); } - else if(prop == NativeWindow::None || (!force && hash.value(prop)==val)){ return; } - else{ hash.insert(prop, val); } - emit PropertiesChanged(QList() << prop, QList() << val); -} - -void NativeWindow::setProperties(QList props, QList vals, bool force){ - for(int i=0; i=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property - if(props[i] == NativeWindow::None || (!force && (hash.value(props[i]) == vals[i])) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value - hash.insert(props[i], vals[i]); - } - emit PropertiesChanged(props, vals); -} - -void NativeWindow::requestProperty(NativeWindow::Property prop, QVariant val, bool force){ - if(prop == NativeWindow::None || prop == NativeWindow::RelatedWindows || (!force && hash.value(prop)==val) ){ return; } - emit RequestPropertiesChange(winid, QList() << prop, QList() << val); -} - -void NativeWindow::requestProperties(QList props, QList vals, bool force){ - //Verify/adjust inputs as needed - for(int i=0; i=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property - if(props[i] == NativeWindow::None || props[i] == NativeWindow::RelatedWindows || (!force && hash.value(props[i])==vals[i]) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value - /*if( (props[i] == NativeWindow::Visible || props[i] == NativeWindow::Active) && frameid !=0){ - //These particular properties needs to change the frame - not the window itself - emit RequestPropertiesChange(frameid, QList() << props[i], QList() << vals[i]); - props.removeAt(i); vals.removeAt(i); i--; - }*/ - } - emit RequestPropertiesChange(winid, props, vals); -} - -QRect NativeWindow::geometry(){ - //Calculate the "full" geometry of the window + frame (if any) - //Check that the size is between the min/max limitations - QSize size = hash.value(NativeWindow::Size).toSize(); - QSize min = hash.value(NativeWindow::MinSize).toSize(); - QSize max = hash.value(NativeWindow::MaxSize).toSize(); - if(min.isValid() && min.width() > size.width() ){ size.setWidth(min.width()); } - if(min.isValid() && min.height() > size.height()){ size.setHeight(min.height()); } - if(max.isValid() && max.width() < size.width() && max.width()>min.width()){ size.setWidth(max.width()); } - if(max.isValid() && max.height() < size.height() && max.height()>min.height()){ size.setHeight(max.height()); } - //Assemble the full geometry - QRect geom( hash.value(NativeWindow::GlobalPos).toPoint(), size ); - //Now adjust the window geom by the frame margins - QList frame = hash.value(NativeWindow::FrameExtents).value< QList >(); //Left,Right,Top,Bottom - //qDebug() << "Calculate Geometry:" << geom << frame; - if(frame.length()==4){ - geom = geom.adjusted( -frame[0], -frame[2], frame[1], frame[3] ); - } - //qDebug() << " - Total:" << geom; - return geom; -} -// ==== PUBLIC SLOTS === -void NativeWindow::toggleVisibility(){ - setProperty(NativeWindow::Visible, !property(NativeWindow::Visible).toBool() ); -} - -void NativeWindow::requestClose(){ - emit RequestClose(winid); -} - -void NativeWindow::requestKill(){ - emit RequestKill(winid); -} - -void NativeWindow::requestPing(){ - emit RequestPing(winid); -} diff --git a/src-qt5/core/libLumina/NativeWindow.h b/src-qt5/core/libLumina/NativeWindow.h deleted file mode 100644 index 67436259..00000000 --- a/src-qt5/core/libLumina/NativeWindow.h +++ /dev/null @@ -1,118 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This is a container object for setting/announcing changes -// in a native window's properties. -// The WM will usually run the "setProperty" function on this object, -// and any other classes/widgets which watch this window can act appropriatly after-the-fact -// Non-WM classes should use the "Request" signals to ask the WM to do something, and listen for changes later -//=========================================== -#ifndef _LUMINA_DESKTOP_NATIVE_WINDOW_H -#define _LUMINA_DESKTOP_NATIVE_WINDOW_H - -#include -#include -#include -#include -#include -#include -#include - -class NativeWindow : public QObject{ - Q_OBJECT -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 Property{ /*QVariant Type*/ - None=0, /*null*/ - MinSize=1, /*QSize*/ - MaxSize=2, /*QSize*/ - Size=3, /*QSize*/ - GlobalPos=4, /*QPoint*/ - Title=5, /*QString*/ - ShortTitle=6, /*QString*/ - Icon=7, /*QIcon*/ - Name=8, /*QString*/ - Workspace=9, /*int*/ - States=10, /*QList : Current state of the window */ - WinTypes=11, /*QList : Current type of window (typically does not change)*/ - WinActions=12, /*QList : Current actions that the window allows (Managed/set by the WM)*/ - FrameExtents=13, /*QList : [Left, Right, Top, Bottom] in pixels */ - RelatedWindows=14, /* QList - better to use the "isRelatedTo(WId)" function instead of reading this directly*/ - Active=15, /*bool*/ - Visible=16 /*bool*/ - }; - - static QList allProperties(){ - //Return all the available properties (excluding "None" and "FrameExtents" (WM control only) ) - QList props; - props << MinSize << MaxSize << Size << GlobalPos << Title << ShortTitle << Icon << Name << Workspace \ - << States << WinTypes << WinActions << RelatedWindows << Active << Visible; - return props; - }; - - NativeWindow(WId id); - ~NativeWindow(); - - void addFrameWinID(WId); - void addDamageID(unsigned int); - bool isRelatedTo(WId); - - WId id(); - WId frameId(); - unsigned int damageId(); - - //QWindow* window(); - - QVariant property(NativeWindow::Property); - void setProperty(NativeWindow::Property, QVariant, bool force = false); - void setProperties(QList, QList, bool force = false); - void requestProperty(NativeWindow::Property, QVariant, bool force = false); - void requestProperties(QList, QList, bool force = false); - - QRect geometry(); //this returns the "full" geometry of the window (window + frame) - -public slots: - void toggleVisibility(); - void requestClose(); //ask the app to close the window (may/not depending on activity) - void requestKill(); //ask the WM to kill the app associated with this window (harsh - only use if not responding) - void requestPing(); //ask the app if it is still active (a WindowNotResponding signal will get sent out if there is no reply); - -private: - QHash hash; - //QWindow *WIN; - WId winid, frameid; - QList relatedTo; - unsigned int dmgID; - -signals: - //General Notifications - void PropertiesChanged(QList, QList); - void RequestPropertiesChange(WId, QList, QList); - 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 NativeWindow id() - void RequestClose(WId); //Close the window - void RequestKill(WId); //Kill the window/app (usually from being unresponsive) - void RequestPing(WId); //Verify that the window is still active (such as not closing after a request - void RequestReparent(WId, WId, QPoint); //client window, frame window, relative origin point in frame - // System Tray Icon Embed/Unembed Requests - //void RequestEmbed(WId, QWidget*); - //void RequestUnEmbed(WId, QWidget*); -}; - -// Declare the enumerations as Qt MetaTypes -Q_DECLARE_METATYPE(NativeWindow::Type); -Q_DECLARE_METATYPE(NativeWindow::Action); -Q_DECLARE_METATYPE(NativeWindow::State); -Q_DECLARE_METATYPE(NativeWindow::Property); - -#endif diff --git a/src-qt5/core/libLumina/NativeWindow.pri b/src-qt5/core/libLumina/NativeWindow.pri deleted file mode 100644 index c906d6fd..00000000 --- a/src-qt5/core/libLumina/NativeWindow.pri +++ /dev/null @@ -1,18 +0,0 @@ - -# Files -QT *= x11extras -LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lxcb-keysyms -lXdamage -#QT *= -lxcb-render -lxcb-render-util - -SOURCES *= $${PWD}/NativeWindow.cpp \ - $${PWD}/NativeWindowSystem.cpp \ - $${PWD}/NativeKeyToQt.cpp \ - $${PWD}/NativeEventFilter.cpp \ - $${PWD}/NativeEmbedWidget.cpp - -HEADERS *= $${PWD}/NativeWindow.h \ - $${PWD}/NativeWindowSystem.h \ - $${PWD}/NativeEventFilter.h \ - $${PWD}/NativeEmbedWidget.h - -INCLUDEPATH *= $${PWD} diff --git a/src-qt5/core/libLumina/NativeWindowSystem.cpp b/src-qt5/core/libLumina/NativeWindowSystem.cpp deleted file mode 100644 index e8e9655a..00000000 --- a/src-qt5/core/libLumina/NativeWindowSystem.cpp +++ /dev/null @@ -1,986 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This is the XCB version of the NativeWindowSystem class, -// used for interacting with the X11 display system on BSD/Linux/Unix systems -//=========================================== -#include "NativeWindowSystem.h" - -//Additional Qt includes -#include -#include -#include -#include -#include -#include -#include - - -//XCB Library includes -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//XLib includes (XCB Damage lib does not appear to register for damage events properly) -#include - -//SYSTEM TRAY STANDARD DEFINITIONS -#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 -#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 -#define SYSTEM_TRAY_REQUEST_DOCK 0 -#define SYSTEM_TRAY_BEGIN_MESSAGE 1 -#define SYSTEM_TRAY_CANCEL_MESSAGE 2 - -#define URGENCYHINT (1L << 8) //For window urgency detection - -#define ROOT_WIN_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ - XCB_EVENT_MASK_BUTTON_PRESS | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_POINTER_MOTION | \ - XCB_EVENT_MASK_PROPERTY_CHANGE | \ - XCB_EVENT_MASK_FOCUS_CHANGE | \ - XCB_EVENT_MASK_ENTER_WINDOW) - -#define NORMAL_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ - XCB_EVENT_MASK_BUTTON_RELEASE | \ - XCB_EVENT_MASK_POINTER_MOTION | \ - XCB_EVENT_MASK_BUTTON_MOTION | \ - XCB_EVENT_MASK_EXPOSURE | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_ENTER_WINDOW | \ - XCB_EVENT_MASK_PROPERTY_CHANGE | \ - XCB_EVENT_MASK_FOCUS_CHANGE) - -#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_FOCUS_CHANGE | \ - XCB_EVENT_MASK_POINTER_MOTION) - -#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ - XCB_EVENT_MASK_BUTTON_RELEASE | \ - XCB_EVENT_MASK_POINTER_MOTION | \ - XCB_EVENT_MASK_EXPOSURE | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_ENTER_WINDOW) - -inline void registerClientEvents(WId id, bool client = true){ - uint32_t values[] = {XCB_NONE}; - values[0] = client ? CLIENT_EVENT_MASK : FRAME_EVENT_MASK ; - /*{ (XCB_EVENT_MASK_PROPERTY_CHANGE - | XCB_EVENT_MASK_BUTTON_PRESS - | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_POINTER_MOTION - | XCB_EVENT_MASK_BUTTON_MOTION - | XCB_EVENT_MASK_EXPOSURE - | XCB_EVENT_MASK_STRUCTURE_NOTIFY - | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT - | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY - | XCB_EVENT_MASK_ENTER_WINDOW) - };*/ - xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, values); -} - -/*inline void registerClientEvents(WId id){ - uint32_t value_list[1] = {NORMAL_WIN_EVENT_MASK}; - xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list); -}*/ - -//Internal XCB private objects class -class NativeWindowSystem::p_objects{ -public: - xcb_ewmh_connection_t EWMH; //This is where all the screen info and atoms are located - QHash ATOMS; - xcb_screen_t *root_screen; - xcb_window_t root_window, wm_window, tray_window; - - //Functions for setting up these objects as needed - bool init_ATOMS(){ - xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH); - if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){ - qDebug() << "Error with XCB atom initializations"; - return false; - } - - QStringList atoms; - atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS" << "_NET_WM_WINDOW_OPACITY" - << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION" << "_XEMBED" - << "_NET_SYSTEM_TRAY_VISUAL" << QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())); - //Create all the requests for the atoms - QList reply; - for(int i=0; iatom); - free(reply[i]); //done with this reply - }else{ - //Invalid atom - could not be created - qDebug() << "Could not initialize XCB atom:" << atoms[i]; - } - } //loop over reply - return (ATOMS.keys().length() == atoms.length()); - } - - WId getTransientFor(WId win){ - xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for_unchecked(QX11Info::connection(), win); - xcb_window_t trans; - if(1!= xcb_icccm_get_wm_transient_for_reply(QX11Info::connection(), cookie, &trans, NULL) ){ - return win; //error in fetching transient window ID (or none found) - }else{ - return trans; - } -} - - bool register_wm(){ - uint32_t value_list[1] = {ROOT_WIN_EVENT_MASK}; - xcb_generic_error_t *status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), root_window, XCB_CW_EVENT_MASK, value_list)); - if(status!=0){ return false; } - uint32_t params[] = {1}; - wm_window = xcb_generate_id(QX11Info::connection()); //need a new ID - xcb_create_window(QX11Info::connection(), root_screen->root_depth, \ - wm_window, root_window, -1, -1, 1, 1, 0, \ - XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \ - XCB_CW_OVERRIDE_REDIRECT, params); - if(wm_window==0){ return false; } - //Set the _NET_SUPPORTING_WM property on the root window first - xcb_ewmh_set_supporting_wm_check(&EWMH, root_window, wm_window); - //Also set this property on the child window (pointing to itself) - xcb_ewmh_set_supporting_wm_check(&EWMH, wm_window, wm_window); - //Now also setup the root event mask on the wm_window - status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), wm_window, XCB_CW_EVENT_MASK, value_list)); - if(status!=0){ return false; } - return true; - } - - bool start_system_tray(){ - xcb_atom_t _NET_SYSTEM_TRAY_S = ATOMS.value( QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())) ); - //Make sure that there is no other system tray running - xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \ - xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL); - if(ownreply == 0){ - qWarning() << " - Could not get owner selection reply"; - return false; - }else if(ownreply->owner != 0){ - free(ownreply); - qWarning() << " - An alternate system tray is currently in use"; - return false; - } - free(ownreply); - //Now create the window to use (just offscreen) - tray_window = xcb_generate_id(QX11Info::connection()); //need a new ID - uint32_t params[] = {1}; - xcb_create_window(QX11Info::connection(), root_screen->root_depth, \ - tray_window, root_screen->root, -1, -1, 1, 1, 0, \ - XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \ - XCB_CW_OVERRIDE_REDIRECT, params); - //Now register this widget as the system tray - xcb_set_selection_owner(QX11Info::connection(), tray_window, _NET_SYSTEM_TRAY_S, XCB_CURRENT_TIME); - //Make sure that it was registered properly - ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \ - xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL); - if(ownreply==0 || ownreply->owner != tray_window){ - if(ownreply!=0){ free(ownreply); } - qWarning() << " - Could not register the system tray"; - xcb_destroy_window(QX11Info::connection(), tray_window); - return false; - } - free(ownreply); //done with structure - //Now register the orientation of the system tray - uint32_t orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; - xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \ - ATOMS.value("_NET_SYSTEM_TRAY_ORIENTATION"), XCB_ATOM_CARDINAL, 32, 1, &orient); - - //Now set the visual ID for the system tray (same as the root window, but TrueColor) - xcb_visualtype_t *type = xcb_aux_find_visual_by_attrs(root_screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32); - if(type!=0){ - xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \ - ATOMS.value("_NET_SYSTEM_TRAY_VISUAL"), XCB_ATOM_VISUALID, 32, 1, &type->visual_id); - }else{ - qWarning() << " - Could not set TrueColor visual for system tray"; - } - - //Finally, send out an X event letting others know that the system tray is up and running - xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.window = root_screen->root; - event.type = EWMH.MANAGER; //MANAGER atom - event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; - event.data.data32[1] = _NET_SYSTEM_TRAY_S; //_NET_SYSTEM_TRAY_S atom - event.data.data32[2] = tray_window; - event.data.data32[3] = 0; - event.data.data32[4] = 0; - - xcb_send_event(QX11Info::connection(), 0, root_screen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); - return true; - } - -}; //end private objects class - - -//inline functions for setting up the internal objects - - -// === PUBLIC === -NativeWindowSystem::NativeWindowSystem() : QObject(){ - obj = 0; - pingTimer = 0; - screenLocked = false; -} - -NativeWindowSystem::~NativeWindowSystem(){ - xcb_ewmh_connection_wipe(&(obj->EWMH)); - free(obj); -} - -//Overarching start/stop functions -bool NativeWindowSystem::start(){ - //Initialize the XCB/EWMH objects - if(obj==0){ - obj = new p_objects(); //instantiate the private objects - obj->wm_window = 0; - obj->tray_window = 0; - xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &obj->EWMH); - if(!xcb_ewmh_init_atoms_replies(&obj->EWMH, cookie, NULL) ){ - qDebug() << "Error with XCB atom initializations"; - return false; - } - obj->root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen()); - obj->root_window = obj->root_screen->root; //simplification for later - minor duplication of memory (unsigned int) - //Initialize all the extra atoms that the EWMH object does not have - if( !obj->init_ATOMS() ){ return false; } - } //Done with private object init - bool ok = obj->register_wm(); - if(ok){ - setRoot_supportedActions(); - ok = obj->start_system_tray(); - }else{ - qWarning() << "Could not register the WM"; - } - return ok; -} - -void NativeWindowSystem::stop(){ - -} - -// === PRIVATE === -NativeWindow* NativeWindowSystem::findWindow(WId id, bool checkRelated){ - //qDebug() << "Find Window:" << id; - for(int i=0; iid() ){ return NWindows[i]; } - else if(id==NWindows[i]->frameId() ){ return NWindows[i]; } - //if(checkRelated && NWindows[i]->isRelatedTo(id)){ return NWindows[i]; } - //else if(!checkRelated && id==NWindows[i]->id()){ return NWindows[i]; } - } - //Check to see if this is a transient for some other window - if(checkRelated){ - //WId tid = obj->getTransientFor(id); - //if(tid!=id){ return findWindow(tid, checkRelated); } //call it recursively as needed - //qDebug() << " -- Could not find Window!"; - } - return 0; -} - -NativeWindow* NativeWindowSystem::findTrayWindow(WId id){ - for(int i=0; iisRelatedTo(id)){ return TWindows[i]; } - } - return 0; -} - -void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props){ - //Put the properties in logical groups as appropriate (some XCB calls return multiple properties) - if(props.contains(NativeWindow::Title)){ - //Try the EWMH standards first - // _NET_WM_NAME - QString name; - xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked(&obj->EWMH, win->id()); - if(cookie.sequence != 0){ - xcb_ewmh_get_utf8_strings_reply_t data; - if( 1 == xcb_ewmh_get_wm_name_reply(&obj->EWMH, cookie, &data, NULL) ){ - name = QString::fromUtf8(data.strings, data.strings_len); - } - } - if(name.isEmpty()){ - //_NET_WM_VISIBLE_NAME - xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_name_unchecked(&obj->EWMH, win->id()); - if(cookie.sequence != 0){ - xcb_ewmh_get_utf8_strings_reply_t data; - if( 1 == xcb_ewmh_get_wm_visible_name_reply(&obj->EWMH, cookie, &data, NULL) ){ - name = QString::fromUtf8(data.strings, data.strings_len); - } - } - } - if(name.isEmpty()){ - //Now try the ICCCM standard - xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_name_unchecked(QX11Info::connection(), win->id()); - xcb_icccm_get_text_property_reply_t reply; - if(1 == xcb_icccm_get_wm_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){ - name = QString::fromLocal8Bit(reply.name, reply.name_len); - xcb_icccm_get_text_property_reply_wipe(&reply); - } - } - win->setProperty(NativeWindow::Title, name); - } //end TITLE property - - if(props.contains(NativeWindow::ShortTitle)){ - //Try the EWMH standards first - // _NET_WM_ICON_NAME - QString name; - xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name_unchecked(&obj->EWMH, win->id()); - if(cookie.sequence != 0){ - xcb_ewmh_get_utf8_strings_reply_t data; - if( 1 == xcb_ewmh_get_wm_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){ - name = QString::fromUtf8(data.strings, data.strings_len); - } - } - if(name.isEmpty()){ - //_NET_WM_VISIBLE_ICON_NAME - xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_icon_name_unchecked(&obj->EWMH, win->id()); - if(cookie.sequence != 0){ - xcb_ewmh_get_utf8_strings_reply_t data; - if( 1 == xcb_ewmh_get_wm_visible_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){ - name = QString::fromUtf8(data.strings, data.strings_len); - } - } - } - if(name.isEmpty()){ - //Now try the ICCCM standard - xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_icon_name_unchecked(QX11Info::connection(), win->id()); - xcb_icccm_get_text_property_reply_t reply; - if(1 == xcb_icccm_get_wm_icon_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){ - name = QString::fromLocal8Bit(reply.name, reply.name_len); - xcb_icccm_get_text_property_reply_wipe(&reply); - } - } - win->setProperty(NativeWindow::ShortTitle, name); - } //end SHORTTITLE property - - if(props.contains(NativeWindow::Icon)){ - //See if this is a tray icon first (different routine - entire app window is the icon) - QIcon icon; - if(win == findTrayWindow(win->id())){ - //Tray Icon Window - QPixmap pix; - //Get the current QScreen (for XCB->Qt conversion) - QList scrnlist = QApplication::screens(); - //Try to grab the given window directly with Qt - for(int i=0; igrabWindow(win->id()); - } - icon.addPixmap(pix); - }else{ - //Standard window - //Fetch the _NET_WM_ICON for the window and return it as a QIcon - xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_unchecked(&obj->EWMH, win->id()); - xcb_ewmh_get_wm_icon_reply_t reply; - if(1 == xcb_ewmh_get_wm_icon_reply(&obj->EWMH, cookie, &reply, NULL)){ - xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply); - //Just use the first - bool done =false; - while(!done){ - //Now convert the current data into a Qt image - // - first 2 elements are width and height (removed via XCB functions) - // - data in rows from left to right and top to bottom - QImage image(iter.width, iter.height, QImage::Format_ARGB32); //initial setup - uint* dat = iter.data; - //dat+=2; //remember the first 2 element offset - for(int i=0; isetProperty(NativeWindow::Icon, icon); - } //end ICON property - - if(props.contains(NativeWindow::MinSize) || props.contains(NativeWindow::MaxSize) - || props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){ - //Try the ICCCM "Normal Hints" structure first (newer spec?) - xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_normal_hints_unchecked(QX11Info::connection(), win->id()); - xcb_size_hints_t reply; - bool ok = false; - if(1==xcb_icccm_get_wm_normal_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; } - else{ - //Could not find normal hints, try the older "size hints" instead - cookie = xcb_icccm_get_wm_size_hints_unchecked(QX11Info::connection(), win->id(), XCB_ATOM_WM_SIZE_HINTS); - if(1==xcb_icccm_get_wm_size_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; } - } - if(ok){ - bool initsize = win->property(NativeWindow::Size).isNull(); //initial window size - if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_POSITION)==XCB_ICCCM_SIZE_HINT_US_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); } - if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_SIZE)==XCB_ICCCM_SIZE_HINT_US_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); } - if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_POSITION)==XCB_ICCCM_SIZE_HINT_P_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); } - if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_SIZE)==XCB_ICCCM_SIZE_HINT_P_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); } - if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)==XCB_ICCCM_SIZE_HINT_P_MIN_SIZE ){ win->setProperty(NativeWindow::MinSize, QSize(reply.min_width, reply.min_height)); } - if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)==XCB_ICCCM_SIZE_HINT_P_MAX_SIZE ){ win->setProperty(NativeWindow::MaxSize, QSize(reply.max_width, reply.max_height)); } - if( (reply.flags&XCB_ICCCM_SIZE_HINT_BASE_SIZE)==XCB_ICCCM_SIZE_HINT_BASE_SIZE && initsize ){ win->setProperty(NativeWindow::Size, QSize(reply.base_width, reply.base_height)); } - //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)==XCB_ICCCM_SIZE_HINT_P_RESIZE_INC ){ hints.width_inc=reply.width_inc; hints.height_inc=reply.height_inc; } - //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_ASPECT)==XCB_ICCCM_SIZE_HINT_P_ASPECT ){ hints.min_aspect_num=reply.min_aspect_num; hints.min_aspect_den=reply.min_aspect_den; hints.max_aspect_num=reply.max_aspect_num; hints.max_aspect_den=reply.max_aspect_den;} - //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)==XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY ){ hints.win_gravity=reply.win_gravity; } - } - } //end of geometry properties - - if(props.contains(NativeWindow::Name)){ - //Put the app/class name here (much more static than the "Title" properties - xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class_unchecked(QX11Info::connection(), win->id()); - xcb_icccm_get_wm_class_reply_t reply; - if(1 == xcb_icccm_get_wm_class_reply(QX11Info::connection(), cookie, &reply, NULL) ){ - //Returns: "::::" - win->setProperty(NativeWindow::Name, ( QString::fromLocal8Bit(reply.instance_name)+"::::"+QString::fromLocal8Bit(reply.class_name) )); - xcb_icccm_get_wm_class_reply_wipe(&reply); - } - } //end NAME property - - if(props.contains(NativeWindow::Workspace)){ - xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop_unchecked(&obj->EWMH, win->id()); - uint32_t num = 0; - int wkspace = -1; - if(1==xcb_ewmh_get_wm_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){ - if(num!=0xFFFFFFFF){ wkspace = num; } - }/*else{ - //Error in fetching property (not set?) - // - put it on the current screen - out = WM_Get_Current_Desktop(); - }*/ - win->setProperty(NativeWindow::Workspace, wkspace); - } - if(props.contains(NativeWindow::FrameExtents)){ - //Just assign default values to this - need to automate it later - //win->setProperty(NativeWindow::FrameExtents, QVariant::fromValue >(QList() << 5 << 5 << 5+QFontMetrics(QFont()).height() << 5) ); - } - if(props.contains(NativeWindow::RelatedWindows)){ - WId orig = win->id(); - WId tid = obj->getTransientFor(orig); - QList list; - while(tid != orig){ - list << tid; - orig = tid; - tid = obj->getTransientFor(orig); - } - win->setProperty(NativeWindow::RelatedWindows, QVariant::fromValue(list)); - } - if(props.contains(NativeWindow::Visible)){ - xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), xcb_get_window_attributes(QX11Info::connection(), win->id()) , NULL); - if(attr != 0){ - win->setProperty(NativeWindow::Visible, attr->map_state == XCB_MAP_STATE_VIEWABLE); - free(attr); - } - } - if(props.contains(NativeWindow::WinTypes)){ - QList< NativeWindow::Type> types; - xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type_unchecked(&obj->EWMH, win->id()); - xcb_ewmh_get_atoms_reply_t reply; - if(1==xcb_ewmh_get_wm_window_type_reply(&obj->EWMH, cookie, &reply, NULL) ){ - for(unsigned int i=0; iEWMH._NET_WM_WINDOW_TYPE_DESKTOP){ types << NativeWindow::T_DESKTOP; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DOCK){ types << NativeWindow::T_DOCK; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR){ types << NativeWindow::T_TOOLBAR; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_MENU){ types << NativeWindow::T_MENU; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY){ types << NativeWindow::T_UTILITY; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH){ types << NativeWindow::T_SPLASH; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG){ types << NativeWindow::T_DIALOG; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU){ types << NativeWindow::T_DROPDOWN_MENU; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU){ types << NativeWindow::T_POPUP_MENU; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP){ types << NativeWindow::T_TOOLTIP; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION){ types << NativeWindow::T_NOTIFICATION; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_COMBO){ types << NativeWindow::T_COMBO; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DND){ types << NativeWindow::T_DND; } - else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL){ types << NativeWindow::T_NORMAL; } - } - } - if(types.isEmpty()){ types << NativeWindow::T_NORMAL; } - win->setProperty(NativeWindow::WinTypes, QVariant::fromValue< QList >(types) ); - } -} - -void NativeWindowSystem::ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList vals){ - if(props.length() == 0 || vals.length()!=props.length() || win ==0 ){ return; } - //qDebug() << "Change Window Properties:" << props << vals; - if(props.contains(NativeWindow::Title)){ - - } - if(props.contains(NativeWindow::ShortTitle)){ - - } - if(props.contains(NativeWindow::Icon)){ - - } - if(props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){ - /*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(NativeWindow::Size).toSize(); - if(props.contains(NativeWindow::Size)){ - sz = vals[ props.indexOf(NativeWindow::Size) ] .toSize(); - } - valList.width = sz.width(); - valList.height = sz.height(); - if(props.contains(NativeWindow::GlobalPos)){ - QPoint pt = vals[ props.indexOf(NativeWindow::GlobalPos) ] .toPoint(); - valList.x = pt.x(); - valList.y = pt.y(); - }else{ - valList.x = win->property(NativeWindow::GlobalPos).toPoint().x(); - valList.y = win->property(NativeWindow::GlobalPos).toPoint().y(); - } - 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);*/ - } - if(props.contains(NativeWindow::Name)){ - - } - if(props.contains(NativeWindow::Workspace)){ - int num = vals[ props.indexOf(NativeWindow::Workspace) ].toInt(); - xcb_ewmh_set_wm_desktop(&obj->EWMH, win->id(), (num<0 ? 0xFFFFFFFF : qAbs(num) ) ); - } - if(props.contains(NativeWindow::RelatedWindows)){ - - } - if(props.contains(NativeWindow::Visible)){ - //qDebug() << "Check Window Visibility:" << vals[ props.indexOf(NativeWindow::Visible) ]; - if( vals[ props.indexOf(NativeWindow::Visible) ].toBool() ){ - //qDebug() << " - Map it!"; - xcb_map_window(QX11Info::connection(), win->id()); - }else{ - //qDebug() << " - Unmap it!"; - xcb_unmap_window(QX11Info::connection(), win->id()); - } - } - if(props.contains(NativeWindow::Active)){ - //Only one window can be "Active" at a time - so only do anything if this window wants to be active - if(vals[props.indexOf(NativeWindow::Active)].toBool() ){ - //Lower the currently active window (invisible window) to the bottom of the stack - xcb_window_t cactive; - if( 1 == xcb_ewmh_get_active_window_reply( &obj->EWMH, - xcb_ewmh_get_active_window_unchecked(&obj->EWMH, QX11Info::appScreen()), - &cactive, NULL) ){ - uint32_t val = XCB_STACK_MODE_BELOW; - xcb_configure_window(QX11Info::connection(), cactive, XCB_CONFIG_WINDOW_STACK_MODE, &val); - } - - xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win->id() ); - //Also send the active window a message to take input focus - xcb_set_input_focus(QX11Info::connection(), XCB_INPUT_FOCUS_PARENT, win->id(), XCB_CURRENT_TIME); - //Send the window a WM_TAKE_FOCUS message -/* xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.window = win->id(); - event.type = obj->ATOMS["WM_PROTOCOLS"]; - event.data.data32[0] = obj->ATOMS["WM_TAKE_FOCUS"]; - event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime; - event.data.data32[2] = 0; - event.data.data32[3] = 0; - event.data.data32[4] = 0; - - xcb_send_event(QX11Info::connection(), 0, win->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); - xcb_flush(QX11Info::connection()); -*/ - } - } - -} - -// === PUBLIC SLOTS === -//These are the slots which are typically only used by the desktop system itself or the NativeEventFilter -void NativeWindowSystem::RegisterVirtualRoot(WId id){ - //Convert to XCB array - xcb_window_t array[1]; - array[0] = id; - //Set the property - xcb_ewmh_set_virtual_roots(&obj->EWMH, QX11Info::appScreen(), 1, array); - //Now also enable automatic compositing for children of this window - //xcb_composite_redirect_window(QX11Info::connection(), id, XCB_COMPOSITE_REDIRECT_AUTOMATIC); - //xcb_composite_redirect_subwindows(QX11Info::connection(), id, XCB_COMPOSITE_REDIRECT_AUTOMATIC); -} - -void NativeWindowSystem::setRoot_supportedActions(){ -//NET_WM standards (ICCCM implied - no standard way to list those) - xcb_atom_t list[] = {obj->EWMH._NET_WM_NAME, - obj->EWMH._NET_WM_ICON, - obj->EWMH._NET_WM_ICON_NAME, - obj->EWMH._NET_WM_DESKTOP, - /*obj->ATOMS["_NET_WM_WINDOW_OPACITY"],*/ - /*_NET_WINDOW_TYPE (and all the various types - 15 in total*/ - obj->EWMH._NET_WM_WINDOW_TYPE, obj->EWMH._NET_WM_WINDOW_TYPE_DESKTOP, obj->EWMH._NET_WM_WINDOW_TYPE_DOCK, - obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR, obj->EWMH._NET_WM_WINDOW_TYPE_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY, - obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH, obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG, obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL, - obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP, - obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION, obj->EWMH._NET_WM_WINDOW_TYPE_COMBO, obj->EWMH._NET_WM_WINDOW_TYPE_DND, - }; - xcb_ewmh_set_supported(&obj->EWMH, QX11Info::appScreen(), 20,list); -} - -void NativeWindowSystem::setRoot_numberOfWorkspaces(QStringList names){ - if(names.isEmpty()){ names << "one"; } - //First set the overall number of workspaces - xcb_ewmh_set_number_of_desktops(&obj->EWMH, QX11Info::appScreen(), names.length()); - //Now set the names for the workspaces - //EWMH LIBRARY BROKEN - appears to be a mismatch in the function header (looking for a single char array, instead of a list of char arrays) - // Ken Moore - 6/27/17 - /* - char *array[ names.length() ]; - for(int i=0; iEWMH, QX11Info::appScreen(), names.length(), array); - */ -} - -void NativeWindowSystem::setRoot_currentWorkspace(int num){ - xcb_ewmh_set_current_desktop(&obj->EWMH, QX11Info::appScreen(), num); -} - -void NativeWindowSystem::setRoot_clientList(QList list, bool stackorder){ - //convert the QList into a generic array - xcb_window_t array[list.length()]; - for(int i=0; iEWMH, QX11Info::appScreen(), list.length(), array); - }else{ - xcb_ewmh_set_client_list(&obj->EWMH, QX11Info::appScreen(), list.length(), array); - } -} - -void NativeWindowSystem::setRoot_desktopGeometry(QRect geom){ - //This one is a combo function - // This will set the "DESKTOP_VIEWPORT" property (point) - // as well as the "DESKTOP_GEOMETRY" property (size) - //Turn the QList into xcb_ewmh_coordinates_t* - xcb_ewmh_coordinates_t array[1]; - array[0].x=geom.x(); array[0].y=geom.y(); - //Now set the property - xcb_ewmh_set_desktop_viewport(&obj->EWMH, QX11Info::appScreen(), 1, array); - xcb_ewmh_set_desktop_geometry(&obj->EWMH, QX11Info::appScreen(), geom.width(), geom.height()); -} - -void NativeWindowSystem::setRoot_desktopWorkarea(QList list){ - //Convert to the XCB/EWMH data structures - xcb_ewmh_geometry_t array[list.length()]; - for(int i=0; iEWMH, QX11Info::appScreen(), list.length(), array); -} - -void NativeWindowSystem::setRoot_activeWindow(WId win){ - /*xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win); - //Also send the active window a message to take input focus - //Send the window a WM_TAKE_FOCUS message - xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.window = win; - event.type = obj->ATOMS["WM_PROTOCOLS"]; - event.data.data32[0] = obj->ATOMS["WM_TAKE_FOCUS"]; - event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime; - event.data.data32[2] = 0; - event.data.data32[3] = 0; - event.data.data32[4] = 0; - - xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); - xcb_flush(QX11Info::connection());*/ -} - -int NativeWindowSystem::currentWorkspace(){ - xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop_unchecked(&obj->EWMH, QX11Info::appScreen()); - uint32_t num = 0; - if(1==xcb_ewmh_get_current_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){ - return num; - }else{ - return 0; - } -} - -//NativeWindowEventFilter interactions -void NativeWindowSystem::NewWindowDetected(WId id){ - //Make sure this can be managed first - if(findWindow(id, false) != 0){ findWindow(id,false)->setProperty(NativeWindow::Visible, true, true); return; } //already managed - xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id); - xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL); - if(attr == 0){ return; } //could not get attributes of window - if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage) - free(attr); - //Now go ahead and create/populate the container for this window - NativeWindow *win = new NativeWindow(id); - //Register for events from this window - registerClientEvents(win->id()); - NWindows << win; - UpdateWindowProperties(win, NativeWindow::allProperties()); - qDebug() << "New Window [& associated ID's]:" << win->id() << win->property(NativeWindow::Name).toString(); - //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, QList)), this, SLOT(RequestPropertiesChange(WId, QList, QList)) ); - emit NewWindowAvailable(win); -} - -void NativeWindowSystem::NewTrayWindowDetected(WId id){ - //Make sure this can be managed first - if(findTrayWindow(id) != 0){ return; } //already managed - xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id); - xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL); - if(attr == 0){ return; } //could not get attributes of window - if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage) - free(attr); - //Register for events from this window - #define TRAY_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ - XCB_EVENT_MASK_BUTTON_RELEASE | \ - XCB_EVENT_MASK_POINTER_MOTION | \ - XCB_EVENT_MASK_BUTTON_MOTION | \ - XCB_EVENT_MASK_EXPOSURE | \ - XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ - XCB_EVENT_MASK_ENTER_WINDOW) - - uint32_t value_list[1] = {TRAY_WIN_EVENT_MASK}; - xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list); - //Now go ahead and create/populate the container for this window - NativeWindow *win = new NativeWindow(id); - TWindows << win; - UpdateWindowProperties(win, NativeWindow::allProperties()); - emit NewTrayWindowAvailable(win); -} - -void NativeWindowSystem::WindowCloseDetected(WId id){ - NativeWindow *win = findWindow(id, false); - //qDebug() << "Got Window Closed" << id << win; - //qDebug() << "Old Window List:" << NWindows.length(); - if(win!=0){ - NWindows.removeAll(win); - //RequestReparent(id, QX11Info::appRootWindow(), QPoint(0,0)); - win->emit WindowClosed(id); - //qDebug() << "Visible Window Closed!!!"; - //win->deleteLater(); - }else{ - win = findTrayWindow(id); - if(win!=0){ - TWindows.removeAll(win); - win->emit WindowClosed(id); - win->deleteLater(); - } - } - //qDebug() << " - Now:" << NWindows.length(); -} - -void NativeWindowSystem::WindowPropertyChanged(WId id, NativeWindow::Property prop){ - //NOTE: This is triggered by the NativeEventFilter - not by changes to the NativeWindow objects themselves - NativeWindow *win = findWindow(id, prop!=NativeWindow::Visible); - if(win==0){ win = findTrayWindow(id); } - if(win!=0){ - UpdateWindowProperties(win, QList() << prop); - }else if(prop != 0){ - //Could not find the window for a specific property with an undefined value - // - update this property for all the windows just in case - for(int i=0; i() << prop); - } - } -} - -void NativeWindowSystem::WindowPropertiesChanged(WId id, QList props){ - //NOTE: This is triggered by the NativeEventFilter - not by changes to the NativeWindow objects themselves - NativeWindow *win = findWindow(id); - if(win==0){ win = findTrayWindow(id); } - if(win!=0){ - UpdateWindowProperties(win, props); - }else{ - //Could not find the window for a specific property with an undefined value - // - update this property for all the windows just in case - for(int i=0; isetProperty(prop, val); - } -} - -void NativeWindowSystem::WindowPropertiesChanged(WId id, QList props, QList vals){ - NativeWindow *win = findWindow(id); - if(win==0){ win = findTrayWindow(id); } - if(win!=0){ - for(int i=0; isetProperty(props[i], vals[i]); } - } -} - -void NativeWindowSystem::RequestPropertyChange(WId id, NativeWindow::Property prop, QVariant val){ - //This is just a simplified version of the multiple-property function - RequestPropertiesChange(id, QList() << prop, QList() << val); -} - -void NativeWindowSystem::RequestPropertiesChange(WId win, QList props, QList vals){ - //Find the window object associated with this id - bool istraywin = false; //just in case we care later if it is a tray window or a regular window - NativeWindow *WIN = findWindow(win); - if(WIN==0){ istraywin = true; WIN = findTrayWindow(win); } - if(WIN==0){ return; } //invalid window ID - no longer available - //Now make any changes as needed - ChangeWindowProperties(WIN, props, vals); -} - -void NativeWindowSystem::GotPong(WId id){ - if(waitingForPong.contains(id)){ - waitingForPong.remove(id); - } - if(waitingForPong.isEmpty() && pingTimer!=0){ pingTimer->stop(); } -} - -void NativeWindowSystem::NewKeyPress(int keycode, WId win){ - emit NewInputEvent(); - if(screenLocked){ return; } - Qt::Key key = KeycodeToQt(keycode); - if(key!=Qt::Key_unknown){ emit KeyPressDetected(win, key); } -} - -void NativeWindowSystem::NewKeyRelease(int keycode, WId win){ - emit NewInputEvent(); - if(screenLocked){ return; } - Qt::Key key = KeycodeToQt(keycode); - if(key!=Qt::Key_unknown){ emit KeyReleaseDetected(win, key); } -} - -void NativeWindowSystem::NewMousePress(int buttoncode, WId win){ - emit NewInputEvent(); - if(screenLocked){ return; } - emit MousePressDetected(win, MouseToQt(buttoncode)); -} - -void NativeWindowSystem::NewMouseRelease(int buttoncode, WId win){ - emit NewInputEvent(); - if(screenLocked){ return; } - emit MouseReleaseDetected(win, MouseToQt(buttoncode)); -} - -void NativeWindowSystem::CheckDamageID(WId win){ - for(int i=0; idamageId() == win || NWindows[i]->id() == win || NWindows[i]->frameId()==win){ - NWindows[i]->emit VisualChanged(); - //qDebug() << "Got DAMAGE Event"; - return; - } - } - NativeWindow *WIN = findTrayWindow(win); - if(WIN!=0){ - UpdateWindowProperties(WIN, QList() << NativeWindow::Icon); - } -} - -// === PRIVATE SLOTS === -//These are the slots which are built-in and automatically connected when a new NativeWindow is created - -void NativeWindowSystem::RequestClose(WId win){ - //Send the window a WM_DELETE_WINDOW message - xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.window = win; - event.type = obj->ATOMS.value("WM_PROTOCOLS"); - event.data.data32[0] = obj->ATOMS.value("WM_DELETE_WINDOW"); - event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime; - event.data.data32[2] = 0; - event.data.data32[3] = 0; - event.data.data32[4] = 0; - - xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); - xcb_flush(QX11Info::connection()); -} - -void NativeWindowSystem::RequestKill(WId win){ - xcb_kill_client(QX11Info::connection(), win); -} - -void NativeWindowSystem::RequestPing(WId win){ - waitingForPong.insert(win, QDateTime::currentDateTime().addSecs(5) ); - xcb_ewmh_send_wm_ping(&obj->EWMH, win, XCB_CURRENT_TIME); - if(pingTimer==0){ - pingTimer = new QTimer(this); - pingTimer->setInterval(2000); //2seconds - connect(pingTimer, SIGNAL(timeout()), this, SLOT(checkPings()) ); - } - pingTimer->start(); -} - -void NativeWindowSystem::RequestReparent(WId win, WId container, QPoint relorigin){ - NativeWindow *WIN = findWindow(win); - if(WIN==0){ return; } //could not find corresponding window structure -//Reparent the window into the container - xcb_reparent_window(QX11Info::connection(), win, container, relorigin.x(), relorigin.y()); - //xcb_map_window(QX11Info::connection(), win); - - //Now send the embed event to the app - //qDebug() << " - send _XEMBED event"; - xcb_client_message_event_t event; - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.window = win; - event.type = obj->ATOMS["_XEMBED"]; //_XEMBED - event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; - event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY - event.data.data32[2] = 0; - event.data.data32[3] = container; //WID of the container - event.data.data32[4] = 0; - - xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); - - //Now setup any redirects and return - //this->SelectInput(win, true); //Notify of structure changes - registerClientEvents(win); - //xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); - - //Now map the window (will be a transparent child of the container) - xcb_map_window(QX11Info::connection(), win); - xcb_map_window(QX11Info::connection(), container); - //Now create/register the damage handler - // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore) - // -- Retested 6/29/17 (no change) Ken Moore - //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer - //xcb_damage_create(QX11Info::connection(), dmgID, win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); - // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself). - Damage dmgID = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles); - WIN->addDamageID( (uint) dmgID); //save this for later - //qDebug() << " - Done"; - //return ( (uint) dmgID ); -} -/* - xcb_reparent_window(QX11Info::connection(), client, parent, relorigin.x(), relorigin.y()); - - //Now ensure that we still get event for these windows - registerClientEvents(client); //make sure we re-do this after reparenting - registerClientEvents(parent); - xcb_map_window(QX11Info::connection(), parent); -}*/ diff --git a/src-qt5/core/libLumina/NativeWindowSystem.h b/src-qt5/core/libLumina/NativeWindowSystem.h deleted file mode 100644 index b67ecc94..00000000 --- a/src-qt5/core/libLumina/NativeWindowSystem.h +++ /dev/null @@ -1,139 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This is a Qt5/Lumina wrapper around native graphics system calls -// It is primarily designed around the creation/modification of instances of -// the "NativeWindow" class for passing information around -//=========================================== -#ifndef _LUMINA_NATIVE_WINDOW_SYSTEM_H -#define _LUMINA_NATIVE_WINDOW_SYSTEM_H - -#include "NativeWindow.h" -#include -#include -#include - -class NativeWindowSystem : public QObject{ - Q_OBJECT -private: - QList NWindows; - QList TWindows; - - //Simplifications to find an already-created window object - NativeWindow* findWindow(WId id, bool checkRelated = true); - - NativeWindow* 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; - p_objects* obj; - - //Internal timers/variables for managing pings - QTimer *pingTimer; - QHash waitingForPong; - void checkPings(){ - QDateTime cur = QDateTime::currentDateTime(); - QList waiting = waitingForPong.keys(); - for(int i=0; istop(); } - NativeWindow *win = findWindow(waiting[i]); - if(win==0){ win = findTrayWindow(waiting[i]); } - if(win!=0){ win->emit WindowNotResponding(waiting[i]); } - } - } - } - - // 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(NativeWindow* win, QList< NativeWindow::Property > props); - void ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList vals); - - //Generic private variables - bool screenLocked; - -public: - //enum Property{ None, CurrentWorkspace, Workspaces, VirtualRoots, WorkAreas }; - enum MouseButton{NoButton, LeftButton, RightButton, MidButton, BackButton, ForwardButton, TaskButton, WheelUp, WheelDown, WheelLeft, WheelRight}; - - NativeWindowSystem(); - ~NativeWindowSystem(); - - //Overarching start/stop functions - bool start(); - void stop(); - - //General-purpose listing functions - QList currentWindows(){ return NWindows; } - QList currentTrayWindows(){ return TWindows; } - - //Small simplification functions - static Qt::Key KeycodeToQt(int keycode); - static NativeWindowSystem::MouseButton MouseToQt(int button); - -public slots: - //These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter - - //This is called by the lock screen to keep the NWS aware of the current status - // it is **NOT** the function to call for the user to actually lock the session (that is in the screensaver/lockscreen class) - void ScreenLockChanged(bool lock){ - screenLocked = lock; - } - - //Root Window property registrations - void RegisterVirtualRoot(WId); - void setRoot_supportedActions(); - void setRoot_numberOfWorkspaces(QStringList names); - void setRoot_currentWorkspace(int); - void setRoot_clientList(QList, bool stackorder = false); - void setRoot_desktopGeometry(QRect); - void setRoot_desktopWorkarea(QList); - void setRoot_activeWindow(WId); - - // - Workspaces - int currentWorkspace(); - //void GoToWorkspace(int); - - - //NativeWindowEventFilter interactions - void NewWindowDetected(WId); //will automatically create the new NativeWindow object - void NewTrayWindowDetected(WId); //will automatically create the new NativeWindow object - void WindowCloseDetected(WId); //will update the lists and make changes if needed - void WindowPropertyChanged(WId, NativeWindow::Property); //will rescan the window and update the object as needed - void WindowPropertiesChanged(WId, QList); - void WindowPropertyChanged(WId, NativeWindow::Property, QVariant); //will save that property/value to the right object - void WindowPropertiesChanged(WId, QList, QList); - void RequestPropertyChange(WId, NativeWindow::Property, QVariant); - void RequestPropertiesChange(WId, QList, QList); - void GotPong(WId); - - void NewKeyPress(int keycode, WId win = 0); - void NewKeyRelease(int keycode, WId win = 0); - void NewMousePress(int buttoncode, WId win = 0); - void NewMouseRelease(int buttoncode, WId win = 0); - void CheckDamageID(WId); - -private slots: - //These are the slots which are built-in and automatically connected when a new NativeWindow is created - void RequestClose(WId); - void RequestKill(WId); - void RequestPing(WId); - void RequestReparent(WId, WId, QPoint); //client, parent, relative origin point in parent - -signals: - void NewWindowAvailable(NativeWindow*); - void NewTrayWindowAvailable(NativeWindow*); - void NewInputEvent(); //a mouse or keypress was detected (lock-state independent); - void KeyPressDetected(WId, Qt::Key); //only emitted if lockstate = false - void KeyReleaseDetected(WId, Qt::Key); //only emitted if lockstate = false - void MousePressDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false - void MouseReleaseDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false - -}; - -#endif diff --git a/src-qt5/core/libLumina/RootSubWindow-animations.cpp b/src-qt5/core/libLumina/RootSubWindow-animations.cpp deleted file mode 100644 index efab20fe..00000000 --- a/src-qt5/core/libLumina/RootSubWindow-animations.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//=========================================== -// Lumina Desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "RootSubWindow.h" -#include - -QStringList RootSubWindow::validAnimations(NativeWindow::Property prop){ - QStringList valid; - if(prop == NativeWindow::Visible){ - valid << "zoom" << "wipe-center-vertical" << "wipe-center-horizontal" << "shade-top" << "shade-right" << "shade-left" << "shade-bottom"; - }else if(prop == NativeWindow::Size){ - //Note: this is used for pretty much all geometry changes to the window where it is visible both before/after animation - valid << "direct"; - } - return valid; -} - -void RootSubWindow::loadAnimation(QString name, NativeWindow::Property prop, QVariant nval){ - if(anim->state()==QAbstractAnimation::Running){ return; } //already running - animResetProp.clear(); - //Special case - random animation each time - if(name=="random"){ - QStringList valid = validAnimations(prop); - if(!valid.isEmpty()){ name = valid.at(qrand()%valid.length()); } - } - //Now setup the animation - if(prop == NativeWindow::Visible){ - //NOTE: Assigns values for "invisible->visible" animation: will reverse it afterwards as needed - anim->setPropertyName("geometry"); - QRect geom = this->geometry(); - if(name == "zoom"){ - //Zoom to/from the center point - anim->setStartValue( QRect(geom.center(), QSize(0,0)) ); - anim->setEndValue(geom); - }else if(name == "wipe-center-vertical"){ - anim->setStartValue( QRect( geom.center().x(), geom.y(), 0, geom.height()) ); - anim->setEndValue( geom ); - }else if(name == "wipe-center-horizontal"){ - anim->setStartValue( QRect( geom.x(), geom.center().y(), geom.width(), 0) ); - anim->setEndValue( geom ); - }else if(name == "shade-top"){ - anim->setStartValue( QRect( geom.x(), geom.y(), geom.width(), 0) ); - anim->setEndValue( geom ); - }else if(name == "shade-bottom"){ - anim->setStartValue( QRect( geom.x(), geom.y()+geom.height(), geom.width(), 0) ); - anim->setEndValue( geom ); - }else if(name == "shade-left"){ - anim->setStartValue( QRect( geom.x(), geom.y(), 0, geom.height()) ); - anim->setEndValue( geom ); - }else if(name == "shade-right"){ - anim->setStartValue( QRect( geom.x()+geom.width(), geom.y(), 0, geom.height()) ); - anim->setEndValue( geom ); - }else{ - //Invalid/None animation - if(nval.toBool()){ this->show(); } - else{ this->hide(); } - return; - } - if(nval.toBool()){ - this->setGeometry( anim->startValue().toRect() ); //ensure the window is the initial geom before it becomes visible - //QTimer::singleShot( anim->duration()+5, this, SLOT(activate()) ); - }else{ - QVariant tmp = anim->startValue(); - anim->setStartValue(anim->endValue()); - anim->setEndValue(tmp); - animResetProp = anim->startValue(); - QTimer::singleShot(anim->duration(), this, SLOT(hide()) ); - } - WinWidget->pause(); - anim->start(); - this->show(); - } //end of Visibility animation - else if(prop == NativeWindow::Size){ - //This is pretty much all geometry animations where the window is visible->visible - anim->setPropertyName("geometry"); - anim->setStartValue(this->geometry()); - anim->setEndValue(nval.toRect()); - /*if(name==""){ - // TO-DO modify the path from beginning->end somehow - }*/ - // Now start the animation - WinWidget->pause(); - anim->start(); - this->show(); - } -} - -void RootSubWindow::animFinished(){ - if(closing){ this->close(); return;} - else if(anim->propertyName()=="geometry"){ - if(!animResetProp.isNull()){ - /*qDebug() << "Animation Finished, Reset Geometry:" << animResetProp.toRect(); - qDebug() << " - Starting Value:" << anim->startValue().toRect(); - qDebug() << " - Ending Value:" << anim->endValue().toRect();*/ - this->setGeometry( animResetProp.toRect() ); - //Also ensure that the proper geometry is saved to the window structure - QRect curg = this->geometry(); - QRect wing = WIN->geometry(); - //qDebug() << " - After Animation Reset:" << curg << wing; - if(curg!=wing){ - QRect clientg = clientGlobalGeom(); - //qDebug() << "Sub Window geometry:" << clientg; - WIN->setProperties(QList< NativeWindow::Property>() << NativeWindow::Size << NativeWindow::GlobalPos, - QList() << clientg.size() << clientg.topLeft() ); - } - } - WinWidget->resyncWindow(); //also let the window know about the current geometry - } - animResetProp = QVariant(); //clear the variable - //QTimer::singleShot(10, WinWidget, SLOT(resume()) ); - WinWidget->resume(); - emit windowAnimFinished(); -} diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp deleted file mode 100644 index 5040f2f9..00000000 --- a/src-qt5/core/libLumina/RootSubWindow.cpp +++ /dev/null @@ -1,601 +0,0 @@ -//=========================================== -// Lumina Desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "RootSubWindow.h" -#include -#include -#include -#include -#include -#include - -#define WIN_BORDER 5 - -#include -#include - -// === PUBLIC === -RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){ - this->setAttribute(Qt::WA_DeleteOnClose); - this->setMouseTracking(true); - //Create the QWindow and QWidget containers for the window - WIN = win; - closing = false; - initWindowFrame(); - //Hookup the signals/slots - connect(WIN, SIGNAL(PropertiesChanged(QList, QList)), this, SLOT(propertiesChanged(QList, QList))); - WinWidget->embedWindow(WIN); - //qDebug() << "[NEW WINDOW]" << WIN->id() << WinWidget->winId() << this->winId(); - activeState = RootSubWindow::Normal; - LoadAllProperties(); -} - -RootSubWindow::~RootSubWindow(){ - //qDebug() << "Visible Window Destroyed"; - WIN->deleteLater(); -} - -WId RootSubWindow::id(){ - return WIN->id(); -} - -NativeWindow* RootSubWindow::nativeWindow(){ - return WIN; -} - -// === PRIVATE === -RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset){ - //Note: pt should be in widget-relative coordinates, not global - if(!WinWidget->geometry().contains(pt) && !titleBar->geometry().contains(pt)){ - //above the frame itself - need to figure out which quadrant it is in (8-directions) - if(pt.y() < WIN_BORDER){ - //One of the top options - if(pt.x() < this->width()/5){ - if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner - return ResizeTopLeft; - }else if(pt.x() > (this->width()*4.0/5.0)){ - if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()); } //difference from top-right corner - return ResizeTopRight; - }else{ - if(setoffset){ offset.setX(0); offset.setY(pt.y()); } //difference from top edge (X does not matter) - return ResizeTop; - } - }else if(pt.y() > (this->height()-WIN_BORDER) ){ - //One of the bottom options - if(pt.x() < this->width()/5){ - if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()-this->height()); } //difference from bottom-left corner - return ResizeBottomLeft; - }else if(pt.x() > (this->width()*4.0/5.0)){ - if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //difference from bottom-right corner - return ResizeBottomRight; - }else{ - if(setoffset){ offset.setX(0); offset.setY(pt.y()-this->height()); } //difference from bottom edge (X does not matter) - return ResizeBottom; - } - }else if(pt.x() < WIN_BORDER){ - //Left side options - if(pt.y() < this->height()/5){ - if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner - return ResizeTopLeft; - }else if(pt.y() > (this->height()*4.0/5.0)){ - if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()-this->height()); } //difference from bottom-left corner - return ResizeBottomLeft; - }else{ - if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter) - return ResizeLeft; - } - }else if(pt.x() > (this->width()-WIN_BORDER) ){ - //Right side options - if(pt.y() < this->height()/5){ - if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()); } //difference from top-right corner - return ResizeTopRight; - }else if(pt.y() > (this->height()*4.0/5.0)){ - if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //difference from bottom-right corner - return ResizeBottomRight; - }else{ - if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(0); } //difference from right edge (Y does not matter) - return ResizeRight; - } - }else{ - return Normal; - } - } - //if it gets this far just return normal - return Normal; -} - -void RootSubWindow::setMouseCursor(ModState state, bool override){ - if(currentCursor==state && !override){ return; } //nothing to change - Qt::CursorShape shape; - switch(state){ - case Normal: - shape = Qt::ArrowCursor; - break; - case Move: - shape = Qt::SizeAllCursor; - break; - case ResizeTop: - shape = Qt::SizeVerCursor; - break; - case ResizeTopRight: - shape = Qt::SizeBDiagCursor; - break; - case ResizeRight: - shape = Qt::SizeHorCursor; - break; - case ResizeBottomRight: - shape = Qt::SizeFDiagCursor; - break; - case ResizeBottom: - shape = Qt::SizeVerCursor; - break; - case ResizeBottomLeft: - shape = Qt::SizeBDiagCursor; - break; - case ResizeLeft: - shape = Qt::SizeHorCursor; - break; - case ResizeTopLeft: - shape = Qt::SizeFDiagCursor; - break; - } - if(override){ - QApplication::setOverrideCursor(QCursor(shape)); - }else{ - currentCursor = state; - this->setCursor(shape); - } -} - -void RootSubWindow::initWindowFrame(){ - //qDebug() << "Create RootSubWindow Frame"; - this->setContentsMargins(0,0,0,0); - mainLayout = new QVBoxLayout(this); - mainLayout->setContentsMargins(0,0,0,0); - titleBar = new QWidget(this); - titleBar->setContentsMargins(0,0,0,0); - titleBarL = new QHBoxLayout(titleBar); - titleBarL->setContentsMargins(0,0,0,0); - closeB = new QToolButton(this); - maxB = new QToolButton(this); - minB = new QToolButton(this); - otherB = new QToolButton(this); - anim = new QPropertyAnimation(this); - anim->setTargetObject(this); - anim->setDuration(200); //1/5 second (appx) - connect(anim, SIGNAL(finished()), this, SLOT(animFinished()) ); - titleLabel = new QLabel(this); - titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - otherM = new QMenu(this); //menu of other actions - otherB->setMenu(otherM); - otherB->setPopupMode(QToolButton::InstantPopup); - otherB->setAutoRaise(true); - WinWidget = new NativeEmbedWidget(this); - connect(closeB, SIGNAL(clicked()), this, SLOT(triggerClose()) ); - connect(maxB, SIGNAL(clicked()), this, SLOT(toggleMaximize()) ); - connect(minB, SIGNAL(clicked()), this, SLOT(toggleMinimize()) ); - //Now assemble the frame layout based on the current settings - titleBarL->addWidget(otherB); - titleBarL->addWidget(titleLabel); - titleBarL->addWidget(minB); - titleBarL->addWidget(maxB); - titleBarL->addWidget(closeB); - WinWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - mainLayout->addWidget(titleBar); - mainLayout->addWidget(WinWidget); - mainLayout->setAlignment(titleBar, Qt::AlignTop); - //Setup the cursors for the buttons - closeB->setCursor(Qt::ArrowCursor); - minB->setCursor(Qt::ArrowCursor); - maxB->setCursor(Qt::ArrowCursor); - otherB->setCursor(Qt::ArrowCursor); - titleLabel->setCursor(Qt::ArrowCursor); - WinWidget->setCursor(Qt::ArrowCursor); - //Now all the stylesheet options - this->setObjectName("WindowFrame"); - closeB->setObjectName("Button_Close"); - minB->setObjectName("Button_Minimize"); - maxB->setObjectName("Button_Maximize"); - otherM->setObjectName("Menu_Actions"); - titleLabel->setObjectName("Label_Title"); - this->setStyleSheet("QFrame#WindowFrame{background-color: rgba(0,0,0,125)} QWidget#Label_Title{background-color: transparent; color: white; } QToolButton{background-color: transparent; border: 1px solid transparent; border-radius: 3px; } QToolButton::hover{background-color: rgba(255,255,255,150); } QToolButton::pressed{ background-color: white; } QToolButton::menu-arrow{ image: none; }"); - //And adjust the margins - mainLayout->setSpacing(0); - titleBarL->setSpacing(1); - this->setFrameStyle(QFrame::NoFrame); - this->setLineWidth(0); - this->setMidLineWidth(0); - this->setFrameRect(QRect(0,0,0,0)); - - //Setup the timer object to syncronize info - moveTimer = new QTimer(this); - moveTimer->setSingleShot(true); - moveTimer->setInterval(100); //1/10 second - connect(moveTimer, SIGNAL(timeout()), WinWidget, SLOT(resyncWindow()) ); - - //Now load the icons for the button - LIconCache::instance()->loadIcon(closeB, "window-close"); - LIconCache::instance()->loadIcon(maxB, "window-maximize"); - LIconCache::instance()->loadIcon(minB, "window-minimize"); - LIconCache::instance()->loadIcon(otherB, "list"); -} - -void RootSubWindow::enableFrame(bool on){ - //Make the individual frame elements visible as needed - if(on){ this->setContentsMargins(WIN_BORDER,WIN_BORDER,WIN_BORDER,WIN_BORDER); }//default border - else{ this->setContentsMargins(0, 0, 0, 0); } - titleBar->setVisible(on); - //And now calculate/save the frame extents - QList extents; extents << 0 << 0 << 0 << 0; //left, right, top, bottom - if(on){ - extents[0] = WIN_BORDER; - extents[1] = WIN_BORDER; - extents[2] = WIN_BORDER + titleBar->height(); - extents[3] = WIN_BORDER; - } - //qDebug() << "SET FRAME EXTENTS:" << extents; - WIN->requestProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList >(extents) ); //save on raw window itself - WIN->setProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList >(extents) ); //save to structure now -} - -void RootSubWindow::enableFrame(QList types){ - static QList noframe; - if(noframe.isEmpty()){ noframe << NativeWindow::T_DESKTOP << NativeWindow::T_DOCK << NativeWindow::T_TOOLBAR << NativeWindow::T_MENU << NativeWindow::T_SPLASH << NativeWindow::T_DROPDOWN_MENU << NativeWindow::T_POPUP_MENU << NativeWindow::T_TOOLTIP << NativeWindow::T_NOTIFICATION << NativeWindow::T_COMBO << NativeWindow::T_DND; } - for(int i=0; i list){ - QList vals; - //Always ensure that visibility changes are evaluated last - bool addvisible = false; - for(int i=0; iproperty(list[i]); - } - //if(addvisible){ list << NativeWindow::Visible; vals << WIN->property(NativeWindow::Visible); } - propertiesChanged(list, vals); -} - -QRect RootSubWindow::clientGlobalGeom(){ - QRect tot = this->geometry(); - QList frame = WIN->property(NativeWindow::FrameExtents).value< QList >(); - //Now adjust this to take out the frame - tot.adjust(frame[0], frame[2], -frame[1], -frame[3]); - return tot; -} - -// === PUBLIC SLOTS === -void RootSubWindow::clientClosed(){ - //qDebug() << "Client Closed"; - closing = true; - if(anim->state()!=QAbstractAnimation::Running){ this->close(); } -} - -void RootSubWindow::LoadAllProperties(){ - QList< NativeWindow::Property> list; - list << NativeWindow::WinTypes << NativeWindow::WinActions << NativeWindow::States - << NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Title << NativeWindow::ShortTitle - << NativeWindow::Icon << NativeWindow::Size << NativeWindow::GlobalPos;// << NativeWindow::Visible << NativeWindow::Active; - LoadProperties(list); - //WIN->requestProperty(NativeWindow::Visible, true); -} - -//Button Actions - public so they can be tied to key shortcuts and stuff as well -void RootSubWindow::toggleMinimize(){ - WIN->toggleVisibility(); -} - -void RootSubWindow::toggleMaximize(){ - //Get the current screen that this window is on - QList screens = QApplication::screens(); - QRect rect; - int primaryscreen = 0; //fallback value - for(int i=0; igeometry().intersected(this->geometry()); - if( (intersect.width()-rect.width() + intersect.height()-rect.height()) > 0){ - rect = intersect; - primaryscreen = i; - } - } - //Now that we have the screen dimensions, lets check/change the window - rect = screens[primaryscreen]->availableGeometry(); - QList< NativeWindow::State > states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State> >(); - if(rect == this->geometry() || states.contains(NativeWindow::S_MAX_VERT) || states.contains(NativeWindow::S_MAX_HORZ)){ - //Already maximized - try to restore it to the previous size/location - if(!lastMaxGeom.isNull()){ - rect = lastMaxGeom; - }else{ - // no last geometry - started out maximized? - // make it half the screen size and centered on the screen - QPoint center = rect.center(); - rect.setWidth( rect.width()/2 ); - rect.setHeight( rect.height()/2 ); - rect.moveTopLeft( center - QPoint(rect.width()/2, rect.height()/2) ); - } - lastMaxGeom = QRect(); //clear this saved geom - }else{ - //Not maximized yet - go ahead and make it so - lastMaxGeom = this->geometry(); //save this for later; - } - //qDebug() << "Toggle Maximize:" << this->geometry() << rect; - QString anim_type = DesktopSettings::instance()->value(DesktopSettings::Animation, "window/move", "random").toString(); - loadAnimation(anim_type, NativeWindow::Size, rect); -} - -void RootSubWindow::triggerClose(){ - WIN->requestClose(); -} - -void RootSubWindow::toggleSticky(){ - QList< NativeWindow::State> states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State > >(); - if(states.contains(NativeWindow::S_STICKY)){ - states.removeAll(NativeWindow::S_STICKY); - }else{ - states << NativeWindow::S_STICKY; - } - WIN->requestProperty(NativeWindow::States, QVariant::fromValue >(states) ); -} - -void RootSubWindow::activate(){ - //WinWidget->raiseWindow(); - WIN->requestProperty(NativeWindow::Active, true, true); -} - -//Mouse Interactivity -void RootSubWindow::startMoving(){ - //If the cursor is not over this window, move it to the center of the titlebar - QPoint curpt = QCursor::pos(); //global coords - if(!this->geometry().contains(curpt)){ - curpt = this->mapToGlobal(titleBar->geometry().center()); - QCursor::setPos(curpt); - } - //Calculate the offset - activeState = Move; - offset = this->mapFromGlobal(curpt); - setMouseCursor(activeState, true); //this one is an override cursor - WinWidget->pause(); - this->grabMouse(); -} - -void RootSubWindow::startResizing(){ - activeState = getStateAtPoint( this->mapFromGlobal(QCursor::pos()), true); //also have it set the offset variable - setMouseCursor(activeState, true); //this one is an override cursor - WinWidget->pause(); - this->grabMouse(); -} - -// === PRIVATE SLOTS === -void RootSubWindow::propertiesChanged(QList props, QList vals){ - for(int i=0; iisPaused() && (this->isVisible()!=vals[i].toBool()) && activeState==Normal ){ - //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry(); - if(vals[i].toBool()){ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/appear", "random").toString(), NativeWindow::Visible, vals[i]); } - else{ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/disappear", "random").toString(), NativeWindow::Visible, vals[i]); } - } - break; - case NativeWindow::Title: - titleLabel->setText(vals[i].toString()); - break; - case NativeWindow::Icon: - //qDebug() << "Got Icon Change:" << vals[i]; - if(vals[i].value().isNull() ){ LIconCache::instance()->loadIcon(otherB, "list"); } - else{ otherB->setIcon(vals[i].value()); } - break; - case NativeWindow::GlobalPos: - if(vals[i].toPoint()!=QPoint(0,0)){ - WinWidget->resyncWindow(); - } - break; - case NativeWindow::Size: - //qDebug() << " - SIZE CHANGE"; - if(WIN->property(NativeWindow::FrameExtents).isNull() && (iisPaused() && activeState==Normal){ - if(WIN->property(NativeWindow::Size).toSize() != WinWidget->size()){ - //qDebug() << "Got Direct Geometry Change:" << WIN->geometry(); - this->setGeometry( QRect(this->geometry().topLeft(), WIN->geometry().size()) ); - WinWidget->resyncWindow(); - } - } - break; - case NativeWindow::MinSize: - if(vals[i].toSize().isValid()){ - //Just larger than titlebar, with enough space for 8 characters in the titlebar (+4 buttons) - //qDebug() << "Got invalid Min Size: Set a reasonable default minimum"; - WinWidget->setMinimumSize( QSize( this->fontMetrics().height()*4 + this->fontMetrics().width("O")*10, this->fontMetrics().height()*10) ); - WIN->setProperty(NativeWindow::MinSize, WinWidget->minimumSize()); - }else{ - WinWidget->setMinimumSize(vals[i].toSize()); - } - if(WIN->property(NativeWindow::Size).toSize().width() < WinWidget->minimumSize().width() \ - || WIN->property(NativeWindow::Size).toSize().height() < WinWidget->minimumSize().height() ){ - WIN->setProperty(NativeWindow::Size, WinWidget->minimumSize(), true); //force this - //WinWidget->resize(WinWidget->minimumSize()); - } - break; - case NativeWindow::MaxSize: - WinWidget->setMaximumSize(vals[i].toSize()); - break; - case NativeWindow::Active: - if(vals[i].toBool()){ activate(); } //WinWidget->raiseWindow(); } - break; - /*case NativeWindow::FrameExtents: - qDebug() << " - FRAME CHANGE"; - if(vals[i].isNull()){ - vals[i] = QVariant::fromValue >( QList() << WinWidget->geometry().x() << this->width()-WinWidget->geometry().x()-WinWidget->geometry().width() << WinWidget->y() << this->height() - WinWidget->y() - WinWidget->geometry().height() ); - WIN->setProperty(NativeWindow::FrameExtents, vals[i]); - } - qDebug() << "Setting Frame Extents:" << vals[i].value >(); - mainLayout->setContentsMargins( vals[i].value< QList >().at(0),vals[i].value< QList >().at(2) - titleLabel->height(),vals[i].value< QList >().at(1),vals[i].value< QList >().at(3)); - break;*/ - case NativeWindow::WinTypes: - //qDebug() << "Got Window Types:" << vals[i].value< QList >(); - enableFrame(vals[i].value< QList >() ); - break; - default: - qDebug() << "Window Property Unused:" << props[i] << vals[i]; - } - } -} - -// === PROTECTED === -void RootSubWindow::mousePressEvent(QMouseEvent *ev){ - activate(); - this->raise(); - QFrame::mousePressEvent(ev); - //qDebug() << "Frame Mouse Press Event"; - if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse - offset.setX(0); offset.setY(0); - if(ev->button()==Qt::LeftButton){ - if(this->childAt(ev->pos())!=0){ - //Clicked on the titlebar - startMoving(); - }else{ - //Clicked on the frame somewhere - startResizing(); - } - } - -} - -void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){ - QFrame::mouseMoveEvent(ev); - if(activeState == Normal){ - setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor - }else{ - //Currently in a modification state - QRect geom = this->geometry(); - QSize minsize(WinWidget->minimumSize().width() + (2*WIN_BORDER), WinWidget->minimumSize().height()+(2*WIN_BORDER)+titleBar->geometry().size().height()); - switch(activeState){ - case Move: - geom.moveTopLeft(ev->globalPos()-offset); //will not change size - break; - case ResizeTop: - geom.setTop(ev->globalPos().y()-offset.y()); - if(geom.size().height() < minsize.height()){ - geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height - } - break; - case ResizeTopRight: - geom.setTopRight(ev->globalPos()-offset); - if(geom.size().height() < minsize.height()){ - geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height - } - if(geom.size().width() < minsize.width()){ - geom.setRight(geom.x() + minsize.width()); //reset back to min width - } - break; - case ResizeRight: - geom.setRight(ev->globalPos().x()-offset.x()); - if(geom.size().width() < minsize.width()){ - geom.setRight(geom.x() + minsize.width()); //reset back to min width - } - break; - case ResizeBottomRight: - geom.setBottomRight(ev->globalPos()-offset); - if(geom.size().height() < minsize.height()){ - geom.setBottom(geom.y() + minsize.height()); //reset back to min height - } - if(geom.size().width() < minsize.width()){ - geom.setRight(geom.x() + minsize.width()); //reset back to min width - } - break; - case ResizeBottom: - geom.setBottom(ev->globalPos().y()-offset.y()); - if(geom.size().height() < minsize.height()){ - geom.setBottom(geom.y() + minsize.height()); //reset back to min height - } - break; - case ResizeBottomLeft: - geom.setBottomLeft(ev->globalPos()-offset); - if(geom.size().height() < minsize.height()){ - geom.setBottom(geom.y() + minsize.height()); //reset back to min height - } - if(geom.size().width() < minsize.width()){ - geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width - } - break; - case ResizeLeft: - geom.setLeft(ev->globalPos().x()-offset.x()); - if(geom.size().width() < minsize.width()){ - geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width - } - break; - case ResizeTopLeft: - geom.setTopLeft(ev->globalPos()-offset); - if(geom.size().height() < minsize.height()){ - geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height - } - if(geom.size().width() < minsize.width()){ - geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width - } - break; - default: - break; - } - //if( (geom.width()%2==0 && geom.height()%2==0) || activeState==Move){ - //qDebug() << " Change Window:" << this->geometry() << geom; - if(activeState==Move){ this->setGeometry(geom); } - else{ - //qDebug() << " Change Window Dimensions:" << this->geometry() << geom; - //qDebug() << " - Mouse Pos:" << ev->globalPos() << ev->pos() << "Offset" << offset; - this->setGeometry(geom); - } - //} - } -} - -void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){ - //Check for a right-click event - //qDebug() << "Frame Mouse Release Event"; - QFrame::mouseReleaseEvent(ev); - if( (activeState==Normal) && (titleBar->geometry().contains(ev->pos())) && (ev->button()==Qt::RightButton) ){ - //WinWidget->raiseWindow();//need to ensure the native window is always on top of this frame but under the menu - otherM->popup(ev->globalPos()); - return; - } - if(activeState!=Normal){ - if(WinWidget->isPaused()){ WinWidget->resume(); } - activeState = Normal; - QApplication::restoreOverrideCursor(); - setMouseCursor( getStateAtPoint(ev->pos()) ); - } - if(QFrame::mouseGrabber() == this){ this->releaseMouse(); } - activate(); - //QTimer::singleShot(0, WinWidget, SLOT(raiseWindow()) ); -} - -/*void RootSubWindow::enterEvent(QEvent *ev){ - QFrame::enterEvent(ev); - WinWidget->raiseWindow(); -}*/ -/*void RootSubWindow::leaveEvent(QEvent *ev){ - QFrame::leaveEvent(ev); - if(activeState == Normal){ - setMouseCursor(Normal); - } - if(!QRect(QPoint(0,0),this->size()).contains( this->mapFromGlobal(QCursor::pos())) ){ WinWidget->lowerWindow(); } -}*/ - -void RootSubWindow::moveEvent(QMoveEvent *ev){ - //qDebug() << "Got Move Event:" << ev->pos() << WinWidget->geometry(); - QFrame::moveEvent(ev); - if(!closing && !WinWidget->isPaused()){ - moveTimer->start(); - } -} diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/RootSubWindow.h deleted file mode 100644 index 598298e2..00000000 --- a/src-qt5/core/libLumina/RootSubWindow.h +++ /dev/null @@ -1,109 +0,0 @@ -//=========================================== -// Lumina Desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This class embeds a native window -// within the RootWindow area -//=========================================== -#ifndef _LUMINA_ROOT_WINDOW_SUB_WINDOW_H -#define _LUMINA_ROOT_WINDOW_SUB_WINDOW_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class RootSubWindow : public QFrame{ - Q_OBJECT -public: - RootSubWindow(QWidget *root, NativeWindow *win); - ~RootSubWindow(); - - WId id(); - NativeWindow* nativeWindow(); - -private: - //Window status - enum ModState{Normal, Move, ResizeTop, ResizeTopRight, ResizeRight, ResizeBottomRight, ResizeBottom, ResizeBottomLeft, ResizeLeft, ResizeTopLeft}; - ModState activeState; - ModState currentCursor; - QPoint offset; //needed for movement calculations (offset from mouse click to movement point) - //Functions for getting/setting state - ModState getStateAtPoint(QPoint pt, bool setoffset = false); //generally used for mouse location detection - void setMouseCursor(ModState, bool override = false); //Update the mouse cursor based on state - - //Native window embed objects - NativeWindow *WIN; - NativeEmbedWidget *WinWidget; - bool closing; - //Title bar objects - QBoxLayout *titleBarL, *mainLayout; - QToolButton *closeB, *maxB, *minB, *otherB; - QLabel *titleLabel; - QMenu *otherM; //menu of other actions - QWidget *titleBar; - //Other random objects (animations,etc) - QPropertyAnimation *anim; - QVariant animResetProp; - QTimer *moveTimer; - QRect lastGeom, lastMaxGeom; //frame coordinates - - void initWindowFrame(); - void enableFrame(bool); - void enableFrame(QList types); - - void LoadProperties( QList< NativeWindow::Property> list); - - static QStringList validAnimations(NativeWindow::Property); - -public slots: - void ensureVisible(){ WIN->setProperty(NativeWindow::Visible, true); } - void giveMouseFocus(){ WinWidget->raiseWindow(); } - void removeMouseFocus(){ WinWidget->lowerWindow(); } - void giveKeyboardFocus(){ WIN->requestProperty(NativeWindow::Active, true, true); } - - void clientClosed(); - void LoadAllProperties(); - - QRect clientGlobalGeom(); - - //Button Actions - public so they can be tied to key shortcuts and stuff as well - void toggleMinimize(); - void toggleMaximize(); - void triggerClose(); - void toggleSticky(); - void activate(); - - //Mouse Interactivity - void startMoving(); - void startResizing(); - -private slots: - void propertiesChanged(QList, QList); - - void loadAnimation(QString name, NativeWindow::Property, QVariant nval); //new val - void animFinished(); - -protected: - void mousePressEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - //void leaveEvent(QEvent *ev); - //void enterEvent(QEvent *ev); - void moveEvent(QMoveEvent *ev); - -signals: - void windowMoved(RootSubWindow*); - void windowAnimFinished(); -}; - -#endif diff --git a/src-qt5/core/libLumina/RootWindow-mgmt.cpp b/src-qt5/core/libLumina/RootWindow-mgmt.cpp deleted file mode 100644 index 24ea639b..00000000 --- a/src-qt5/core/libLumina/RootWindow-mgmt.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2016, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "RootWindow.h" - -//Primary/private function -void RootWindow::arrangeWindows(RootSubWindow *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; inativeWindow()->property(NativeWindow::Active).toBool()){ primary = WINDOWS[i]; } - } - if(primary==0 && !WINDOWS.isEmpty()){ primary = WINDOWS[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(); - 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 winlist = WINDOWS; - for(int i=0; inativeWindow()->property(NativeWindow::Workspace).toInt()!=wkspace - || !winlist[i]->nativeWindow()->property(NativeWindow::Visible).toBool() - || desktopArea.intersected(winlist[i]->geometry()).isNull() ){ - //window is outside of the desired area or invisible - ignore it - winlist.removeAt(i); - i--; - } - } - if(!winlist.contains(primary)){ winlist << primary; } //could be doing this on a window right before it is shown - else if(primaryonly){ winlist.removeAll(primary); winlist << primary; } //move primary window to last - //QRegion used; - for(int i=0; igeometry(); - //verify that the window is contained by the desktop area - if(geom.width()>desktopArea.width()){ geom.setWidth(desktopArea.width()); } - if(geom.height()>desktopArea.height()){ geom.setHeight(desktopArea.height()); } - //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()); - }else if(type=="snap"){ - - }else if(type=="single_max"){ - winlist[i]->setGeometry( 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); - - } - //qDebug() << " - New Geometry:" << winlist[i]->geometry(); - } //end loop over winlist -} - -// ================ -// Public slots for starting the arrangement routine(s) above -// ================ -void RootWindow::ArrangeWindows(WId primary, QString type){ - RootSubWindow* win = windowForId(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); - if(type.isEmpty()){ type = "single_max"; } //grab the default arrangement format for tiling - arrangeWindows(win, type); -} - -void RootWindow::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); - if(win==0){ return; } //invalid window - QRect geom = win->nativeWindow()->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); } - //Now run it through the window arrangement routine - arrangeWindows(win, newwindow ?"center" : "snap", true); -} diff --git a/src-qt5/core/libLumina/RootWindow.cpp b/src-qt5/core/libLumina/RootWindow.cpp deleted file mode 100644 index 705297be..00000000 --- a/src-qt5/core/libLumina/RootWindow.cpp +++ /dev/null @@ -1,283 +0,0 @@ -//=========================================== -// Lumina-DE source code -// Copyright (c) 2016, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "RootWindow.h" - -#include -#include -#include - -#define DEBUG 0 - -// === PUBLIC === -RootWindow::RootWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){ - qRegisterMetaType("WId"); - autoResizeTimer = 0; - lastActiveMouse = 0; - mouseFocusTimer = 0; - this->setMouseTracking(true); -} - -RootWindow::~RootWindow(){ - -} - -void RootWindow::start(){ - - if(autoResizeTimer==0){ - autoResizeTimer = new QTimer(this); - autoResizeTimer->setInterval(100); //1/10 second (collect all nearly-simultaneous signals and compress into a single update) - autoResizeTimer->setSingleShot(true); - connect(autoResizeTimer, SIGNAL(timeout()), this, SLOT(ResizeRoot()) ); - connect(QApplication::desktop(), SIGNAL(resized(int)), autoResizeTimer, SLOT(start()) ); - connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), autoResizeTimer, SLOT(start()) ); - } - if(mouseFocusTimer==0){ - mouseFocusTimer = new QTimer(this); - mouseFocusTimer->setInterval(100); - connect(mouseFocusTimer, SIGNAL(timeout()), this, SLOT(checkMouseFocus()) ); - - } - this->show(); - ResizeRoot(); - emit RegisterVirtualRoot(this->winId()); -} - -// === PRIVATE === -void RootWindow::updateScreenPixmap(screeninfo *info){ - QPixmap pix(info->area.size()); - if(info->scale == RootWindow::SolidColor){ - QColor color; - if(info->file.startsWith("rgb(")){ - QStringList colors = info->file.section(")",0,0).section("(",1,1).split(","); - color = QColor(colors[0].toInt(), colors[1].toInt(), colors[2].toInt()); - }else{ - color = QColor(info->file); - } - pix.fill(color); - }else{ - QPixmap raw(info->file); //load the image from file - //Now apply the proper aspect ratio as needed - if(info->scale == RootWindow::Stretch || info->scale == RootWindow::Full || info->scale == RootWindow::Fit){ - Qt::AspectRatioMode armode = Qt::KeepAspectRatio; - if(info->scale == RootWindow::Stretch ){ armode = Qt::IgnoreAspectRatio; } - else if(info->scale == RootWindow::Full ){ armode = Qt::KeepAspectRatioByExpanding; } - if(raw.height()!=info->area.height() && raw.width() !=info->area.width()){ - raw = raw.scaled(info->area.size(), armode); - } - } - //Now calculate offset and draw width/height - QRect drawRect(0,0, raw.width(), raw.height()); - if(info->scale == RootWindow::Full ){ - drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 ); - }else if(info->scale == RootWindow::Fit ){ - drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 ); - }else if(info->scale == RootWindow::Center ){ - drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 ); - }else if(info->scale == RootWindow::Tile ){ - //Draw the entire area - no offset - drawRect.setHeight(info->area.height()); - drawRect.setWidth(info->area.width()); - }else if(info->scale == RootWindow::BottomLeft ){ - drawRect.moveTo( 0 , info->area.height() - raw.height() ); - }else if(info->scale == RootWindow::BottomRight ){ - drawRect.moveTo( (info->area.width() - raw.width()), (info->area.height() - raw.height()) ); - }else if(info->scale == RootWindow::BottomCenter ){ - drawRect.moveTo( (info->area.width() - raw.width())/2, info->area.height() - raw.height() ); - }else if(info->scale == RootWindow::TopLeft ){ - drawRect.moveTo( 0, 0 ); - }else if(info->scale == RootWindow::TopRight ){ - drawRect.moveTo( (info->area.width() - raw.width()), 0); - }else if(info->scale == RootWindow::TopCenter ){ - drawRect.moveTo( (info->area.width() - raw.width())/2, 0); - }else if(info->scale == RootWindow::CenterLeft ){ - drawRect.moveTo( 0, (info->area.height() - raw.height())/2 ); - }else if(info->scale == RootWindow::CenterRight ){ - drawRect.moveTo( (info->area.width() - raw.width()), (info->area.height() - raw.height())/2 ); - } - - QPainter P(&pix); - P.setBrush(raw); - P.setBrushOrigin( drawRect.x(), drawRect.y() ); - P.drawRect( drawRect ); -} //end SolidColor Check - - info->wallpaper = pix; -} - -RootSubWindow* RootWindow::windowForId(WId id){ - RootSubWindow *tmp = 0; - for(int i=0; iid() == id){ tmp = WINDOWS[i]; } - } - return tmp; -} - -QScreen* RootWindow::screenUnderMouse(){ - QPoint mpos = QCursor::pos(); - QList scrns = QApplication::screens(); - for(int i=0; igeometry().contains(mpos)){ return scrns[i]; } - } - //Could not find an exact match - just return the first one - return scrns.first(); -} - -// === PUBLIC SLOTS === -void RootWindow::ResizeRoot(){ - if(DEBUG){ qDebug() << "Resize Root..."; } - QList scrns = QApplication::screens(); - //Update all the screen locations and ID's in the WALLPAPERS list - QRect fullscreen; - QStringList valid; - //Update the size of the rootWindow itself - for(int i=0; iname() << scrns[i]->geometry(); } - fullscreen = fullscreen.united(scrns[i]->geometry()); - valid << scrns[i]->name(); - for(int j=0; jname()){ - QSize oldsize = WALLPAPERS[j].area.size(); - WALLPAPERS[j].area = scrns[i]->geometry(); - if(oldsize != WALLPAPERS[j].area.size()){ updateScreenPixmap(&WALLPAPERS[j]); } - break; - } - } - } - //Now clean up any invalid screen info in the WALLPAPERS List - QStringList invalid; - for(int i=0; isetGeometry(fullscreen); - this->update(); - emit RootResized(fullscreen); - if(!valid.isEmpty()){ emit NewScreens(valid); } - if(!invalid.isEmpty()){ emit RemovedScreens(invalid); } - if(DEBUG){ qDebug() << " - Geom after change:" << this->geometry(); } -} - -void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file){ - bool found = false; - for(int i=0; i scrns = QApplication::screens(); - for(int i=0; iname()==id){ - screeninfo info; - info.id = id; - info.file = file; - info.scale = scale; - info.area = scrns[i]->geometry(); - updateScreenPixmap(&info); - //qDebug() << " --- Loaded Wallpaper:" << info.id << info.file << info.area; - WALLPAPERS << info; - break; - } - } - } //end check for a new id - -} - -void RootWindow::checkMouseFocus(){ - QPoint cpos = QCursor::pos(); - if(lastCursorPos != cpos){ emit MouseMoved(); } - lastCursorPos = cpos; - QWidget *child = this->childAt(QCursor::pos()); - while(child!=0 && child->whatsThis()!="RootSubWindow"){ - child = child->parentWidget(); - if(child==this){ child = 0;} //end of the line - } - - if(child==lastActiveMouse){ return; } //nothing new to do - //Make sure the child is actually a RootSubWindow - if(lastActiveMouse!=0){ lastActiveMouse->removeMouseFocus(); lastActiveMouse = 0; } - if(child!=0){ - lastActiveMouse = static_cast(child); - - if(DesktopSettings::instance()->value(DesktopSettings::WM, "focusFollowsMouse", true).toBool()){ - lastActiveMouse->giveKeyboardFocus(); - if(DesktopSettings::instance()->value(DesktopSettings::WM, "raiseOnFocus", false).toBool()){ - lastActiveMouse->raise(); - } - } - lastActiveMouse->giveMouseFocus(); //always give mouse focus on mouseover - } -} - -void RootWindow::NewWindow(NativeWindow *win){ - RootSubWindow *subwin = 0; - //qDebug() << "Got New Window:" << win->property(NativeWindow::Title); - for(int i=0; iid() == win->id()){ subwin = WINDOWS[i]; } - } - if(subwin==0){ - subwin = new RootSubWindow(this, win); - subwin->setWhatsThis("RootSubWindow"); - connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) ); - connect(subwin, SIGNAL(windowAnimFinished()), this, SLOT(checkMouseFocus()) ); - WINDOWS << subwin; - } - //QApplication::processEvents(); - CheckWindowPosition(win->id(), true); //first-time run - //QTimer::singleShot(300, subwin, SLOT(ensureVisible())); - win->setProperty(NativeWindow::Visible, true); - //win->requestProperty( NativeWindow::Active, true); - //win->requestProperties(QList() << NativeWindow::Visible << NativeWindow::Active, QList() << true << true, true); - if(!mouseFocusTimer->isActive()){ mouseFocusTimer->start(); } -} - -void RootWindow::CloseWindow(WId win){ - for(int i=0; iid() == win){ - if(lastActiveMouse==WINDOWS[i]){ lastActiveMouse = 0; } //no longer valid - WINDOWS.takeAt(i)->clientClosed(); - break; - } - } - if(WINDOWS.isEmpty()){ mouseFocusTimer->stop(); } //no windows to look for -} - -// === PRIVATE SLOTS === - -// === PROTECTED === -void RootWindow::paintEvent(QPaintEvent *ev){ - //qDebug() << "RootWindow: PaintEvent:" << ev->rect(); //<< QDateTime::currentDateTime()->toString(QDateTime::ShortDate); - //QWidget::paintEvent(ev); - bool found = false; - QPainter painter(this); - QRect geom = ev->rect(); - geom.adjust(-100,-100,100,100); //give it a few more pixels in each direction to repaint (noticing some issues in Qt 5.7.1) - for(int i=0; i -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "RootSubWindow.h" - -#include -#include - -class RootWindow : public QWidget{ - Q_OBJECT -public: - enum ScaleType{ SolidColor, Stretch, Full, Fit, Center, Tile, BottomLeft, BottomRight, BottomCenter, \ - TopLeft, TopRight, TopCenter, CenterLeft, CenterRight}; - - RootWindow(); - ~RootWindow(); - - void start(); - -private: - struct screeninfo{ - QString id; - QRect area; - QString file; - ScaleType scale; - QPixmap wallpaper; //Note: This pixmap will always be the same size as "area" - }; - QTimer *autoResizeTimer, *mouseFocusTimer; - RootSubWindow *lastActiveMouse; - QPoint lastCursorPos; - - QList WALLPAPERS; - void updateScreenPixmap(screeninfo *info); //used for recalculating the wallpaper pixmap based on file/area/scale as needed - - //Window Management - QList WINDOWS; - RootSubWindow* windowForId(WId id); - void arrangeWindows(RootSubWindow *primary = 0, QString type = "", bool primaryonly = false); - - QScreen* screenUnderMouse(); - - -public slots: - void ResizeRoot(); - void ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file); - //Note: for "SingleColor" scaling the "file" variable should be "rgb(R,G,B)" or "#hexcode" - void checkMouseFocus(); - - void NewWindow(NativeWindow*); - void CloseWindow(WId); //automatically connected for any new native window - - //Window arrangement functions - defined in "RootWindow-mgmt.cpp" - void ArrangeWindows(WId primary = 0, QString type = ""); - void TileWindows(WId primary = 0, QString type = ""); - void CheckWindowPosition(WId, bool newwindow = false); //used after a "drop" to validate/snap/re-arrange window(s) as needed - -private slots: - -protected: - void paintEvent(QPaintEvent *ev); - -signals: - void RegisterVirtualRoot(WId); - void RootResized(QRect); - void NewScreens(QStringList); // [screen_id_1, screen_id_2, etc..] - void RemovedScreens(QStringList); // [screen_id_1, screen_id_2, etc..] - void WorkspaceChanged(int); - void MouseMoved(); - -}; - -#endif diff --git a/src-qt5/core/libLumina/RootWindow.pri b/src-qt5/core/libLumina/RootWindow.pri deleted file mode 100644 index 9426b6b4..00000000 --- a/src-qt5/core/libLumina/RootWindow.pri +++ /dev/null @@ -1,17 +0,0 @@ - -# Files -SOURCES *= $${PWD}/RootWindow.cpp \ - $${PWD}/RootWindow-mgmt.cpp \ - $${PWD}/RootSubWindow.cpp \ - $${PWD}/RootSubWindow-animations.cpp - -HEADERS *= $${PWD}/RootWindow.h \ - $${PWD}/RootSubWindow.h - -INCLUDEPATH *= ${PWD} - -# include other library dependencies -include(LUtils.pri) -include(NativeWindow.pri) -include(LIconCache.pri) -include(DesktopSettings.pri) diff --git a/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp b/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp new file mode 100644 index 00000000..efab20fe --- /dev/null +++ b/src-qt5/core/libLumina/obsolete/RootSubWindow-animations.cpp @@ -0,0 +1,116 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "RootSubWindow.h" +#include + +QStringList RootSubWindow::validAnimations(NativeWindow::Property prop){ + QStringList valid; + if(prop == NativeWindow::Visible){ + valid << "zoom" << "wipe-center-vertical" << "wipe-center-horizontal" << "shade-top" << "shade-right" << "shade-left" << "shade-bottom"; + }else if(prop == NativeWindow::Size){ + //Note: this is used for pretty much all geometry changes to the window where it is visible both before/after animation + valid << "direct"; + } + return valid; +} + +void RootSubWindow::loadAnimation(QString name, NativeWindow::Property prop, QVariant nval){ + if(anim->state()==QAbstractAnimation::Running){ return; } //already running + animResetProp.clear(); + //Special case - random animation each time + if(name=="random"){ + QStringList valid = validAnimations(prop); + if(!valid.isEmpty()){ name = valid.at(qrand()%valid.length()); } + } + //Now setup the animation + if(prop == NativeWindow::Visible){ + //NOTE: Assigns values for "invisible->visible" animation: will reverse it afterwards as needed + anim->setPropertyName("geometry"); + QRect geom = this->geometry(); + if(name == "zoom"){ + //Zoom to/from the center point + anim->setStartValue( QRect(geom.center(), QSize(0,0)) ); + anim->setEndValue(geom); + }else if(name == "wipe-center-vertical"){ + anim->setStartValue( QRect( geom.center().x(), geom.y(), 0, geom.height()) ); + anim->setEndValue( geom ); + }else if(name == "wipe-center-horizontal"){ + anim->setStartValue( QRect( geom.x(), geom.center().y(), geom.width(), 0) ); + anim->setEndValue( geom ); + }else if(name == "shade-top"){ + anim->setStartValue( QRect( geom.x(), geom.y(), geom.width(), 0) ); + anim->setEndValue( geom ); + }else if(name == "shade-bottom"){ + anim->setStartValue( QRect( geom.x(), geom.y()+geom.height(), geom.width(), 0) ); + anim->setEndValue( geom ); + }else if(name == "shade-left"){ + anim->setStartValue( QRect( geom.x(), geom.y(), 0, geom.height()) ); + anim->setEndValue( geom ); + }else if(name == "shade-right"){ + anim->setStartValue( QRect( geom.x()+geom.width(), geom.y(), 0, geom.height()) ); + anim->setEndValue( geom ); + }else{ + //Invalid/None animation + if(nval.toBool()){ this->show(); } + else{ this->hide(); } + return; + } + if(nval.toBool()){ + this->setGeometry( anim->startValue().toRect() ); //ensure the window is the initial geom before it becomes visible + //QTimer::singleShot( anim->duration()+5, this, SLOT(activate()) ); + }else{ + QVariant tmp = anim->startValue(); + anim->setStartValue(anim->endValue()); + anim->setEndValue(tmp); + animResetProp = anim->startValue(); + QTimer::singleShot(anim->duration(), this, SLOT(hide()) ); + } + WinWidget->pause(); + anim->start(); + this->show(); + } //end of Visibility animation + else if(prop == NativeWindow::Size){ + //This is pretty much all geometry animations where the window is visible->visible + anim->setPropertyName("geometry"); + anim->setStartValue(this->geometry()); + anim->setEndValue(nval.toRect()); + /*if(name==""){ + // TO-DO modify the path from beginning->end somehow + }*/ + // Now start the animation + WinWidget->pause(); + anim->start(); + this->show(); + } +} + +void RootSubWindow::animFinished(){ + if(closing){ this->close(); return;} + else if(anim->propertyName()=="geometry"){ + if(!animResetProp.isNull()){ + /*qDebug() << "Animation Finished, Reset Geometry:" << animResetProp.toRect(); + qDebug() << " - Starting Value:" << anim->startValue().toRect(); + qDebug() << " - Ending Value:" << anim->endValue().toRect();*/ + this->setGeometry( animResetProp.toRect() ); + //Also ensure that the proper geometry is saved to the window structure + QRect curg = this->geometry(); + QRect wing = WIN->geometry(); + //qDebug() << " - After Animation Reset:" << curg << wing; + if(curg!=wing){ + QRect clientg = clientGlobalGeom(); + //qDebug() << "Sub Window geometry:" << clientg; + WIN->setProperties(QList< NativeWindow::Property>() << NativeWindow::Size << NativeWindow::GlobalPos, + QList() << clientg.size() << clientg.topLeft() ); + } + } + WinWidget->resyncWindow(); //also let the window know about the current geometry + } + animResetProp = QVariant(); //clear the variable + //QTimer::singleShot(10, WinWidget, SLOT(resume()) ); + WinWidget->resume(); + emit windowAnimFinished(); +} diff --git a/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp b/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp new file mode 100644 index 00000000..5040f2f9 --- /dev/null +++ b/src-qt5/core/libLumina/obsolete/RootSubWindow.cpp @@ -0,0 +1,601 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "RootSubWindow.h" +#include +#include +#include +#include +#include +#include + +#define WIN_BORDER 5 + +#include +#include + +// === PUBLIC === +RootSubWindow::RootSubWindow(QWidget *root, NativeWindow *win) : QFrame(root){ + this->setAttribute(Qt::WA_DeleteOnClose); + this->setMouseTracking(true); + //Create the QWindow and QWidget containers for the window + WIN = win; + closing = false; + initWindowFrame(); + //Hookup the signals/slots + connect(WIN, SIGNAL(PropertiesChanged(QList, QList)), this, SLOT(propertiesChanged(QList, QList))); + WinWidget->embedWindow(WIN); + //qDebug() << "[NEW WINDOW]" << WIN->id() << WinWidget->winId() << this->winId(); + activeState = RootSubWindow::Normal; + LoadAllProperties(); +} + +RootSubWindow::~RootSubWindow(){ + //qDebug() << "Visible Window Destroyed"; + WIN->deleteLater(); +} + +WId RootSubWindow::id(){ + return WIN->id(); +} + +NativeWindow* RootSubWindow::nativeWindow(){ + return WIN; +} + +// === PRIVATE === +RootSubWindow::ModState RootSubWindow::getStateAtPoint(QPoint pt, bool setoffset){ + //Note: pt should be in widget-relative coordinates, not global + if(!WinWidget->geometry().contains(pt) && !titleBar->geometry().contains(pt)){ + //above the frame itself - need to figure out which quadrant it is in (8-directions) + if(pt.y() < WIN_BORDER){ + //One of the top options + if(pt.x() < this->width()/5){ + if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner + return ResizeTopLeft; + }else if(pt.x() > (this->width()*4.0/5.0)){ + if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()); } //difference from top-right corner + return ResizeTopRight; + }else{ + if(setoffset){ offset.setX(0); offset.setY(pt.y()); } //difference from top edge (X does not matter) + return ResizeTop; + } + }else if(pt.y() > (this->height()-WIN_BORDER) ){ + //One of the bottom options + if(pt.x() < this->width()/5){ + if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()-this->height()); } //difference from bottom-left corner + return ResizeBottomLeft; + }else if(pt.x() > (this->width()*4.0/5.0)){ + if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //difference from bottom-right corner + return ResizeBottomRight; + }else{ + if(setoffset){ offset.setX(0); offset.setY(pt.y()-this->height()); } //difference from bottom edge (X does not matter) + return ResizeBottom; + } + }else if(pt.x() < WIN_BORDER){ + //Left side options + if(pt.y() < this->height()/5){ + if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()); } //difference from top-left corner + return ResizeTopLeft; + }else if(pt.y() > (this->height()*4.0/5.0)){ + if(setoffset){ offset.setX(pt.x()); offset.setY(pt.y()-this->height()); } //difference from bottom-left corner + return ResizeBottomLeft; + }else{ + if(setoffset){ offset.setX(pt.x()); offset.setY(0); } //difference from left edge (Y does not matter) + return ResizeLeft; + } + }else if(pt.x() > (this->width()-WIN_BORDER) ){ + //Right side options + if(pt.y() < this->height()/5){ + if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()); } //difference from top-right corner + return ResizeTopRight; + }else if(pt.y() > (this->height()*4.0/5.0)){ + if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(pt.y()-this->height()); } //difference from bottom-right corner + return ResizeBottomRight; + }else{ + if(setoffset){ offset.setX(pt.x()-this->width()); offset.setY(0); } //difference from right edge (Y does not matter) + return ResizeRight; + } + }else{ + return Normal; + } + } + //if it gets this far just return normal + return Normal; +} + +void RootSubWindow::setMouseCursor(ModState state, bool override){ + if(currentCursor==state && !override){ return; } //nothing to change + Qt::CursorShape shape; + switch(state){ + case Normal: + shape = Qt::ArrowCursor; + break; + case Move: + shape = Qt::SizeAllCursor; + break; + case ResizeTop: + shape = Qt::SizeVerCursor; + break; + case ResizeTopRight: + shape = Qt::SizeBDiagCursor; + break; + case ResizeRight: + shape = Qt::SizeHorCursor; + break; + case ResizeBottomRight: + shape = Qt::SizeFDiagCursor; + break; + case ResizeBottom: + shape = Qt::SizeVerCursor; + break; + case ResizeBottomLeft: + shape = Qt::SizeBDiagCursor; + break; + case ResizeLeft: + shape = Qt::SizeHorCursor; + break; + case ResizeTopLeft: + shape = Qt::SizeFDiagCursor; + break; + } + if(override){ + QApplication::setOverrideCursor(QCursor(shape)); + }else{ + currentCursor = state; + this->setCursor(shape); + } +} + +void RootSubWindow::initWindowFrame(){ + //qDebug() << "Create RootSubWindow Frame"; + this->setContentsMargins(0,0,0,0); + mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0,0,0,0); + titleBar = new QWidget(this); + titleBar->setContentsMargins(0,0,0,0); + titleBarL = new QHBoxLayout(titleBar); + titleBarL->setContentsMargins(0,0,0,0); + closeB = new QToolButton(this); + maxB = new QToolButton(this); + minB = new QToolButton(this); + otherB = new QToolButton(this); + anim = new QPropertyAnimation(this); + anim->setTargetObject(this); + anim->setDuration(200); //1/5 second (appx) + connect(anim, SIGNAL(finished()), this, SLOT(animFinished()) ); + titleLabel = new QLabel(this); + titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + otherM = new QMenu(this); //menu of other actions + otherB->setMenu(otherM); + otherB->setPopupMode(QToolButton::InstantPopup); + otherB->setAutoRaise(true); + WinWidget = new NativeEmbedWidget(this); + connect(closeB, SIGNAL(clicked()), this, SLOT(triggerClose()) ); + connect(maxB, SIGNAL(clicked()), this, SLOT(toggleMaximize()) ); + connect(minB, SIGNAL(clicked()), this, SLOT(toggleMinimize()) ); + //Now assemble the frame layout based on the current settings + titleBarL->addWidget(otherB); + titleBarL->addWidget(titleLabel); + titleBarL->addWidget(minB); + titleBarL->addWidget(maxB); + titleBarL->addWidget(closeB); + WinWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + mainLayout->addWidget(titleBar); + mainLayout->addWidget(WinWidget); + mainLayout->setAlignment(titleBar, Qt::AlignTop); + //Setup the cursors for the buttons + closeB->setCursor(Qt::ArrowCursor); + minB->setCursor(Qt::ArrowCursor); + maxB->setCursor(Qt::ArrowCursor); + otherB->setCursor(Qt::ArrowCursor); + titleLabel->setCursor(Qt::ArrowCursor); + WinWidget->setCursor(Qt::ArrowCursor); + //Now all the stylesheet options + this->setObjectName("WindowFrame"); + closeB->setObjectName("Button_Close"); + minB->setObjectName("Button_Minimize"); + maxB->setObjectName("Button_Maximize"); + otherM->setObjectName("Menu_Actions"); + titleLabel->setObjectName("Label_Title"); + this->setStyleSheet("QFrame#WindowFrame{background-color: rgba(0,0,0,125)} QWidget#Label_Title{background-color: transparent; color: white; } QToolButton{background-color: transparent; border: 1px solid transparent; border-radius: 3px; } QToolButton::hover{background-color: rgba(255,255,255,150); } QToolButton::pressed{ background-color: white; } QToolButton::menu-arrow{ image: none; }"); + //And adjust the margins + mainLayout->setSpacing(0); + titleBarL->setSpacing(1); + this->setFrameStyle(QFrame::NoFrame); + this->setLineWidth(0); + this->setMidLineWidth(0); + this->setFrameRect(QRect(0,0,0,0)); + + //Setup the timer object to syncronize info + moveTimer = new QTimer(this); + moveTimer->setSingleShot(true); + moveTimer->setInterval(100); //1/10 second + connect(moveTimer, SIGNAL(timeout()), WinWidget, SLOT(resyncWindow()) ); + + //Now load the icons for the button + LIconCache::instance()->loadIcon(closeB, "window-close"); + LIconCache::instance()->loadIcon(maxB, "window-maximize"); + LIconCache::instance()->loadIcon(minB, "window-minimize"); + LIconCache::instance()->loadIcon(otherB, "list"); +} + +void RootSubWindow::enableFrame(bool on){ + //Make the individual frame elements visible as needed + if(on){ this->setContentsMargins(WIN_BORDER,WIN_BORDER,WIN_BORDER,WIN_BORDER); }//default border + else{ this->setContentsMargins(0, 0, 0, 0); } + titleBar->setVisible(on); + //And now calculate/save the frame extents + QList extents; extents << 0 << 0 << 0 << 0; //left, right, top, bottom + if(on){ + extents[0] = WIN_BORDER; + extents[1] = WIN_BORDER; + extents[2] = WIN_BORDER + titleBar->height(); + extents[3] = WIN_BORDER; + } + //qDebug() << "SET FRAME EXTENTS:" << extents; + WIN->requestProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList >(extents) ); //save on raw window itself + WIN->setProperty(NativeWindow::FrameExtents, QVariant::fromValue< QList >(extents) ); //save to structure now +} + +void RootSubWindow::enableFrame(QList types){ + static QList noframe; + if(noframe.isEmpty()){ noframe << NativeWindow::T_DESKTOP << NativeWindow::T_DOCK << NativeWindow::T_TOOLBAR << NativeWindow::T_MENU << NativeWindow::T_SPLASH << NativeWindow::T_DROPDOWN_MENU << NativeWindow::T_POPUP_MENU << NativeWindow::T_TOOLTIP << NativeWindow::T_NOTIFICATION << NativeWindow::T_COMBO << NativeWindow::T_DND; } + for(int i=0; i list){ + QList vals; + //Always ensure that visibility changes are evaluated last + bool addvisible = false; + for(int i=0; iproperty(list[i]); + } + //if(addvisible){ list << NativeWindow::Visible; vals << WIN->property(NativeWindow::Visible); } + propertiesChanged(list, vals); +} + +QRect RootSubWindow::clientGlobalGeom(){ + QRect tot = this->geometry(); + QList frame = WIN->property(NativeWindow::FrameExtents).value< QList >(); + //Now adjust this to take out the frame + tot.adjust(frame[0], frame[2], -frame[1], -frame[3]); + return tot; +} + +// === PUBLIC SLOTS === +void RootSubWindow::clientClosed(){ + //qDebug() << "Client Closed"; + closing = true; + if(anim->state()!=QAbstractAnimation::Running){ this->close(); } +} + +void RootSubWindow::LoadAllProperties(){ + QList< NativeWindow::Property> list; + list << NativeWindow::WinTypes << NativeWindow::WinActions << NativeWindow::States + << NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Title << NativeWindow::ShortTitle + << NativeWindow::Icon << NativeWindow::Size << NativeWindow::GlobalPos;// << NativeWindow::Visible << NativeWindow::Active; + LoadProperties(list); + //WIN->requestProperty(NativeWindow::Visible, true); +} + +//Button Actions - public so they can be tied to key shortcuts and stuff as well +void RootSubWindow::toggleMinimize(){ + WIN->toggleVisibility(); +} + +void RootSubWindow::toggleMaximize(){ + //Get the current screen that this window is on + QList screens = QApplication::screens(); + QRect rect; + int primaryscreen = 0; //fallback value + for(int i=0; igeometry().intersected(this->geometry()); + if( (intersect.width()-rect.width() + intersect.height()-rect.height()) > 0){ + rect = intersect; + primaryscreen = i; + } + } + //Now that we have the screen dimensions, lets check/change the window + rect = screens[primaryscreen]->availableGeometry(); + QList< NativeWindow::State > states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State> >(); + if(rect == this->geometry() || states.contains(NativeWindow::S_MAX_VERT) || states.contains(NativeWindow::S_MAX_HORZ)){ + //Already maximized - try to restore it to the previous size/location + if(!lastMaxGeom.isNull()){ + rect = lastMaxGeom; + }else{ + // no last geometry - started out maximized? + // make it half the screen size and centered on the screen + QPoint center = rect.center(); + rect.setWidth( rect.width()/2 ); + rect.setHeight( rect.height()/2 ); + rect.moveTopLeft( center - QPoint(rect.width()/2, rect.height()/2) ); + } + lastMaxGeom = QRect(); //clear this saved geom + }else{ + //Not maximized yet - go ahead and make it so + lastMaxGeom = this->geometry(); //save this for later; + } + //qDebug() << "Toggle Maximize:" << this->geometry() << rect; + QString anim_type = DesktopSettings::instance()->value(DesktopSettings::Animation, "window/move", "random").toString(); + loadAnimation(anim_type, NativeWindow::Size, rect); +} + +void RootSubWindow::triggerClose(){ + WIN->requestClose(); +} + +void RootSubWindow::toggleSticky(){ + QList< NativeWindow::State> states = WIN->property(NativeWindow::States).value< QList< NativeWindow::State > >(); + if(states.contains(NativeWindow::S_STICKY)){ + states.removeAll(NativeWindow::S_STICKY); + }else{ + states << NativeWindow::S_STICKY; + } + WIN->requestProperty(NativeWindow::States, QVariant::fromValue >(states) ); +} + +void RootSubWindow::activate(){ + //WinWidget->raiseWindow(); + WIN->requestProperty(NativeWindow::Active, true, true); +} + +//Mouse Interactivity +void RootSubWindow::startMoving(){ + //If the cursor is not over this window, move it to the center of the titlebar + QPoint curpt = QCursor::pos(); //global coords + if(!this->geometry().contains(curpt)){ + curpt = this->mapToGlobal(titleBar->geometry().center()); + QCursor::setPos(curpt); + } + //Calculate the offset + activeState = Move; + offset = this->mapFromGlobal(curpt); + setMouseCursor(activeState, true); //this one is an override cursor + WinWidget->pause(); + this->grabMouse(); +} + +void RootSubWindow::startResizing(){ + activeState = getStateAtPoint( this->mapFromGlobal(QCursor::pos()), true); //also have it set the offset variable + setMouseCursor(activeState, true); //this one is an override cursor + WinWidget->pause(); + this->grabMouse(); +} + +// === PRIVATE SLOTS === +void RootSubWindow::propertiesChanged(QList props, QList vals){ + for(int i=0; iisPaused() && (this->isVisible()!=vals[i].toBool()) && activeState==Normal ){ + //qDebug() << "Got Visibility Change:" << vals[i] << this->geometry() << WIN->geometry(); + if(vals[i].toBool()){ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/appear", "random").toString(), NativeWindow::Visible, vals[i]); } + else{ loadAnimation( DesktopSettings::instance()->value(DesktopSettings::Animation, "window/disappear", "random").toString(), NativeWindow::Visible, vals[i]); } + } + break; + case NativeWindow::Title: + titleLabel->setText(vals[i].toString()); + break; + case NativeWindow::Icon: + //qDebug() << "Got Icon Change:" << vals[i]; + if(vals[i].value().isNull() ){ LIconCache::instance()->loadIcon(otherB, "list"); } + else{ otherB->setIcon(vals[i].value()); } + break; + case NativeWindow::GlobalPos: + if(vals[i].toPoint()!=QPoint(0,0)){ + WinWidget->resyncWindow(); + } + break; + case NativeWindow::Size: + //qDebug() << " - SIZE CHANGE"; + if(WIN->property(NativeWindow::FrameExtents).isNull() && (iisPaused() && activeState==Normal){ + if(WIN->property(NativeWindow::Size).toSize() != WinWidget->size()){ + //qDebug() << "Got Direct Geometry Change:" << WIN->geometry(); + this->setGeometry( QRect(this->geometry().topLeft(), WIN->geometry().size()) ); + WinWidget->resyncWindow(); + } + } + break; + case NativeWindow::MinSize: + if(vals[i].toSize().isValid()){ + //Just larger than titlebar, with enough space for 8 characters in the titlebar (+4 buttons) + //qDebug() << "Got invalid Min Size: Set a reasonable default minimum"; + WinWidget->setMinimumSize( QSize( this->fontMetrics().height()*4 + this->fontMetrics().width("O")*10, this->fontMetrics().height()*10) ); + WIN->setProperty(NativeWindow::MinSize, WinWidget->minimumSize()); + }else{ + WinWidget->setMinimumSize(vals[i].toSize()); + } + if(WIN->property(NativeWindow::Size).toSize().width() < WinWidget->minimumSize().width() \ + || WIN->property(NativeWindow::Size).toSize().height() < WinWidget->minimumSize().height() ){ + WIN->setProperty(NativeWindow::Size, WinWidget->minimumSize(), true); //force this + //WinWidget->resize(WinWidget->minimumSize()); + } + break; + case NativeWindow::MaxSize: + WinWidget->setMaximumSize(vals[i].toSize()); + break; + case NativeWindow::Active: + if(vals[i].toBool()){ activate(); } //WinWidget->raiseWindow(); } + break; + /*case NativeWindow::FrameExtents: + qDebug() << " - FRAME CHANGE"; + if(vals[i].isNull()){ + vals[i] = QVariant::fromValue >( QList() << WinWidget->geometry().x() << this->width()-WinWidget->geometry().x()-WinWidget->geometry().width() << WinWidget->y() << this->height() - WinWidget->y() - WinWidget->geometry().height() ); + WIN->setProperty(NativeWindow::FrameExtents, vals[i]); + } + qDebug() << "Setting Frame Extents:" << vals[i].value >(); + mainLayout->setContentsMargins( vals[i].value< QList >().at(0),vals[i].value< QList >().at(2) - titleLabel->height(),vals[i].value< QList >().at(1),vals[i].value< QList >().at(3)); + break;*/ + case NativeWindow::WinTypes: + //qDebug() << "Got Window Types:" << vals[i].value< QList >(); + enableFrame(vals[i].value< QList >() ); + break; + default: + qDebug() << "Window Property Unused:" << props[i] << vals[i]; + } + } +} + +// === PROTECTED === +void RootSubWindow::mousePressEvent(QMouseEvent *ev){ + activate(); + this->raise(); + QFrame::mousePressEvent(ev); + //qDebug() << "Frame Mouse Press Event"; + if(activeState != Normal){ return; } // do nothing - already in a state of grabbed mouse + offset.setX(0); offset.setY(0); + if(ev->button()==Qt::LeftButton){ + if(this->childAt(ev->pos())!=0){ + //Clicked on the titlebar + startMoving(); + }else{ + //Clicked on the frame somewhere + startResizing(); + } + } + +} + +void RootSubWindow::mouseMoveEvent(QMouseEvent *ev){ + QFrame::mouseMoveEvent(ev); + if(activeState == Normal){ + setMouseCursor( getStateAtPoint(ev->pos()) ); //just update the mouse cursor + }else{ + //Currently in a modification state + QRect geom = this->geometry(); + QSize minsize(WinWidget->minimumSize().width() + (2*WIN_BORDER), WinWidget->minimumSize().height()+(2*WIN_BORDER)+titleBar->geometry().size().height()); + switch(activeState){ + case Move: + geom.moveTopLeft(ev->globalPos()-offset); //will not change size + break; + case ResizeTop: + geom.setTop(ev->globalPos().y()-offset.y()); + if(geom.size().height() < minsize.height()){ + geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height + } + break; + case ResizeTopRight: + geom.setTopRight(ev->globalPos()-offset); + if(geom.size().height() < minsize.height()){ + geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height + } + if(geom.size().width() < minsize.width()){ + geom.setRight(geom.x() + minsize.width()); //reset back to min width + } + break; + case ResizeRight: + geom.setRight(ev->globalPos().x()-offset.x()); + if(geom.size().width() < minsize.width()){ + geom.setRight(geom.x() + minsize.width()); //reset back to min width + } + break; + case ResizeBottomRight: + geom.setBottomRight(ev->globalPos()-offset); + if(geom.size().height() < minsize.height()){ + geom.setBottom(geom.y() + minsize.height()); //reset back to min height + } + if(geom.size().width() < minsize.width()){ + geom.setRight(geom.x() + minsize.width()); //reset back to min width + } + break; + case ResizeBottom: + geom.setBottom(ev->globalPos().y()-offset.y()); + if(geom.size().height() < minsize.height()){ + geom.setBottom(geom.y() + minsize.height()); //reset back to min height + } + break; + case ResizeBottomLeft: + geom.setBottomLeft(ev->globalPos()-offset); + if(geom.size().height() < minsize.height()){ + geom.setBottom(geom.y() + minsize.height()); //reset back to min height + } + if(geom.size().width() < minsize.width()){ + geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width + } + break; + case ResizeLeft: + geom.setLeft(ev->globalPos().x()-offset.x()); + if(geom.size().width() < minsize.width()){ + geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width + } + break; + case ResizeTopLeft: + geom.setTopLeft(ev->globalPos()-offset); + if(geom.size().height() < minsize.height()){ + geom.setTop(geom.y() - (minsize.height()-geom.size().height())); //reset back to min height + } + if(geom.size().width() < minsize.width()){ + geom.setLeft(geom.x() - (minsize.width()-geom.size().width())); //reset back to min width + } + break; + default: + break; + } + //if( (geom.width()%2==0 && geom.height()%2==0) || activeState==Move){ + //qDebug() << " Change Window:" << this->geometry() << geom; + if(activeState==Move){ this->setGeometry(geom); } + else{ + //qDebug() << " Change Window Dimensions:" << this->geometry() << geom; + //qDebug() << " - Mouse Pos:" << ev->globalPos() << ev->pos() << "Offset" << offset; + this->setGeometry(geom); + } + //} + } +} + +void RootSubWindow::mouseReleaseEvent(QMouseEvent *ev){ + //Check for a right-click event + //qDebug() << "Frame Mouse Release Event"; + QFrame::mouseReleaseEvent(ev); + if( (activeState==Normal) && (titleBar->geometry().contains(ev->pos())) && (ev->button()==Qt::RightButton) ){ + //WinWidget->raiseWindow();//need to ensure the native window is always on top of this frame but under the menu + otherM->popup(ev->globalPos()); + return; + } + if(activeState!=Normal){ + if(WinWidget->isPaused()){ WinWidget->resume(); } + activeState = Normal; + QApplication::restoreOverrideCursor(); + setMouseCursor( getStateAtPoint(ev->pos()) ); + } + if(QFrame::mouseGrabber() == this){ this->releaseMouse(); } + activate(); + //QTimer::singleShot(0, WinWidget, SLOT(raiseWindow()) ); +} + +/*void RootSubWindow::enterEvent(QEvent *ev){ + QFrame::enterEvent(ev); + WinWidget->raiseWindow(); +}*/ +/*void RootSubWindow::leaveEvent(QEvent *ev){ + QFrame::leaveEvent(ev); + if(activeState == Normal){ + setMouseCursor(Normal); + } + if(!QRect(QPoint(0,0),this->size()).contains( this->mapFromGlobal(QCursor::pos())) ){ WinWidget->lowerWindow(); } +}*/ + +void RootSubWindow::moveEvent(QMoveEvent *ev){ + //qDebug() << "Got Move Event:" << ev->pos() << WinWidget->geometry(); + QFrame::moveEvent(ev); + if(!closing && !WinWidget->isPaused()){ + moveTimer->start(); + } +} diff --git a/src-qt5/core/libLumina/obsolete/RootSubWindow.h b/src-qt5/core/libLumina/obsolete/RootSubWindow.h new file mode 100644 index 00000000..598298e2 --- /dev/null +++ b/src-qt5/core/libLumina/obsolete/RootSubWindow.h @@ -0,0 +1,109 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This class embeds a native window +// within the RootWindow area +//=========================================== +#ifndef _LUMINA_ROOT_WINDOW_SUB_WINDOW_H +#define _LUMINA_ROOT_WINDOW_SUB_WINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class RootSubWindow : public QFrame{ + Q_OBJECT +public: + RootSubWindow(QWidget *root, NativeWindow *win); + ~RootSubWindow(); + + WId id(); + NativeWindow* nativeWindow(); + +private: + //Window status + enum ModState{Normal, Move, ResizeTop, ResizeTopRight, ResizeRight, ResizeBottomRight, ResizeBottom, ResizeBottomLeft, ResizeLeft, ResizeTopLeft}; + ModState activeState; + ModState currentCursor; + QPoint offset; //needed for movement calculations (offset from mouse click to movement point) + //Functions for getting/setting state + ModState getStateAtPoint(QPoint pt, bool setoffset = false); //generally used for mouse location detection + void setMouseCursor(ModState, bool override = false); //Update the mouse cursor based on state + + //Native window embed objects + NativeWindow *WIN; + NativeEmbedWidget *WinWidget; + bool closing; + //Title bar objects + QBoxLayout *titleBarL, *mainLayout; + QToolButton *closeB, *maxB, *minB, *otherB; + QLabel *titleLabel; + QMenu *otherM; //menu of other actions + QWidget *titleBar; + //Other random objects (animations,etc) + QPropertyAnimation *anim; + QVariant animResetProp; + QTimer *moveTimer; + QRect lastGeom, lastMaxGeom; //frame coordinates + + void initWindowFrame(); + void enableFrame(bool); + void enableFrame(QList types); + + void LoadProperties( QList< NativeWindow::Property> list); + + static QStringList validAnimations(NativeWindow::Property); + +public slots: + void ensureVisible(){ WIN->setProperty(NativeWindow::Visible, true); } + void giveMouseFocus(){ WinWidget->raiseWindow(); } + void removeMouseFocus(){ WinWidget->lowerWindow(); } + void giveKeyboardFocus(){ WIN->requestProperty(NativeWindow::Active, true, true); } + + void clientClosed(); + void LoadAllProperties(); + + QRect clientGlobalGeom(); + + //Button Actions - public so they can be tied to key shortcuts and stuff as well + void toggleMinimize(); + void toggleMaximize(); + void triggerClose(); + void toggleSticky(); + void activate(); + + //Mouse Interactivity + void startMoving(); + void startResizing(); + +private slots: + void propertiesChanged(QList, QList); + + void loadAnimation(QString name, NativeWindow::Property, QVariant nval); //new val + void animFinished(); + +protected: + void mousePressEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + //void leaveEvent(QEvent *ev); + //void enterEvent(QEvent *ev); + void moveEvent(QMoveEvent *ev); + +signals: + void windowMoved(RootSubWindow*); + void windowAnimFinished(); +}; + +#endif diff --git a/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp b/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp new file mode 100644 index 00000000..24ea639b --- /dev/null +++ b/src-qt5/core/libLumina/obsolete/RootWindow-mgmt.cpp @@ -0,0 +1,95 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "RootWindow.h" + +//Primary/private function +void RootWindow::arrangeWindows(RootSubWindow *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; inativeWindow()->property(NativeWindow::Active).toBool()){ primary = WINDOWS[i]; } + } + if(primary==0 && !WINDOWS.isEmpty()){ primary = WINDOWS[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(); + 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 winlist = WINDOWS; + for(int i=0; inativeWindow()->property(NativeWindow::Workspace).toInt()!=wkspace + || !winlist[i]->nativeWindow()->property(NativeWindow::Visible).toBool() + || desktopArea.intersected(winlist[i]->geometry()).isNull() ){ + //window is outside of the desired area or invisible - ignore it + winlist.removeAt(i); + i--; + } + } + if(!winlist.contains(primary)){ winlist << primary; } //could be doing this on a window right before it is shown + else if(primaryonly){ winlist.removeAll(primary); winlist << primary; } //move primary window to last + //QRegion used; + for(int i=0; igeometry(); + //verify that the window is contained by the desktop area + if(geom.width()>desktopArea.width()){ geom.setWidth(desktopArea.width()); } + if(geom.height()>desktopArea.height()){ geom.setHeight(desktopArea.height()); } + //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()); + }else if(type=="snap"){ + + }else if(type=="single_max"){ + winlist[i]->setGeometry( 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); + + } + //qDebug() << " - New Geometry:" << winlist[i]->geometry(); + } //end loop over winlist +} + +// ================ +// Public slots for starting the arrangement routine(s) above +// ================ +void RootWindow::ArrangeWindows(WId primary, QString type){ + RootSubWindow* win = windowForId(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); + if(type.isEmpty()){ type = "single_max"; } //grab the default arrangement format for tiling + arrangeWindows(win, type); +} + +void RootWindow::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); + if(win==0){ return; } //invalid window + QRect geom = win->nativeWindow()->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); } + //Now run it through the window arrangement routine + arrangeWindows(win, newwindow ?"center" : "snap", true); +} diff --git a/src-qt5/core/libLumina/obsolete/RootWindow.cpp b/src-qt5/core/libLumina/obsolete/RootWindow.cpp new file mode 100644 index 00000000..705297be --- /dev/null +++ b/src-qt5/core/libLumina/obsolete/RootWindow.cpp @@ -0,0 +1,283 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "RootWindow.h" + +#include +#include +#include + +#define DEBUG 0 + +// === PUBLIC === +RootWindow::RootWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){ + qRegisterMetaType("WId"); + autoResizeTimer = 0; + lastActiveMouse = 0; + mouseFocusTimer = 0; + this->setMouseTracking(true); +} + +RootWindow::~RootWindow(){ + +} + +void RootWindow::start(){ + + if(autoResizeTimer==0){ + autoResizeTimer = new QTimer(this); + autoResizeTimer->setInterval(100); //1/10 second (collect all nearly-simultaneous signals and compress into a single update) + autoResizeTimer->setSingleShot(true); + connect(autoResizeTimer, SIGNAL(timeout()), this, SLOT(ResizeRoot()) ); + connect(QApplication::desktop(), SIGNAL(resized(int)), autoResizeTimer, SLOT(start()) ); + connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), autoResizeTimer, SLOT(start()) ); + } + if(mouseFocusTimer==0){ + mouseFocusTimer = new QTimer(this); + mouseFocusTimer->setInterval(100); + connect(mouseFocusTimer, SIGNAL(timeout()), this, SLOT(checkMouseFocus()) ); + + } + this->show(); + ResizeRoot(); + emit RegisterVirtualRoot(this->winId()); +} + +// === PRIVATE === +void RootWindow::updateScreenPixmap(screeninfo *info){ + QPixmap pix(info->area.size()); + if(info->scale == RootWindow::SolidColor){ + QColor color; + if(info->file.startsWith("rgb(")){ + QStringList colors = info->file.section(")",0,0).section("(",1,1).split(","); + color = QColor(colors[0].toInt(), colors[1].toInt(), colors[2].toInt()); + }else{ + color = QColor(info->file); + } + pix.fill(color); + }else{ + QPixmap raw(info->file); //load the image from file + //Now apply the proper aspect ratio as needed + if(info->scale == RootWindow::Stretch || info->scale == RootWindow::Full || info->scale == RootWindow::Fit){ + Qt::AspectRatioMode armode = Qt::KeepAspectRatio; + if(info->scale == RootWindow::Stretch ){ armode = Qt::IgnoreAspectRatio; } + else if(info->scale == RootWindow::Full ){ armode = Qt::KeepAspectRatioByExpanding; } + if(raw.height()!=info->area.height() && raw.width() !=info->area.width()){ + raw = raw.scaled(info->area.size(), armode); + } + } + //Now calculate offset and draw width/height + QRect drawRect(0,0, raw.width(), raw.height()); + if(info->scale == RootWindow::Full ){ + drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 ); + }else if(info->scale == RootWindow::Fit ){ + drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 ); + }else if(info->scale == RootWindow::Center ){ + drawRect.moveTo( (info->area.width() - raw.width())/2, (info->area.height() - raw.height())/2 ); + }else if(info->scale == RootWindow::Tile ){ + //Draw the entire area - no offset + drawRect.setHeight(info->area.height()); + drawRect.setWidth(info->area.width()); + }else if(info->scale == RootWindow::BottomLeft ){ + drawRect.moveTo( 0 , info->area.height() - raw.height() ); + }else if(info->scale == RootWindow::BottomRight ){ + drawRect.moveTo( (info->area.width() - raw.width()), (info->area.height() - raw.height()) ); + }else if(info->scale == RootWindow::BottomCenter ){ + drawRect.moveTo( (info->area.width() - raw.width())/2, info->area.height() - raw.height() ); + }else if(info->scale == RootWindow::TopLeft ){ + drawRect.moveTo( 0, 0 ); + }else if(info->scale == RootWindow::TopRight ){ + drawRect.moveTo( (info->area.width() - raw.width()), 0); + }else if(info->scale == RootWindow::TopCenter ){ + drawRect.moveTo( (info->area.width() - raw.width())/2, 0); + }else if(info->scale == RootWindow::CenterLeft ){ + drawRect.moveTo( 0, (info->area.height() - raw.height())/2 ); + }else if(info->scale == RootWindow::CenterRight ){ + drawRect.moveTo( (info->area.width() - raw.width()), (info->area.height() - raw.height())/2 ); + } + + QPainter P(&pix); + P.setBrush(raw); + P.setBrushOrigin( drawRect.x(), drawRect.y() ); + P.drawRect( drawRect ); +} //end SolidColor Check + + info->wallpaper = pix; +} + +RootSubWindow* RootWindow::windowForId(WId id){ + RootSubWindow *tmp = 0; + for(int i=0; iid() == id){ tmp = WINDOWS[i]; } + } + return tmp; +} + +QScreen* RootWindow::screenUnderMouse(){ + QPoint mpos = QCursor::pos(); + QList scrns = QApplication::screens(); + for(int i=0; igeometry().contains(mpos)){ return scrns[i]; } + } + //Could not find an exact match - just return the first one + return scrns.first(); +} + +// === PUBLIC SLOTS === +void RootWindow::ResizeRoot(){ + if(DEBUG){ qDebug() << "Resize Root..."; } + QList scrns = QApplication::screens(); + //Update all the screen locations and ID's in the WALLPAPERS list + QRect fullscreen; + QStringList valid; + //Update the size of the rootWindow itself + for(int i=0; iname() << scrns[i]->geometry(); } + fullscreen = fullscreen.united(scrns[i]->geometry()); + valid << scrns[i]->name(); + for(int j=0; jname()){ + QSize oldsize = WALLPAPERS[j].area.size(); + WALLPAPERS[j].area = scrns[i]->geometry(); + if(oldsize != WALLPAPERS[j].area.size()){ updateScreenPixmap(&WALLPAPERS[j]); } + break; + } + } + } + //Now clean up any invalid screen info in the WALLPAPERS List + QStringList invalid; + for(int i=0; isetGeometry(fullscreen); + this->update(); + emit RootResized(fullscreen); + if(!valid.isEmpty()){ emit NewScreens(valid); } + if(!invalid.isEmpty()){ emit RemovedScreens(invalid); } + if(DEBUG){ qDebug() << " - Geom after change:" << this->geometry(); } +} + +void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file){ + bool found = false; + for(int i=0; i scrns = QApplication::screens(); + for(int i=0; iname()==id){ + screeninfo info; + info.id = id; + info.file = file; + info.scale = scale; + info.area = scrns[i]->geometry(); + updateScreenPixmap(&info); + //qDebug() << " --- Loaded Wallpaper:" << info.id << info.file << info.area; + WALLPAPERS << info; + break; + } + } + } //end check for a new id + +} + +void RootWindow::checkMouseFocus(){ + QPoint cpos = QCursor::pos(); + if(lastCursorPos != cpos){ emit MouseMoved(); } + lastCursorPos = cpos; + QWidget *child = this->childAt(QCursor::pos()); + while(child!=0 && child->whatsThis()!="RootSubWindow"){ + child = child->parentWidget(); + if(child==this){ child = 0;} //end of the line + } + + if(child==lastActiveMouse){ return; } //nothing new to do + //Make sure the child is actually a RootSubWindow + if(lastActiveMouse!=0){ lastActiveMouse->removeMouseFocus(); lastActiveMouse = 0; } + if(child!=0){ + lastActiveMouse = static_cast(child); + + if(DesktopSettings::instance()->value(DesktopSettings::WM, "focusFollowsMouse", true).toBool()){ + lastActiveMouse->giveKeyboardFocus(); + if(DesktopSettings::instance()->value(DesktopSettings::WM, "raiseOnFocus", false).toBool()){ + lastActiveMouse->raise(); + } + } + lastActiveMouse->giveMouseFocus(); //always give mouse focus on mouseover + } +} + +void RootWindow::NewWindow(NativeWindow *win){ + RootSubWindow *subwin = 0; + //qDebug() << "Got New Window:" << win->property(NativeWindow::Title); + for(int i=0; iid() == win->id()){ subwin = WINDOWS[i]; } + } + if(subwin==0){ + subwin = new RootSubWindow(this, win); + subwin->setWhatsThis("RootSubWindow"); + connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) ); + connect(subwin, SIGNAL(windowAnimFinished()), this, SLOT(checkMouseFocus()) ); + WINDOWS << subwin; + } + //QApplication::processEvents(); + CheckWindowPosition(win->id(), true); //first-time run + //QTimer::singleShot(300, subwin, SLOT(ensureVisible())); + win->setProperty(NativeWindow::Visible, true); + //win->requestProperty( NativeWindow::Active, true); + //win->requestProperties(QList() << NativeWindow::Visible << NativeWindow::Active, QList() << true << true, true); + if(!mouseFocusTimer->isActive()){ mouseFocusTimer->start(); } +} + +void RootWindow::CloseWindow(WId win){ + for(int i=0; iid() == win){ + if(lastActiveMouse==WINDOWS[i]){ lastActiveMouse = 0; } //no longer valid + WINDOWS.takeAt(i)->clientClosed(); + break; + } + } + if(WINDOWS.isEmpty()){ mouseFocusTimer->stop(); } //no windows to look for +} + +// === PRIVATE SLOTS === + +// === PROTECTED === +void RootWindow::paintEvent(QPaintEvent *ev){ + //qDebug() << "RootWindow: PaintEvent:" << ev->rect(); //<< QDateTime::currentDateTime()->toString(QDateTime::ShortDate); + //QWidget::paintEvent(ev); + bool found = false; + QPainter painter(this); + QRect geom = ev->rect(); + geom.adjust(-100,-100,100,100); //give it a few more pixels in each direction to repaint (noticing some issues in Qt 5.7.1) + for(int i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "RootSubWindow.h" + +#include +#include + +class RootWindow : public QWidget{ + Q_OBJECT +public: + enum ScaleType{ SolidColor, Stretch, Full, Fit, Center, Tile, BottomLeft, BottomRight, BottomCenter, \ + TopLeft, TopRight, TopCenter, CenterLeft, CenterRight}; + + RootWindow(); + ~RootWindow(); + + void start(); + +private: + struct screeninfo{ + QString id; + QRect area; + QString file; + ScaleType scale; + QPixmap wallpaper; //Note: This pixmap will always be the same size as "area" + }; + QTimer *autoResizeTimer, *mouseFocusTimer; + RootSubWindow *lastActiveMouse; + QPoint lastCursorPos; + + QList WALLPAPERS; + void updateScreenPixmap(screeninfo *info); //used for recalculating the wallpaper pixmap based on file/area/scale as needed + + //Window Management + QList WINDOWS; + RootSubWindow* windowForId(WId id); + void arrangeWindows(RootSubWindow *primary = 0, QString type = "", bool primaryonly = false); + + QScreen* screenUnderMouse(); + + +public slots: + void ResizeRoot(); + void ChangeWallpaper(QString id, RootWindow::ScaleType scale, QString file); + //Note: for "SingleColor" scaling the "file" variable should be "rgb(R,G,B)" or "#hexcode" + void checkMouseFocus(); + + void NewWindow(NativeWindow*); + void CloseWindow(WId); //automatically connected for any new native window + + //Window arrangement functions - defined in "RootWindow-mgmt.cpp" + void ArrangeWindows(WId primary = 0, QString type = ""); + void TileWindows(WId primary = 0, QString type = ""); + void CheckWindowPosition(WId, bool newwindow = false); //used after a "drop" to validate/snap/re-arrange window(s) as needed + +private slots: + +protected: + void paintEvent(QPaintEvent *ev); + +signals: + void RegisterVirtualRoot(WId); + void RootResized(QRect); + void NewScreens(QStringList); // [screen_id_1, screen_id_2, etc..] + void RemovedScreens(QStringList); // [screen_id_1, screen_id_2, etc..] + void WorkspaceChanged(int); + void MouseMoved(); + +}; + +#endif diff --git a/src-qt5/core/libLumina/obsolete/RootWindow.pri b/src-qt5/core/libLumina/obsolete/RootWindow.pri new file mode 100644 index 00000000..9426b6b4 --- /dev/null +++ b/src-qt5/core/libLumina/obsolete/RootWindow.pri @@ -0,0 +1,17 @@ + +# Files +SOURCES *= $${PWD}/RootWindow.cpp \ + $${PWD}/RootWindow-mgmt.cpp \ + $${PWD}/RootSubWindow.cpp \ + $${PWD}/RootSubWindow-animations.cpp + +HEADERS *= $${PWD}/RootWindow.h \ + $${PWD}/RootSubWindow.h + +INCLUDEPATH *= ${PWD} + +# include other library dependencies +include(LUtils.pri) +include(NativeWindow.pri) +include(LIconCache.pri) +include(DesktopSettings.pri) diff --git a/src-qt5/core/lumina-desktop-unified/LSession.cpp b/src-qt5/core/lumina-desktop-unified/LSession.cpp index bace2dbe..cc754005 100644 --- a/src-qt5/core/lumina-desktop-unified/LSession.cpp +++ b/src-qt5/core/lumina-desktop-unified/LSession.cpp @@ -129,15 +129,15 @@ void LSession::setupSession(){ QList scrns= QApplication::screens(); for(int i=0; iname(); - Lumina::ROOTWIN->ChangeWallpaper(scrns[i]->name(), RootWindow::Stretch, LOS::LuminaShare()+"desktop-background.jpg"); + RootDesktopObject::instance()->ChangeWallpaper(scrns[i]->name(), LOS::LuminaShare()+"desktop-background.jpg"); } - Lumina::ROOTWIN->start(); + //Lumina::ROOTWIN->start(); Lumina::NWS->setRoot_numberOfWorkspaces(QStringList() << "one" << "two"); Lumina::NWS->setRoot_currentWorkspace(0); if(DEBUG){ qDebug() << " - Create Desktop Context Menu"; } - DesktopContextMenu *cmenu = new DesktopContextMenu(Lumina::ROOTWIN); + /*DesktopContextMenu *cmenu = new DesktopContextMenu(Lumina::ROOTWIN); connect(cmenu, SIGNAL(showLeaveDialog()), this, SLOT(StartLogout()) ); - cmenu->start(); + cmenu->start();*/ //desktopFiles = QDir(QDir::homePath()+"/Desktop").entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs, QDir::Name | QDir::IgnoreCase | QDir::DirsFirst); //updateDesktops(); @@ -229,6 +229,7 @@ void LSession::setupGlobalConnections(){ connect(Lumina::ROOTWIN, SIGNAL(RegisterVirtualRoot(WId)), Lumina::NWS, SLOT(RegisterVirtualRoot(WId)) ); connect(Lumina::ROOTWIN, SIGNAL(RootResized(QRect)), Lumina::NWS, SLOT(setRoot_desktopGeometry(QRect)) ); connect(Lumina::ROOTWIN, SIGNAL(MouseMoved()), Lumina::SS, SLOT(newInputEvent()) ); + connect(Lumina::ROOTWIN, SIGNAL(startLogout()), this, SLOT(StartLogout()) ); //Native Window Class connections connect(Lumina::NEF, SIGNAL(WindowCreated(WId)), Lumina::NWS, SLOT(NewWindowDetected(WId))); diff --git a/src-qt5/core/lumina-desktop-unified/global-includes.h b/src-qt5/core/lumina-desktop-unified/global-includes.h index ae57ac08..91604362 100644 --- a/src-qt5/core/lumina-desktop-unified/global-includes.h +++ b/src-qt5/core/lumina-desktop-unified/global-includes.h @@ -55,7 +55,13 @@ #include #include #include +#include +#include +#include +// C++ Backend classes for QML interface +#include +#include // libLumina includes #include @@ -66,7 +72,6 @@ #include #include #include -#include #include #include #include @@ -74,8 +79,6 @@ #include #include -// Standard C includes -#include //Setup any global defines (no classes or global objects: use "global-objects.h" for that) diff --git a/src-qt5/core/lumina-desktop-unified/global-objects.h b/src-qt5/core/lumina-desktop-unified/global-objects.h index 0c990dc6..c204587f 100644 --- a/src-qt5/core/lumina-desktop-unified/global-objects.h +++ b/src-qt5/core/lumina-desktop-unified/global-objects.h @@ -25,8 +25,12 @@ #include "src-screensaver/LScreenSaver.h" //#include "src-WM/LWindowManager.h" +#include #include "LSession.h" +// Standard C includes +#include + //Any special defines for settings/testing #define ANIMTIME 80 //animation time in milliseconds diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro index 6b9ee876..21e46b22 100644 --- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro @@ -16,18 +16,13 @@ TARGET = lumina-desktop-unified target.path = $${L_BINDIR} #include all the special classes from the Lumina tree -include(../libLumina/ResizeMenu.pri) include(../libLumina/LDesktopUtils.pri) #includes LUtils and LOS include(../libLumina/LuminaXDG.pri) -#include(../libLumina/LuminaX11.pri) include(../libLumina/LuminaSingleApplication.pri) -include(../libLumina/LuminaThemes.pri) include(../libLumina/DesktopSettings.pri) -include(../libLumina/RootWindow.pri) include(../libLumina/ExternalProcess.pri) -include(../libLumina/NativeWindow.pri) +include(../../src-cpp/NativeWindow.pri) include(../libLumina/XDGMime.pri) -include(../libLumina/LIconCache.pri) include(../../src-cpp/plugins-screensaver.pri) @@ -45,8 +40,7 @@ SOURCES += main.cpp \ HEADERS += global-includes.h \ global-objects.h \ LSession.h \ - BootSplash.h \ - JsonMenu.h + BootSplash.h FORMS += BootSplash.ui diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp new file mode 100644 index 00000000..c0710bbc --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp @@ -0,0 +1,33 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "RootWindow.h" + +RootWindow::RootWindow(){ + root_win = QWindow::fromWinId( QX11Info::appRootWindow() ); // + root_view = new QQuickView(root_win); //make it a child of the root window + root_obj = RootDesktopObject::instance(); + syncRootSize(); + connect(root_win, SIGNAL(widthChanged(int)), this, SLOT(syncRootSize()) ); + connect(root_win, SIGNAL(heightChanged(int)),this, SLOT(syncRootSize()) ); + //Now setup the QQuickView + root_view->setResizeMode(QQuickView::SizeRootObjectToView); + root_view->engine()->rootContext()->setContextProperty("RootObject", root_obj); + root_view->setSource(QUrl("qrc:///qml/RootDesktop")); + root_view->show(); +} + +RootWindow::~RootWindow(){ + root_view->deleteLater(); + root_obj->deleteLater(); +} + +void RootWindow::syncRootSize(){ + if(root_win->width() != root_view->width() || root_win->height() != root_view->height()){ + root_view->setGeometry(0, 0, root_win->width(), root_win->height() ); + emit RootResized(root_view->geometry()); + } +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h new file mode 100644 index 00000000..1050ba21 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h @@ -0,0 +1,32 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_DESKTOP_ROOT_WINDOW_H +#define _LUMINA_DESKTOP_ROOT_WINDOW_H +#include + +class RootWindow : public QObject{ + Q_OBJECT +private: + QWindow *root_win; + QQuickView *root_view; + RootDesktopObject *root_obj; + +public: + RootWindow(); + ~RootWindow(); + +public slots: + void syncRootSize(); + +signals: + void startLogout(); + void RegisterVirtualRoot(WId); + void RootResized(QRect); + void MouseMoved(); +}; + +#endif 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 75aef8a6..25aa02b7 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri @@ -1,6 +1,8 @@ -SOURCES *= $${PWD}/ContextMenu.cpp +SOURCES *= $${PWD}/RootWindow.cpp -HEADERS *= $${PWD}/ContextMenu.h +HEADERS *= $${PWD}/RootWindow.h #update the includepath so we can just #include as needed without paths -INCLUDEPATH *= ${PWD} +INCLUDEPATH *= $${PWD} + +include(../../../src-cpp/Desktop.pri) diff --git a/src-qt5/src-cpp/Desktop.pri b/src-qt5/src-cpp/Desktop.pri index c7da397d..dff6646c 100644 --- a/src-qt5/src-cpp/Desktop.pri +++ b/src-qt5/src-cpp/Desktop.pri @@ -1,9 +1,12 @@ QT *= gui qml quick -SOURCES *= RootDesktopObject.cpp +SOURCES *= $${PWD}/RootDesktopObject.cpp \ + $${PWD}/ScreenObject.cpp -HEADERS *= RootDesktopObject.h \ - ScreenObject.h +HEADERS *= $${PWD}/RootDesktopObject.h \ + $${PWD}/ScreenObject.h -include(../src-qml/src-qml.pri) +INCLUDEPATH *= $${PWD} + +include($${PWD}/../src-qml/src-qml.pri) diff --git a/src-qt5/src-cpp/NativeEmbedWidget.cpp b/src-qt5/src-cpp/NativeEmbedWidget.cpp new file mode 100644 index 00000000..57b6edde --- /dev/null +++ b/src-qt5/src-cpp/NativeEmbedWidget.cpp @@ -0,0 +1,423 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "NativeEmbedWidget.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +//#include +//#include +#include +#include + +#define DISABLE_COMPOSITING true + +/*inline xcb_render_pictformat_t get_pictformat(){ + static xcb_render_pictformat_t format = 0; + if(format==0){ + xcb_render_query_pict_formats_reply_t *reply = xcb_render_query_pict_formats_reply( QX11Info::connection(), xcb_render_query_pict_formats(QX11Info::connection()), NULL); + format = xcb_render_util_find_standard_format(reply, XCB_PICT_STANDARD_ARGB_32)->id; + free(reply); + } + return format; +} + + +inline void renderWindowToWidget(WId id, QWidget *widget, bool hastransparency = true){ + //window and widget are assumed to be the same size + //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; } + + xcb_render_picture_t pic_id = xcb_generate_id(QX11Info::connection()); + xcb_render_create_picture_aux(QX11Info::connection(), pic_id, pix, get_pictformat() , 0, NULL); + // + xcb_render_composite(QX11Info::connection(), hastransparency ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC, pic_id, XCB_RENDER_PICTURE_NONE, widget->x11RenderHandle(), + 0, 0, 0, 0, 0, 0, (uint16_t) widget->width(), (uint16_t) widget->height() ); +}*/ + +#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_FOCUS_CHANGE | \ + XCB_EVENT_MASK_POINTER_MOTION) + +#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ + XCB_EVENT_MASK_BUTTON_RELEASE | \ + XCB_EVENT_MASK_POINTER_MOTION | \ + XCB_EVENT_MASK_EXPOSURE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_ENTER_WINDOW) + +inline void registerClientEvents(WId id, bool client = true){ + uint32_t values[] = {XCB_NONE}; + values[0] = client ? CLIENT_EVENT_MASK : FRAME_EVENT_MASK ; + /*{ (XCB_EVENT_MASK_PROPERTY_CHANGE + | XCB_EVENT_MASK_BUTTON_PRESS + | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_POINTER_MOTION + | XCB_EVENT_MASK_BUTTON_MOTION + | XCB_EVENT_MASK_EXPOSURE + | XCB_EVENT_MASK_STRUCTURE_NOTIFY + | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT + | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY + | XCB_EVENT_MASK_ENTER_WINDOW) + };*/ + xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, values); +} + +// ============ +// PRIVATE +// ============ +//Simplification functions for the XCB/XLib interactions +void NativeEmbedWidget::syncWinSize(QSize sz){ + if(WIN==0){ return; } + else if(!sz.isValid()){ sz = this->size(); } //use the current widget size + //qDebug() << "Sync Window Size:" << sz; + //if(sz == winSize){ return; } //no change + QPoint pt(0,0); + if(!DISABLE_COMPOSITING){ pt = this->mapToGlobal(QPoint(0,0)); } + const uint32_t valList[4] = {(uint32_t) pt.x(), (uint32_t) pt.y(), (uint32_t) sz.width(), (uint32_t) sz.height()}; + const uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; + xcb_configure_window(QX11Info::connection(), WIN->id(), mask, valList); + winSize = sz; //save this for checking later +} + +void NativeEmbedWidget::syncWidgetSize(QSize sz){ + //qDebug() << "Sync Widget Size:" << sz; + this->resize(sz); +} + +void NativeEmbedWidget::hideWindow(){ + //qDebug() << "Hide Embed Window"; + xcb_unmap_window(QX11Info::connection(), WIN->id()); +} + +void NativeEmbedWidget::showWindow(){ + //qDebug() << "Show Embed Window"; + xcb_map_window(QX11Info::connection(), WIN->id()); + reregisterEvents(); + if(!DISABLE_COMPOSITING){ + QTimer::singleShot(0,this, SLOT(repaintWindow())); + } +} + +QImage NativeEmbedWidget::windowImage(QRect geom){ + //if(DISABLE_COMPOSITING){ + if(!this->isVisible()){ return QImage(); } //nothing to grab yet + QList screens = static_cast( QApplication::instance() )->screens(); + //for(int i=0; icontains(this)){ + if(!screens.isEmpty()){ + return screens[0]->grabWindow(WIN->id(), geom.x(), geom.y(), geom.width(), geom.height()).toImage(); + } + //} + //} + return QImage(); + /*}else{ + //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 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 QImage(); } + QImage img(ximg->data, ximg->width, ximg->height, ximg->stride, QImage::Format_ARGB32_Premultiplied); + img = img.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); + + //Cleanup the XCB data structures + xcb_free_pixmap(QX11Info::connection(), pix); + + return img; + }*/ +} +void NativeEmbedWidget::setWinUnpaused(){ + paused = false; + winImage = QImage(); + if(!DISABLE_COMPOSITING){ + repaintWindow(); //update the cached image right away + }else if(this->isVisible()){ + showWindow(); + } + resyncWindow(); //make sure the window knows about the new location +} +// ============ +// PUBLIC +// ============ +NativeEmbedWidget::NativeEmbedWidget(QWidget *parent) : QWidget(parent){ + WIN = 0; //nothing embedded yet + paused = false; + this->setMouseTracking(true); + //this->setSizeIncrement(2,2); +} + +bool NativeEmbedWidget::embedWindow(NativeWindow *window){ + WIN = window; + + //Now send the embed event to the app + //qDebug() << " - send _XEMBED event"; + /*xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = WIN->id(); + event.type = obj->ATOMS["_XEMBED"]; //_XEMBED + event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; + event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY + event.data.data32[2] = 0; + event.data.data32[3] = this->winId(); //WID of the container + event.data.data32[4] = 0; + + xcb_send_event(QX11Info::connection(), 0, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + */ + //Now setup any redirects and return + if(!DISABLE_COMPOSITING){ + xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); + xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); //AUTOMATIC); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); + + //Now create/register the damage handler + // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore) + // -- Retested 6/29/17 (no change) Ken Moore + //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer + //xcb_damage_create(QX11Info::connection(), dmgID, WIN->id(), XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); + // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself). + Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles); + + WIN->addDamageID( (uint) dmgID); //save this for later + connect(WIN, SIGNAL(VisualChanged()), this, SLOT(repaintWindow()) ); //make sure we repaint the widget on visual change + }else{ + xcb_reparent_window(QX11Info::connection(), WIN->id(), this->winId(), 0, 0); + registerClientEvents(this->winId()); //child events get forwarded through the frame - watch this for changes too + //Also use a partial-composite here - make sure the window pixmap is available even when the window is obscured + xcb_composite_redirect_window(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_AUTOMATIC); + //xcb_composite_redirect_subwindows(QX11Info::connection(), WIN->id(), XCB_COMPOSITE_REDIRECT_MANUAL); + //Also alert us when the window visual changes + Damage dmgID = XDamageCreate(QX11Info::display(), WIN->id(), XDamageReportRawRectangles); + + WIN->addDamageID( (uint) dmgID); //save this for later + connect(WIN, SIGNAL(VisualChanged()), this, SLOT(repaintWindow()) ); //make sure we repaint the widget on visual change + } + WIN->addFrameWinID(this->winId()); + registerClientEvents(WIN->id()); + //qDebug() << "Events Registered:" << WIN->id() << this->winId(); + return true; +} + +bool NativeEmbedWidget::detachWindow(){ + xcb_reparent_window(QX11Info::connection(), WIN->id(), QX11Info::appRootWindow(), -1, -1); + //WIN = 0; + return true; +} + +bool NativeEmbedWidget::isEmbedded(){ + return (WIN!=0); +} + +void NativeEmbedWidget::raiseWindow(){ + if(DISABLE_COMPOSITING){ return; } + uint32_t val = XCB_STACK_MODE_ABOVE; + xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); +} + +void NativeEmbedWidget::lowerWindow(){ + if(DISABLE_COMPOSITING){ return; } + uint32_t val = XCB_STACK_MODE_BELOW; + xcb_configure_window(QX11Info::connection(), WIN->id(), XCB_CONFIG_WINDOW_STACK_MODE, &val); +} + +// ============== +// PUBLIC SLOTS +// ============== +//Pause/resume +void NativeEmbedWidget::pause(){ + if(DISABLE_COMPOSITING){ + winImage = windowImage(QRect(QPoint(0,0), this->size())); + hideWindow(); + }else{ + if(winImage.isNull()){ repaintWindow(); } //make sure we have one image already cached first + } + paused = true; +} + +void NativeEmbedWidget::resume(){ + //paused = false; + syncWinSize(); + if(DISABLE_COMPOSITING){ + //showWindow(); + }else{ + repaintWindow(); //update the cached image right away + } + QTimer::singleShot(10, this, SLOT(setWinUnpaused()) ); +} + +void NativeEmbedWidget::resyncWindow(){ + if(WIN==0){ return; } + //syncWinSize(); + //if(DISABLE_COMPOSITING){ + // Specs say to send an artificial configure event to the window if the window was reparented into the frame + QPoint loc = this->mapToGlobal( QPoint(0,0) ); + //Send an artificial configureNotify event to the window with the global position/size included + xcb_configure_notify_event_t *event = (xcb_configure_notify_event_t*) calloc(32,1); //always 32-byes long, even if we don't need all of it + event->x = loc.x(); + event->y = loc.y(); + event->width = this->width(); + event->height = this->height(); + event->border_width = 0; + event->above_sibling = XCB_NONE; + event->override_redirect = false; + event->window = WIN->id(); + event->event = WIN->id(); + event->response_type = XCB_CONFIGURE_NOTIFY; + xcb_send_event(QX11Info::connection(), false, WIN->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, (char *) event); + xcb_flush(QX11Info::connection()); + free(event); + /*}else{ + //Window is floating invisibly - make sure it is in the right place + //Make sure the window size is syncronized and visual up to date + //syncWinSize(); + QTimer::singleShot(10, this, SLOT(repaintWindow()) ); + }*/ + +} + +void NativeEmbedWidget::repaintWindow(){ + //if(DISABLE_COMPOSITING){ return; } + //qDebug() << "Update Window Image:" << !paused; + if(paused){ return; } + /*QImage tmp = windowImage( QRect(QPoint(0,0), this->size()) ); + if(!tmp.isNull()){ + winImage = tmp; + }else{ qDebug() << "Got Null Image!!"; }*/ + this->parentWidget()->update(); //visual changed - need to update the image on the widget +} + +void NativeEmbedWidget::reregisterEvents(){ + if(WIN!=0){ registerClientEvents(WIN->id()); } +} + +// ============== +// PROTECTED +// ============== +void NativeEmbedWidget::resizeEvent(QResizeEvent *ev){ + QWidget::resizeEvent(ev); + if(WIN!=0 && !paused){ + syncWinSize(ev->size()); + } //syncronize the window with the new widget size +} + +void NativeEmbedWidget::showEvent(QShowEvent *ev){ + if(WIN!=0){ showWindow(); } + QWidget::showEvent(ev); +} + +void NativeEmbedWidget::hideEvent(QHideEvent *ev){ + if(WIN!=0){ hideWindow(); } + QWidget::hideEvent(ev); +} + +void NativeEmbedWidget::paintEvent(QPaintEvent *ev){ + QPainter P(this); + P.setClipping(true); + P.setClipRect(0,0,this->width(), this->height()); + P.fillRect(ev->rect(), Qt::transparent); + if(WIN==0){ return; } + QRect geom = ev->rect(); //atomic updates + //qDebug() << "Paint Rect:" << geom; + QImage img; + if(!paused){ img = windowImage(geom); } + else if(!winImage.isNull()){ + if(winImage.size() == this->size()){ img = winImage.copy(geom); } + else{ img = winImage.scaled(geom.size()); } //this is a fast transformation - might be slightly distorted + } + //Need to paint the image from the window onto the widget as an overlay + P.drawImage( geom , img, QRect(QPoint(0,0), img.size()), Qt::NoOpaqueDetection); //1-to-1 mapping + + +} + +void NativeEmbedWidget::enterEvent(QEvent *ev){ + QWidget::enterEvent(ev); + //qDebug() << "Enter Embed Widget"; + //raiseWindow(); //this->grabMouse(); +} + +void NativeEmbedWidget::leaveEvent(QEvent *ev){ + QWidget::leaveEvent(ev); + /*qDebug() << "Leave Embed Widget"; + QPoint pt = QCursor::pos(); + QPoint relpt = this->parentWidget()->mapFromGlobal(pt); + qDebug() << " - Geom:" << this->geometry() << "Global pt:" << pt << "Relative pt:" << relpt; + if(!this->geometry().contains(relpt) ){ lowerWindow(); }*/ +} + +void NativeEmbedWidget::mouseMoveEvent(QMouseEvent *ev){ + QWidget::mouseMoveEvent(ev); + //Forward this event on to the window +} + +void NativeEmbedWidget::mousePressEvent(QMouseEvent *ev){ + QWidget::mousePressEvent(ev); + //Forward this event on to the window +} + +void NativeEmbedWidget::mouseReleaseEvent(QMouseEvent *ev){ + QWidget::mouseReleaseEvent(ev); + //Forward this event on to the window +} + +/*bool NativeEmbedWidget::nativeEvent(const QByteArray &eventType, void *message, long *result){ + if(eventType=="xcb_generic_event_t" && WIN!=0){ + //Convert to known event type (for X11 systems) + xcb_generic_event_t *ev = static_cast(message); + //qDebug() << "Got Embed Window Event:" << xcb_event_get_label(ev->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) << xcb_event_get_request_label(ev->response_type); + uint32_t mask = 0; + switch( ev->response_type & XCB_EVENT_RESPONSE_TYPE_MASK){ + case XCB_BUTTON_PRESS: + //This is a mouse button press + mask = XCB_EVENT_MASK_BUTTON_PRESS; + break; + case XCB_BUTTON_RELEASE: + //This is a mouse button release + //qDebug() << "Button Release Event"; + mask = XCB_EVENT_MASK_BUTTON_RELEASE; + break; + case XCB_MOTION_NOTIFY: + //This is a mouse movement event + mask = XCB_EVENT_MASK_POINTER_MOTION; + break; + case XCB_ENTER_NOTIFY: + //This is a mouse movement event when mouse goes over a new window + mask = XCB_EVENT_MASK_ENTER_WINDOW; + break; + case XCB_LEAVE_NOTIFY: + //This is a mouse movement event when mouse goes leaves a window + mask = XCB_EVENT_MASK_LEAVE_WINDOW; + break; + default: + mask = 0; + } + + //Now forward this event on to the embedded window + if(mask!=0){ + qDebug() << " - Got a mouse event"; + xcb_send_event(QX11Info::connection(), true, WIN->id(),mask, (char*) ev); + return true; + } + } + return false; +}*/ diff --git a/src-qt5/src-cpp/NativeEmbedWidget.h b/src-qt5/src-cpp/NativeEmbedWidget.h new file mode 100644 index 00000000..16bb46dc --- /dev/null +++ b/src-qt5/src-cpp/NativeEmbedWidget.h @@ -0,0 +1,74 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is a container object for embedding a native window into a QWidget +// and maintaining a 1-to-1 mapping of sizing and other properties +// while also providing compositing effects between the two windows +//=========================================== +#ifndef _LUMINA_NATIVE_EMBED_WIDGET_H +#define _LUMINA_NATIVE_EMBED_WIDGET_H + +#include "NativeWindow.h" +#include +#include +#include +#include +#include +#include +#include + +class NativeEmbedWidget : public QWidget{ + Q_OBJECT +private: + NativeWindow *WIN; + QSize winSize; + QImage winImage; + bool paused, hasAlphaChannel; + +private slots: + //Simplification functions + void syncWinSize(QSize sz = QSize()); + void syncWidgetSize(QSize sz); + void hideWindow(); + void showWindow(); + QImage windowImage(QRect geom); + + void setWinUnpaused(); + +public: + NativeEmbedWidget(QWidget *parent); + + bool embedWindow(NativeWindow *window); + bool detachWindow(); + bool isEmbedded(); //status of the embed + bool isPaused(){ return paused; } + +public slots: + void raiseWindow(); + void lowerWindow(); + + //Pause/resume + void pause(); + void resume(); + + void resyncWindow(); + void repaintWindow(); + void reregisterEvents(); + +protected: + void resizeEvent(QResizeEvent *ev); + void showEvent(QShowEvent *ev); + void hideEvent(QHideEvent *ev); + void paintEvent(QPaintEvent *ev); + void enterEvent(QEvent *ev); + void leaveEvent(QEvent *ev); + void mouseMoveEvent(QMouseEvent *ev); + void mousePressEvent(QMouseEvent *ev); + void mouseReleaseEvent(QMouseEvent *ev); + //bool nativeEvent(const QByteArray &eventType, void *message, long *result); +}; + +#endif diff --git a/src-qt5/src-cpp/NativeEventFilter.cpp b/src-qt5/src-cpp/NativeEventFilter.cpp new file mode 100644 index 00000000..c13c1fc8 --- /dev/null +++ b/src-qt5/src-cpp/NativeEventFilter.cpp @@ -0,0 +1,300 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2015-2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "NativeEventFilter.h" +#include +#include + +//#include +//#include + +//================================================== +// NOTE: All the XCB interactions and atoms are accessed via: +// obj->XCB->EWMH.(atom name) +// obj->XCB->(do something) +//================================================== + +/* +List of XCB response types (since almost impossible to find good docs on XCB) +switch (xcb_generic_event_t*->response_type & ~0x80) +case values: +XCB_KEY_[PRESS | RELEASE] +XCB_BUTTON_[PRESS | RELEASE] +XCB_MOTION_NOTIFY +XCB_ENTER_NOTIFY +XCB_LEAVE_NOTIFY +XCB_FOCUS_[IN | OUT] +XCB_KEYMAP_NOTIFY +XCB_EXPOSE +XCB_GRAPHICS_EXPOSURE +XCB_VISIBILITY_NOTIFY +XCB_CREATE_NOTIFY +XCB_DESTROY_NOTIFY +XCB_UNMAP_NOTIFY +XCB_MAP_[NOTIFY | REQUEST] +XCB_REPARENT_NOTIFY +XCB_CONFIGURE_[NOTIFY | REQUEST] +XCB_GRAVITY_NOTIFY +XCB_RESIZE_REQUEST +XCB_CIRCULATE_[NOTIFY | REQUEST] +XCB_PROPERTY_NOTIFY +XCB_SELECTION_[CLEAR | REQUEST | NOTIFY] +XCB_COLORMAP_NOTIFY +XCB_CLIENT_MESSAGE +*/ + +//SYSTEM TRAY STANDARD DEFINITIONS +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + +//#include +#include +#include +#include +#include + +#define DEBUG 0 + +//Special objects/variables for XCB parsing +static xcb_ewmh_connection_t EWMH; +//static LXCB *XCB = 0; +static xcb_atom_t _NET_SYSTEM_TRAY_OPCODE = 0; + +inline void ParsePropertyEvent(xcb_property_notify_event_t *ev, NativeEventFilter *obj){ + //qDebug() << "Got Property Event:" << ev->window << ev->atom; + NativeWindow::Property prop = NativeWindow::None; + //Now determine which properties are getting changed, and update the native window as appropriate + if(ev->atom == EWMH._NET_WM_NAME){ prop = NativeWindow::Title; } + else if(ev->atom == EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; } + else if(ev->atom == EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; } + else if(ev->atom == EWMH._NET_WM_DESKTOP){ prop = NativeWindow::Workspace; } + else if(ev->atom == EWMH._NET_WM_WINDOW_TYPE ){ prop = NativeWindow::WinTypes; } + else if( ev->atom == EWMH._NET_WM_STATE){ prop = NativeWindow::States; } + //Send out the signal if necessary + if(prop!=NativeWindow::None){ + //if(DEBUG){ + //qDebug() << "Detected Property Change:" << ev->window << prop; + //} + obj->emit WindowPropertyChanged(ev->window, prop); + }else{ + //Quick re-check of the simple properties (nothing like the icon or other graphics) + obj->emit WindowPropertiesChanged(ev->window, QList() << NativeWindow::Title + << NativeWindow::ShortTitle << NativeWindow::Workspace ); + //qDebug() << "Unknown Property Change:" << ev->window << ev->atom; + } +} + +inline void ParseClientMessageEvent(xcb_client_message_event_t *ev, NativeEventFilter *obj){ + NativeWindow::Property prop = NativeWindow::None; + QVariant val; + if(ev->type==EWMH._NET_WM_NAME){ prop = NativeWindow::Title; } + else if(ev->type==EWMH._NET_WM_ICON){ prop = NativeWindow::Icon; } + else if(ev->type==EWMH._NET_WM_ICON_NAME){ prop = NativeWindow::ShortTitle; } + else if(ev->type==EWMH._NET_WM_DESKTOP){ + prop = NativeWindow::Workspace; + val = QVariant( (int) ev->data.data32[0] ); + }else if(ev->type==EWMH._NET_WM_WINDOW_TYPE){ prop = NativeWindow::WinTypes; } + else if(ev->type==EWMH._NET_WM_STATE){ prop = NativeWindow::States; } + + if(prop!=NativeWindow::None){ + //if(DEBUG){ + qDebug() << "Detected Property Change Request:" << ev->window << prop; //} + if(val.isNull()){ obj->emit WindowPropertyChanged(ev->window, prop); } + else{ obj->emit RequestWindowPropertyChange(ev->window, prop, val); } + } + +} + + +//Constructor for the Event Filter wrapper +NativeEventFilter::NativeEventFilter() : QObject(){ + EF = new EventFilter(this); + if(EWMH.nb_screens <=0){ + xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH); + if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){ + qDebug() << "Error with XCB atom initializations"; + } + } + if(_NET_SYSTEM_TRAY_OPCODE==0){ + //_NET_SYSTEM_TRAY_OPCODE + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(QX11Info::connection(), 0, 23,"_NET_SYSTEM_TRAY_OPCODE"); + xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(QX11Info::connection(), cookie, NULL); + if(r){ + _NET_SYSTEM_TRAY_OPCODE = r->atom; + free(r); + } + } +} + +void NativeEventFilter::start(){ + if(DEBUG){ qDebug() << " - Install event filter..."; } + QCoreApplication::instance()->installNativeEventFilter(EF); + if(DEBUG){ qDebug() << " - Run request check..."; } + +} + +void NativeEventFilter::stop(){ + QCoreApplication::instance()->installNativeEventFilter(0); +} + +//============================= +// EventFilter Class +//============================= + +//Constructor for the XCB event filter +EventFilter::EventFilter(NativeEventFilter *parent) : QAbstractNativeEventFilter(){ + obj = parent; +} + +//This function format taken directly from the Qt5.3 documentation +bool EventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *){ + //qDebug() << "New Event"; + if(eventType=="xcb_generic_event_t"){ + //Convert to known event type (for X11 systems) + xcb_generic_event_t *ev = static_cast(message); + //Now parse the event and emit signals as necessary + switch( ev->response_type & ~0x80){ +//============================== +// INTERACTIVITY EVENTS +//============================== + case XCB_KEY_PRESS: + //This is a keyboard key press + //qDebug() << "Key Press Event" + obj->emit KeyPressed( ((xcb_key_press_event_t *) ev)->detail, ((xcb_key_press_event_t *) ev)->root ); + break; + case XCB_KEY_RELEASE: + //This is a keyboard key release + //qDebug() << "Key Release Event"; + obj->emit KeyReleased( ((xcb_key_release_event_t *) ev)->detail, ((xcb_key_release_event_t *) ev)->root ); + break; + case XCB_BUTTON_PRESS: + //This is a mouse button press + //qDebug() << "Button Press Event"; + obj->emit MousePressed( ((xcb_button_press_event_t *) ev)->detail, ((xcb_button_press_event_t *) ev)->root ); + break; + case XCB_BUTTON_RELEASE: + //This is a mouse button release + //qDebug() << "Button Release Event"; + obj->emit MouseReleased( ((xcb_button_release_event_t *) ev)->detail, ((xcb_button_release_event_t *) ev)->root ); + break; + case XCB_MOTION_NOTIFY: + //This is a mouse movement event + if(DEBUG){ qDebug() << "Motion Notify Event"; } + obj->emit MouseMovement(); + break; + case XCB_ENTER_NOTIFY: + //This is a mouse movement event when mouse goes over a new window + //qDebug() << "Enter Notify Event"; + obj->emit MouseEnterWindow( ((xcb_enter_notify_event_t *) ev)->root ); + break; + case XCB_LEAVE_NOTIFY: + //This is a mouse movement event when mouse goes leaves a window + //qDebug() << "Leave Notify Event"; + obj->emit MouseLeaveWindow( ((xcb_leave_notify_event_t *) ev)->root ); + break; +//============================== + case XCB_EXPOSE: + //qDebug() << "Expose Notify Event:"; + //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window; + break; +//============================== + case XCB_MAP_NOTIFY: + //qDebug() << "Window Map Event:" << ((xcb_map_notify_event_t *)ev)->window; + obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, true); + break; //This is just a notification that a window was mapped - nothing needs to change here + case XCB_MAP_REQUEST: + //qDebug() << "Window Map Request Event"; + obj->emit WindowCreated( ((xcb_map_request_event_t *) ev)->window ); + break; +//============================== + case XCB_CREATE_NOTIFY: + //qDebug() << "Window Create Event"; + break; +//============================== + case XCB_UNMAP_NOTIFY: + //qDebug() << "Window Unmap Event:" << ((xcb_unmap_notify_event_t *)ev)->window; + obj->emit WindowPropertyChanged( ((xcb_map_notify_event_t *)ev)->window, NativeWindow::Visible, false); + break; +//============================== + case XCB_DESTROY_NOTIFY: + //qDebug() << "Window Closed Event:" << ((xcb_destroy_notify_event_t *)ev)->window; + obj->emit WindowDestroyed( ((xcb_destroy_notify_event_t *) ev)->window ); + break; +//============================== + case XCB_FOCUS_IN: + //qDebug() << "Focus In Event:"; + break; +//============================== + case XCB_FOCUS_OUT: + //qDebug() << "Focus Out Event:"; + break; +//============================== + case XCB_PROPERTY_NOTIFY: + //qDebug() << "Property Notify Event:"; + ParsePropertyEvent((xcb_property_notify_event_t*)ev, obj); + break; +//============================== + case XCB_CLIENT_MESSAGE: + //qDebug() << "Client Message Event"; + //qDebug() << " - Given Window:" << ((xcb_client_message_event_t*)ev)->window; + if( ((xcb_client_message_event_t*)ev)->type == _NET_SYSTEM_TRAY_OPCODE && ((xcb_client_message_event_t*)ev)->format == 32){ + //data32[0] is timestamp, [1] is opcode, [2] is window handle + if(SYSTEM_TRAY_REQUEST_DOCK == ((xcb_client_message_event_t*)ev)->data.data32[1]){ + obj->emit TrayWindowCreated( ((xcb_client_message_event_t*)ev)->data.data32[2] ); + //addTrayApp( ((xcb_client_message_event_t*)ev)->data.data32[2] ); + } + //Ignore the System Tray messages at the moment + }else if(((xcb_client_message_event_t*)ev)->window != QX11Info::appRootWindow()){ + ParseClientMessageEvent((xcb_client_message_event_t*)ev, obj); + } + break; +//============================== + case XCB_CONFIGURE_NOTIFY: + //qDebug() << "Configure Notify Event"; + /*obj->emit WindowPropertiesChanged( ((xcb_configure_notify_event_t*)ev)->window, + QList() << NativeWindow::GlobalPos << NativeWindow::Size, + QList() << QPoint(((xcb_configure_notify_event_t*)ev)->x, ((xcb_configure_notify_event_t*)ev)->y) << + QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) );*/ + obj->emit WindowPropertyChanged( ((xcb_configure_notify_event_t*)ev)->window, NativeWindow::Size, + QSize(((xcb_configure_notify_event_t*)ev)->width, ((xcb_configure_notify_event_t*)ev)->height) ); + break; +//============================== + case XCB_CONFIGURE_REQUEST: + //qDebug() << "Configure Request Event"; + obj->emit RequestWindowPropertiesChange( ((xcb_configure_request_event_t*)ev)->window, + QList() << NativeWindow::GlobalPos << NativeWindow::Size, + QList() << QPoint(((xcb_configure_request_event_t*)ev)->x, ((xcb_configure_request_event_t*)ev)->y) << + QSize(((xcb_configure_request_event_t*)ev)->width, ((xcb_configure_request_event_t*)ev)->height) ); + break; +//============================== + case XCB_RESIZE_REQUEST: + //qDebug() << "Resize Request Event"; + obj->emit RequestWindowPropertyChange( ((xcb_resize_request_event_t*)ev)->window, + NativeWindow::Size, QSize(((xcb_resize_request_event_t*)ev)->width, ((xcb_resize_request_event_t*)ev)->height) ); + break; +//============================== + case XCB_SELECTION_CLEAR: + //qDebug() << "Selection Clear Event"; + break; +//============================== + case 85: //not sure what event this is - but it seems to come up very often (just hide the notice) + case 0: + case XCB_GE_GENERIC: + break; //generic event - don't do anything special + default: + //if( (ev->response_type & ~0x80)==TrayDmgID){ + obj->emit PossibleDamageEvent( ((xcb_damage_notify_event_t*)ev)->drawable ); + //checkDamageID( ((xcb_damage_notify_event_t*)ev)->drawable ); + //}else{ + //qDebug() << "Default Event:" << (ev->response_type & ~0x80); + //} +//============================== + } + } + return false; + //never stop event handling (this will not impact the X events themselves - just the internal Qt application) +} diff --git a/src-qt5/src-cpp/NativeEventFilter.h b/src-qt5/src-cpp/NativeEventFilter.h new file mode 100644 index 00000000..a3be3ef1 --- /dev/null +++ b/src-qt5/src-cpp/NativeEventFilter.h @@ -0,0 +1,71 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2012-2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This class provides the XCB event handling/registrations that are needed +//=========================================== +#ifndef _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H +#define _LUMINA_DESKTOP_NATIVE_EVENT_FILTER_H + +#include +#include +#include + +#include "NativeWindow.h" + + +class NativeEventFilter : public QObject{ + Q_OBJECT +private: + QAbstractNativeEventFilter* EF; + WId WMFlag; //used to flag a running WM process + +public: + NativeEventFilter(); + ~NativeEventFilter(){} + + void start(); + void stop(); + +signals: + //Window Signals + void WindowCreated(WId); + void WindowDestroyed(WId); + void WindowPropertyChanged(WId, NativeWindow::Property); + void WindowPropertiesChanged(WId, QList); + void WindowPropertyChanged(WId, NativeWindow::Property, QVariant); + void WindowPropertiesChanged(WId, QList, QList); + void RequestWindowPropertyChange(WId, NativeWindow::Property, QVariant); + void RequestWindowPropertiesChange(WId, QList, QList); + + //System Tray Signals + void TrayWindowCreated(WId); + void TrayWindowDestroyed(WId); + + //Miscellaneos Signals + void PossibleDamageEvent(WId); + + //Input Event Signals + void KeyPressed(int, WId); + void KeyReleased(int, WId); + void MousePressed(int, WId); + void MouseReleased(int, WId); + void MouseMovement(); + void MouseEnterWindow(WId); + void MouseLeaveWindow(WId); +}; + +class EventFilter : public QAbstractNativeEventFilter{ +public: + EventFilter(NativeEventFilter *parent); + ~EventFilter(){} + + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *); + +private: + NativeEventFilter *obj; +}; + +#endif diff --git a/src-qt5/src-cpp/NativeKeyToQt.cpp b/src-qt5/src-cpp/NativeKeyToQt.cpp new file mode 100644 index 00000000..06056be7 --- /dev/null +++ b/src-qt5/src-cpp/NativeKeyToQt.cpp @@ -0,0 +1,528 @@ + +#include + +#include +#include + +// XCB/X11 Includes +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_LATIN8 +#define XK_LATIN9 +//NOTE: Look at the keysymdef.h file for additional define/characters which we may need later +#include +#include + + +//Small simplification functions +Qt::Key NativeWindowSystem::KeycodeToQt(int keycode){ + static xcb_key_symbols_t *SYM = 0; + if(SYM==0){ SYM = xcb_key_symbols_alloc(QX11Info::connection()); } + xcb_keysym_t symbol = xcb_key_symbols_get_keysym(SYM, keycode,0); + //not sure about the "column" input - we want raw keys though so ignore the "modified" key states (columns) for now + //qDebug() << "Try to convert keycode to Qt::Key:" << keycode << symbol; + //Now map this symbol to the appropriate Qt::Key enumeration + switch(symbol){ + //FUNCTION KEYS + case XK_F1: return Qt::Key_F1; + case XK_F2: return Qt::Key_F2; + case XK_F3: return Qt::Key_F3; + case XK_F4: return Qt::Key_F4; + case XK_F5: return Qt::Key_F5; + case XK_F6: return Qt::Key_F6; + case XK_F7: return Qt::Key_F7; + case XK_F8: return Qt::Key_F8; + case XK_F9: return Qt::Key_F9; + case XK_F10: return Qt::Key_F10; + case XK_F11: return Qt::Key_F11; + case XK_F12: return Qt::Key_F12; + case XK_F13: return Qt::Key_F13; + case XK_F14: return Qt::Key_F14; + case XK_F15: return Qt::Key_F15; + case XK_F16: return Qt::Key_F16; + case XK_F17: return Qt::Key_F17; + case XK_F18: return Qt::Key_F18; + case XK_F19: return Qt::Key_F19; + case XK_F20: return Qt::Key_F20; + case XK_F21: return Qt::Key_F21; + case XK_F22: return Qt::Key_F22; + case XK_F23: return Qt::Key_F23; + case XK_F24: return Qt::Key_F24; + case XK_F25: return Qt::Key_F25; + case XK_F26: return Qt::Key_F26; + case XK_F27: return Qt::Key_F27; + case XK_F28: return Qt::Key_F28; + case XK_F29: return Qt::Key_F29; + case XK_F30: return Qt::Key_F30; + case XK_F31: return Qt::Key_F31; + case XK_F32: return Qt::Key_F32; + case XK_F33: return Qt::Key_F33; + case XK_F34: return Qt::Key_F34; + case XK_F35: return Qt::Key_F35; + //Miscellaneous Keys + case XK_BackSpace: return Qt::Key_Backspace; + case XK_Delete: return Qt::Key_Delete; + //case XK_LineFeed: return Qt::Key_Backspace; + case XK_Clear: return Qt::Key_Clear; + case XK_Return: return Qt::Key_Return; + case XK_Pause: return Qt::Key_Pause; + case XK_Scroll_Lock: return Qt::Key_ScrollLock; + case XK_Sys_Req: return Qt::Key_SysReq; + case XK_Escape: return Qt::Key_Escape; + case XK_Select: return Qt::Key_Select; + case XK_Print: return Qt::Key_Print; + //case XK_Execute: return Qt::Key_Execute; + case XK_Insert: return Qt::Key_Insert; + case XK_Undo: return Qt::Key_Undo; + case XK_Redo: return Qt::Key_Redo; + case XK_Menu: return Qt::Key_Menu; + case XK_Find: return Qt::Key_Find; + case XK_Cancel: return Qt::Key_Cancel; + case XK_Help: return Qt::Key_Help; + //case XK_Break: return Qt::Key_Break; + //case XK_Mode_switch: return Qt::Key_Backspace; + //case XK_script_switch: return Qt::Key_Backspace; + case XK_Num_Lock: return Qt::Key_NumLock; + //Cursor Controls + case XK_Home: return Qt::Key_Home; + case XK_Left: return Qt::Key_Left; + case XK_Up: return Qt::Key_Up; + case XK_Right: return Qt::Key_Right; + case XK_Down: return Qt::Key_Down; + //case XK_Prior: return Qt::Key_Backspace; + case XK_Page_Up: return Qt::Key_PageUp; + case XK_Page_Down: return Qt::Key_PageDown; + //case XK_Next: return Qt::Key_Backspace; + case XK_End: return Qt::Key_End; + //case XK_Begin: return Qt::Key_Backspace; + // Keypad Functions and numbers + case XK_KP_Space: return Qt::Key_Space; + case XK_KP_Tab: return Qt::Key_Tab; + case XK_KP_Enter: return Qt::Key_Enter; + case XK_KP_F1: return Qt::Key_F1; + case XK_KP_F2: return Qt::Key_F2; + case XK_KP_F3: return Qt::Key_F3; + case XK_KP_F4: return Qt::Key_F4; + case XK_KP_Home: return Qt::Key_Home; + case XK_KP_Left: return Qt::Key_Left; + case XK_KP_Up: return Qt::Key_Up; + case XK_KP_Right: return Qt::Key_Right; + case XK_KP_Down: return Qt::Key_Down; + //case XK_KP_Prior: return Qt::Key_ + case XK_KP_Page_Up: return Qt::Key_PageUp; + //case XK_KP_Next: return Qt::Key_ + case XK_KP_Page_Down: return Qt::Key_PageDown; + case XK_KP_End: return Qt::Key_End; + //case XK_KP_Begin: return Qt::Key_ + case XK_KP_Insert: return Qt::Key_Insert; + case XK_KP_Delete: return Qt::Key_Delete; + case XK_KP_Equal: return Qt::Key_Equal; + case XK_KP_Multiply: return Qt::Key_Asterisk; + case XK_KP_Add: return Qt::Key_Plus; + case XK_KP_Separator: return Qt::Key_Comma; //X11 definitions say this is often comma + case XK_KP_Subtract: return Qt::Key_Minus; + case XK_KP_Decimal: return Qt::Key_Period; + case XK_KP_Divide: return Qt::Key_Slash; + case XK_KP_0: return Qt::Key_0; + case XK_KP_1: return Qt::Key_1; + case XK_KP_2: return Qt::Key_2; + case XK_KP_3: return Qt::Key_3; + case XK_KP_4: return Qt::Key_4; + case XK_KP_5: return Qt::Key_5; + case XK_KP_6: return Qt::Key_6; + case XK_KP_7: return Qt::Key_7; + case XK_KP_8: return Qt::Key_8; + case XK_KP_9: return Qt::Key_9; + // Modifier Keys + case XK_Shift_L: return Qt::Key_Shift; + case XK_Shift_R: return Qt::Key_Shift; + case XK_Control_L: return Qt::Key_Control; + case XK_Control_R: return Qt::Key_Control; + case XK_Caps_Lock: return Qt::Key_CapsLock; + //case XK_Shift_Lock: return Qt::Key_ShiftLock; + case XK_Meta_L: return Qt::Key_Meta; + case XK_Meta_R: return Qt::Key_Meta; + case XK_Alt_L: return Qt::Key_Alt; + case XK_Alt_R: return Qt::Key_Alt; + case XK_Super_L: return Qt::Key_Super_L; + case XK_Super_R: return Qt::Key_Super_R; + case XK_Hyper_L: return Qt::Key_Hyper_L; + case XK_Hyper_R: return Qt::Key_Hyper_R; + case XK_space: return Qt::Key_Space; + case XK_exclam: return Qt::Key_Exclam; + case XK_quotedbl: return Qt::Key_QuoteDbl; + case XK_numbersign: return Qt::Key_NumberSign; + case XK_dollar: return Qt::Key_Dollar; + case XK_percent: return Qt::Key_Percent; + case XK_ampersand: return Qt::Key_Ampersand; + case XK_apostrophe: return Qt::Key_Apostrophe; + case XK_parenleft: return Qt::Key_ParenLeft; + case XK_parenright: return Qt::Key_ParenRight; + case XK_asterisk: return Qt::Key_Asterisk; + case XK_plus: return Qt::Key_Plus; + case XK_comma: return Qt::Key_Comma; + case XK_minus: return Qt::Key_Minus; + case XK_period: return Qt::Key_Period; + case XK_slash: return Qt::Key_Slash; + case XK_0: return Qt::Key_0; + case XK_1: return Qt::Key_1; + case XK_2: return Qt::Key_2; + case XK_3: return Qt::Key_3; + case XK_4: return Qt::Key_4; + case XK_5: return Qt::Key_5; + case XK_6: return Qt::Key_6; + case XK_7: return Qt::Key_7; + case XK_8: return Qt::Key_8; + case XK_9: return Qt::Key_9; + case XK_colon: return Qt::Key_Colon; + case XK_semicolon: return Qt::Key_Semicolon; + case XK_less: return Qt::Key_Less; + case XK_equal: return Qt::Key_Equal; + case XK_greater: return Qt::Key_Greater; + case XK_question: return Qt::Key_Question; + case XK_at: return Qt::Key_At; + case XK_A: return Qt::Key_A; + case XK_B: return Qt::Key_B; + case XK_C: return Qt::Key_C; + case XK_D: return Qt::Key_D; + case XK_E: return Qt::Key_E; + case XK_F: return Qt::Key_F; + case XK_G: return Qt::Key_G; + case XK_H: return Qt::Key_H; + case XK_I: return Qt::Key_I; + case XK_J: return Qt::Key_J; + case XK_K: return Qt::Key_K; + case XK_L: return Qt::Key_L; + case XK_M: return Qt::Key_M; + case XK_N: return Qt::Key_N; + case XK_O: return Qt::Key_O; + case XK_P: return Qt::Key_P; + case XK_Q: return Qt::Key_Q; + case XK_R: return Qt::Key_R; + case XK_S: return Qt::Key_S; + case XK_T: return Qt::Key_T; + case XK_U: return Qt::Key_U; + case XK_V: return Qt::Key_V; + case XK_W: return Qt::Key_W; + case XK_X: return Qt::Key_X; + case XK_Y : return Qt::Key_Y; + case XK_Z: return Qt::Key_Z; + case XK_bracketleft: return Qt::Key_BracketLeft; + case XK_backslash: return Qt::Key_Backslash; + case XK_bracketright: return Qt::Key_BracketRight; + case XK_asciicircum: return Qt::Key_AsciiCircum; + case XK_underscore: return Qt::Key_Underscore; + case XK_grave: return Qt::Key_Agrave; + case XK_a: return Qt::Key_A; + case XK_b: return Qt::Key_B; + case XK_c: return Qt::Key_C; + case XK_d: return Qt::Key_D; + case XK_e: return Qt::Key_E; + case XK_f : return Qt::Key_F; + case XK_g: return Qt::Key_G; + case XK_h: return Qt::Key_H; + case XK_i: return Qt::Key_I; + case XK_j: return Qt::Key_J; + case XK_k: return Qt::Key_K; + case XK_l: return Qt::Key_L; + case XK_m: return Qt::Key_M; + case XK_n: return Qt::Key_N; + case XK_o: return Qt::Key_O; + case XK_p: return Qt::Key_P; + case XK_q: return Qt::Key_Q; + case XK_r: return Qt::Key_R; + case XK_s: return Qt::Key_S; + case XK_t : return Qt::Key_T; + case XK_u: return Qt::Key_U; + case XK_v: return Qt::Key_V; + case XK_w: return Qt::Key_W; + case XK_x: return Qt::Key_X; + case XK_y: return Qt::Key_Y; + case XK_z: return Qt::Key_Z; + case XK_braceleft: return Qt::Key_BraceLeft; + case XK_bar: return Qt::Key_Bar; + case XK_braceright: return Qt::Key_BraceRight; + case XK_asciitilde: return Qt::Key_AsciiTilde; + + case XK_nobreakspace: return Qt::Key_nobreakspace; + case XK_exclamdown: return Qt::Key_exclamdown; + case XK_cent: return Qt::Key_cent; + case XK_sterling: return Qt::Key_sterling; + case XK_currency: return Qt::Key_currency; + case XK_yen: return Qt::Key_yen; + case XK_brokenbar: return Qt::Key_brokenbar; + case XK_section: return Qt::Key_section; + case XK_diaeresis: return Qt::Key_diaeresis; + case XK_copyright: return Qt::Key_copyright; + case XK_ordfeminine: return Qt::Key_ordfeminine; + case XK_guillemotleft: return Qt::Key_guillemotleft; + case XK_notsign: return Qt::Key_notsign; + case XK_hyphen: return Qt::Key_hyphen; + case XK_registered: return Qt::Key_registered; + case XK_macron: return Qt::Key_macron; + case XK_degree: return Qt::Key_degree; + case XK_plusminus: return Qt::Key_plusminus; + case XK_twosuperior: return Qt::Key_twosuperior; + case XK_threesuperior: return Qt::Key_threesuperior; + case XK_acute: return Qt::Key_acute; + case XK_mu: return Qt::Key_mu; + case XK_paragraph: return Qt::Key_paragraph; + case XK_periodcentered: return Qt::Key_periodcentered; + case XK_cedilla: return Qt::Key_cedilla; + case XK_onesuperior: return Qt::Key_onesuperior; + case XK_masculine: return Qt::Key_masculine; + case XK_guillemotright: return Qt::Key_guillemotright; + case XK_onequarter: return Qt::Key_onequarter; + case XK_onehalf: return Qt::Key_onehalf; + case XK_threequarters: return Qt::Key_threequarters; + case XK_questiondown: return Qt::Key_questiondown; + case XK_Agrave: return Qt::Key_Agrave; + case XK_Aacute: return Qt::Key_Aacute; + case XK_Acircumflex: return Qt::Key_Acircumflex; + case XK_Atilde: return Qt::Key_Atilde; + case XK_Adiaeresis: return Qt::Key_Adiaeresis; + case XK_Aring: return Qt::Key_Aring; + case XK_AE: return Qt::Key_AE; + case XK_Ccedilla: return Qt::Key_Ccedilla; + case XK_Egrave: return Qt::Key_Egrave; + case XK_Eacute: return Qt::Key_Eacute; + case XK_Ecircumflex: return Qt::Key_Ecircumflex; + case XK_Ediaeresis: return Qt::Key_Ediaeresis; + case XK_Igrave: return Qt::Key_Igrave; + case XK_Iacute: return Qt::Key_Iacute; + case XK_Icircumflex: return Qt::Key_Icircumflex; + case XK_Idiaeresis: return Qt::Key_Idiaeresis; + case XK_ETH: return Qt::Key_ETH; + //case XK_Eth: return Qt::Key_Eth; + case XK_Ntilde: return Qt::Key_Ntilde; + case XK_Ograve: return Qt::Key_Ograve; + case XK_Oacute: return Qt::Key_Oacute; + case XK_Ocircumflex: return Qt::Key_Ocircumflex; + case XK_Otilde: return Qt::Key_Otilde; + case XK_Odiaeresis: return Qt::Key_Odiaeresis; + case XK_multiply: return Qt::Key_multiply; + //case XK_Oslash: return Qt::Key_AsciiTilde; + case XK_Ooblique: return Qt::Key_Ooblique; + case XK_Ugrave: return Qt::Key_Ugrave; + case XK_Uacute: return Qt::Key_Uacute; + case XK_Ucircumflex: return Qt::Key_Ucircumflex; + case XK_Udiaeresis: return Qt::Key_Udiaeresis; + case XK_Yacute: return Qt::Key_Yacute; + case XK_THORN: return Qt::Key_THORN; + //case XK_Thorn: return Qt::Key_AsciiTilde; + case XK_ssharp: return Qt::Key_ssharp; + /*case XK_agrave: return Qt::Key_AsciiTilde; + case XK_aacute: return Qt::Key_AsciiTilde; + case XK_acircumflex: return Qt::Key_AsciiTilde; + case XK_atilde: return Qt::Key_AsciiTilde; + case XK_adiaeresis: return Qt::Key_AsciiTilde; + case XK_aring: return Qt::Key_AsciiTilde; + case XK_ae: return Qt::Key_AsciiTilde; + case XK_ccedilla: return Qt::Key_AsciiTilde; + case XK_egrave: return Qt::Key_AsciiTilde; + case XK_eacute: return Qt::Key_AsciiTilde; + case XK_ecircumflex: return Qt::Key_AsciiTilde; + case XK_ediaeresis: return Qt::Key_AsciiTilde; + case XK_igrave: return Qt::Key_AsciiTilde; + case XK_iacute: return Qt::Key_AsciiTilde; + case XK_icircumflex: return Qt::Key_AsciiTilde; + case XK_idiaeresis: return Qt::Key_AsciiTilde; + case XK_eth: return Qt::Key_AsciiTilde; + case XK_ntilde: return Qt::Key_AsciiTilde; + case XK_ograve: return Qt::Key_AsciiTilde; + case XK_oacute: return Qt::Key_AsciiTilde; + case XK_ocircumflex: return Qt::Key_AsciiTilde; + case XK_otilde: return Qt::Key_AsciiTilde; + case XK_odiaeresis: return Qt::Key_AsciiTilde; + case XK_division: return Qt::Key_AsciiTilde; + case XK_oslash: return Qt::Key_AsciiTilde; + case XK_ooblique: return Qt::Key_AsciiTilde; + case XK_ugrave: return Qt::Key_AsciiTilde; + case XK_uacute: return Qt::Key_AsciiTilde; + case XK_ucircumflex: return Qt::Key_AsciiTilde; + case XK_udiaeresis: return Qt::Key_AsciiTilde; + case XK_yacute: return Qt::Key_AsciiTilde; + case XK_thorn: return Qt::Key_AsciiTilde; + case XK_ydiaeresis: return Qt::Key_AsciiTilde; + + case: XK_Agonek: return Qt::Key_AsciiTilde; + case XK_breve: return Qt::Key_AsciiTilde; + case XK_Lstroke: return Qt::Key_AsciiTilde; + case XK_Lcaron: return Qt::Key_AsciiTilde; + case XK_Sacute: return Qt::Key_AsciiTilde; + case XK_Scaron: return Qt::Key_AsciiTilde; + case XK_Scedilla: return Qt::Key_AsciiTilde; + case XK_Tcaron: return Qt::Key_AsciiTilde; + case XK_Zacute: return Qt::Key_AsciiTilde; + case XK_Zcaron: return Qt::Key_AsciiTilde; + case XK_Zabovedot: return Qt::Key_AsciiTilde; + case XK_aogonek: return Qt::Key_AsciiTilde; + case XK_ogonek: return Qt::Key_AsciiTilde; + case XK_lstroke: return Qt::Key_AsciiTilde; + case XK_lcaron: return Qt::Key_AsciiTilde; + case XK_sacute: return Qt::Key_AsciiTilde; + case XK_caron: return Qt::Key_AsciiTilde; + case XK_scaron: return Qt::Key_AsciiTilde; + case XK_scedilla: return Qt::Key_AsciiTilde; + case XK_tcaron: return Qt::Key_AsciiTilde; + case XK_zacute: return Qt::Key_AsciiTilde; + case XK_doubleacute: return Qt::Key_AsciiTilde; + case XK_zcaron: return Qt::Key_AsciiTilde; + case XK_zabovedot: return Qt::Key_AsciiTilde; + case XK_Racute: return Qt::Key_AsciiTilde; + case XK_Abreve: return Qt::Key_AsciiTilde; + case XK_Lacute: return Qt::Key_AsciiTilde; + case XK_Cacute: return Qt::Key_AsciiTilde; + case XK_Ccaron: return Qt::Key_AsciiTilde; + case XK_Eogonek: return Qt::Key_AsciiTilde; + case XK_Ecaron: return Qt::Key_AsciiTilde; + case XK_Dcaron: return Qt::Key_AsciiTilde; + case XK_Dstroke: return Qt::Key_AsciiTilde; + case XK_Nacute: return Qt::Key_AsciiTilde; + case XK_Ncaron: return Qt::Key_AsciiTilde; + case XK_Odoubleacute: return Qt::Key_AsciiTilde; + case XK_Rcaron: return Qt::Key_AsciiTilde; + case XK_Uring: return Qt::Key_AsciiTilde; + case XK_Udoubleacute: return Qt::Key_AsciiTilde; + case XK_Tcedilla: return Qt::Key_AsciiTilde; + case XK_racute: return Qt::Key_AsciiTilde; + case XK_abreve: return Qt::Key_AsciiTilde; + case XK_lacute: return Qt::Key_AsciiTilde; + case XK_cacute: return Qt::Key_AsciiTilde; + case XK_ccaron: return Qt::Key_AsciiTilde; + case XK_eogonek: return Qt::Key_AsciiTilde; + case XK_ecaron: return Qt::Key_AsciiTilde; + case XK_dcaron: return Qt::Key_AsciiTilde; + case XK_dstroke: return Qt::Key_AsciiTilde; + case XK_nacute: return Qt::Key_AsciiTilde; + case XK_ncaron: return Qt::Key_AsciiTilde; + case XK_odoubleacute: return Qt::Key_AsciiTilde; + case XK_rcaron: return Qt::Key_AsciiTilde; + case XK_uring: return Qt::Key_AsciiTilde; + case XK_udoubleacute: return Qt::Key_AsciiTilde; + case XK_tcedilla: return Qt::Key_AsciiTilde; + case XK_abovedot: return Qt::Key_AsciiTilde; + case XK_Hstroke: return Qt::Key_AsciiTilde; + case XK_Hcircumflex: return Qt::Key_AsciiTilde; + case XK_Iabovedot: return Qt::Key_AsciiTilde; + case XK_Gbreve: return Qt::Key_AsciiTilde; + case XK_Jcircumflex: return Qt::Key_AsciiTilde; + case XK_hstroke: return Qt::Key_AsciiTilde; + case XK_hcircumflex: return Qt::Key_AsciiTilde; + case XK_idotless: return Qt::Key_AsciiTilde; + case XK_gbreve: return Qt::Key_AsciiTilde; + case XK_jcircumflex: return Qt::Key_AsciiTilde; + case XK_Cabovedot: return Qt::Key_AsciiTilde; + case XK_Ccircumflex: return Qt::Key_AsciiTilde; + case XK_Gabovedot: return Qt::Key_AsciiTilde; + case XK_Gcircumflex: return Qt::Key_AsciiTilde; + case XK_Ubreve: return Qt::Key_AsciiTilde; + case XK_Scircumflex: return Qt::Key_AsciiTilde; + case XK_cabovedot: return Qt::Key_AsciiTilde; + case XK_ccircumflex: return Qt::Key_AsciiTilde; + case XK_gabovedot: return Qt::Key_AsciiTilde; + case XK_gcircumflex: return Qt::Key_AsciiTilde; + case XK_ubreve: return Qt::Key_AsciiTilde; + case XK_scircumflex: return Qt::Key_AsciiTilde; + case XK_kra: return Qt::Key_AsciiTilde; + case XK_kappa: return Qt::Key_AsciiTilde; + case XK_Rcedilla: return Qt::Key_AsciiTilde; + case XK_Itilde: return Qt::Key_AsciiTilde; + case XK_Lcedilla: return Qt::Key_AsciiTilde; + case XK_Emacron: return Qt::Key_AsciiTilde; + case XK_Gcedilla: return Qt::Key_AsciiTilde; + case XK_Tslash: return Qt::Key_AsciiTilde; + case XK_rcedilla: return Qt::Key_AsciiTilde; + case XK_itilde: return Qt::Key_AsciiTilde; + case XK_lcedilla: return Qt::Key_AsciiTilde; + case XK_emacron: return Qt::Key_AsciiTilde; + case XK_gcedilla: return Qt::Key_AsciiTilde; + case XK_tslash: return Qt::Key_AsciiTilde; + case XK_ENG: return Qt::Key_AsciiTilde; + case XK_eng: return Qt::Key_AsciiTilde; + case XK_Amacron: return Qt::Key_AsciiTilde; + case XK_Iogonek: return Qt::Key_AsciiTilde; + case XK_Eabovedot: return Qt::Key_AsciiTilde; + case XK_Imacron: return Qt::Key_AsciiTilde; + case XK_Ncedilla: return Qt::Key_AsciiTilde; + case XK_Omacron: return Qt::Key_AsciiTilde; + case XK_Kcedilla: return Qt::Key_AsciiTilde; + case XK_Uogonek: return Qt::Key_AsciiTilde; + case XK_Utilde: return Qt::Key_AsciiTilde; + case XK_Umacron: return Qt::Key_AsciiTilde; + case XK_amacron: return Qt::Key_AsciiTilde; + case XK_iogonek: return Qt::Key_AsciiTilde; + case XK_eabovedot: return Qt::Key_AsciiTilde; + case XK_imacron: return Qt::Key_AsciiTilde; + case XK_ncedilla: return Qt::Key_AsciiTilde; + case XK_omacron: return Qt::Key_AsciiTilde; + case XK_kcedilla: return Qt::Key_AsciiTilde; + case XK_uogonek: return Qt::Key_AsciiTilde; + case XK_utilde: return Qt::Key_AsciiTilde; + case XK_umacron: return Qt::Key_AsciiTilde; + case XK_Wcircumflex: return Qt::Key_AsciiTilde; + case XK_wcircumflex: return Qt::Key_AsciiTilde; + case XK_Ycircumflex: return Qt::Key_AsciiTilde; + case XK_ycircumflex: return Qt::Key_AsciiTilde; + case XK_Babovedot: return Qt::Key_AsciiTilde; + case XK_babovedot: return Qt::Key_AsciiTilde; + case XK_Dabovedot: return Qt::Key_AsciiTilde; + case XK_dabovedot: return Qt::Key_AsciiTilde; + case XK_Fabovedot: return Qt::Key_AsciiTilde; + case XK_fabovedot: return Qt::Key_AsciiTilde; + case XK_Mabovedot: return Qt::Key_AsciiTilde; + case XK_mabovedot: return Qt::Key_AsciiTilde; + case XK_Pabovedot: return Qt::Key_AsciiTilde; + case XK_pabovedot: return Qt::Key_AsciiTilde; + case XK_Sabovedot: return Qt::Key_AsciiTilde; + case XK_sabovedot: return Qt::Key_AsciiTilde; + case XK_Tabovedot: return Qt::Key_AsciiTilde; + case XK_tabovedot: return Qt::Key_AsciiTilde; + case XK_Wgrave: return Qt::Key_AsciiTilde; + case XK_wgrave: return Qt::Key_AsciiTilde; + case XK_Wacute: return Qt::Key_AsciiTilde; + case XK_wacute: return Qt::Key_AsciiTilde; + case XK_Wdiaeresis: return Qt::Key_AsciiTilde; + case XK_wdiaeresis: return Qt::Key_AsciiTilde; + case XK_Ygrave: return Qt::Key_AsciiTilde; + case XK_ygrave: return Qt::Key_AsciiTilde; + case XK_OE: return Qt::Key_AsciiTilde; + case XK_oe: return Qt::Key_AsciiTilde; + case XK_Ydiaeresis: return Qt::Key_AsciiTilde;*/ + default: + qDebug() << "Unknown Key"; + } + qDebug() << " -- Simple Qt Map:" << (Qt::Key)(symbol); + qDebug() << " -- Key Sequence Map:" << QKeySequence(symbol); + qDebug() << " - Not implemented yet"; + return Qt::Key_unknown; +} + +NativeWindowSystem::MouseButton NativeWindowSystem::MouseToQt(int keycode){ + switch(keycode){ + case 1: + return NativeWindowSystem::LeftButton; + case 3: + return NativeWindowSystem::RightButton; + case 2: + return NativeWindowSystem::MidButton; + case 4: + return NativeWindowSystem::WheelUp; + case 5: + return NativeWindowSystem::WheelDown; + case 6: + return NativeWindowSystem::WheelLeft; + case 7: + return NativeWindowSystem::WheelRight; + case 8: + return NativeWindowSystem::BackButton; //Not sure if this is correct yet (1/27/17) + case 9: + return NativeWindowSystem::ForwardButton; //Not sure if this is correct yet (1/27/17) + default: + return NativeWindowSystem::NoButton; + } +} diff --git a/src-qt5/src-cpp/NativeWindow.cpp b/src-qt5/src-cpp/NativeWindow.cpp new file mode 100644 index 00000000..02cc001e --- /dev/null +++ b/src-qt5/src-cpp/NativeWindow.cpp @@ -0,0 +1,123 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "NativeWindow.h" + +#include + +// === PUBLIC === +NativeWindow::NativeWindow(WId id) : QObject(){ + winid = id; + frameid = 0; + dmgID = 0; +} + +NativeWindow::~NativeWindow(){ + hash.clear(); +} + +void NativeWindow::addFrameWinID(WId fid){ + frameid = fid; +} + +void NativeWindow::addDamageID(unsigned int dmg){ + dmgID = dmg; +} + +bool NativeWindow::isRelatedTo(WId tmp){ + return (relatedTo.contains(tmp) || winid == tmp || frameid == tmp); +} + +WId NativeWindow::id(){ + return winid; +} + +WId NativeWindow::frameId(){ + return frameid; +} + +unsigned int NativeWindow::damageId(){ + return dmgID; +} + +QVariant NativeWindow::property(NativeWindow::Property prop){ + if(hash.contains(prop)){ return hash.value(prop); } + else if(prop == NativeWindow::RelatedWindows){ return QVariant::fromValue(relatedTo); } + return QVariant(); //null variant +} + +void NativeWindow::setProperty(NativeWindow::Property prop, QVariant val, bool force){ + if(prop == NativeWindow::RelatedWindows){ relatedTo = val.value< QList >(); } + else if(prop == NativeWindow::None || (!force && hash.value(prop)==val)){ return; } + else{ hash.insert(prop, val); } + emit PropertiesChanged(QList() << prop, QList() << val); +} + +void NativeWindow::setProperties(QList props, QList vals, bool force){ + for(int i=0; i=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property + if(props[i] == NativeWindow::None || (!force && (hash.value(props[i]) == vals[i])) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value + hash.insert(props[i], vals[i]); + } + emit PropertiesChanged(props, vals); +} + +void NativeWindow::requestProperty(NativeWindow::Property prop, QVariant val, bool force){ + if(prop == NativeWindow::None || prop == NativeWindow::RelatedWindows || (!force && hash.value(prop)==val) ){ return; } + emit RequestPropertiesChange(winid, QList() << prop, QList() << val); +} + +void NativeWindow::requestProperties(QList props, QList vals, bool force){ + //Verify/adjust inputs as needed + for(int i=0; i=vals.length()){ props.removeAt(i); i--; continue; } //no corresponding value for this property + if(props[i] == NativeWindow::None || props[i] == NativeWindow::RelatedWindows || (!force && hash.value(props[i])==vals[i]) ){ props.removeAt(i); vals.removeAt(i); i--; continue; } //Invalid property or identical value + /*if( (props[i] == NativeWindow::Visible || props[i] == NativeWindow::Active) && frameid !=0){ + //These particular properties needs to change the frame - not the window itself + emit RequestPropertiesChange(frameid, QList() << props[i], QList() << vals[i]); + props.removeAt(i); vals.removeAt(i); i--; + }*/ + } + emit RequestPropertiesChange(winid, props, vals); +} + +QRect NativeWindow::geometry(){ + //Calculate the "full" geometry of the window + frame (if any) + //Check that the size is between the min/max limitations + QSize size = hash.value(NativeWindow::Size).toSize(); + QSize min = hash.value(NativeWindow::MinSize).toSize(); + QSize max = hash.value(NativeWindow::MaxSize).toSize(); + if(min.isValid() && min.width() > size.width() ){ size.setWidth(min.width()); } + if(min.isValid() && min.height() > size.height()){ size.setHeight(min.height()); } + if(max.isValid() && max.width() < size.width() && max.width()>min.width()){ size.setWidth(max.width()); } + if(max.isValid() && max.height() < size.height() && max.height()>min.height()){ size.setHeight(max.height()); } + //Assemble the full geometry + QRect geom( hash.value(NativeWindow::GlobalPos).toPoint(), size ); + //Now adjust the window geom by the frame margins + QList frame = hash.value(NativeWindow::FrameExtents).value< QList >(); //Left,Right,Top,Bottom + //qDebug() << "Calculate Geometry:" << geom << frame; + if(frame.length()==4){ + geom = geom.adjusted( -frame[0], -frame[2], frame[1], frame[3] ); + } + //qDebug() << " - Total:" << geom; + return geom; +} +// ==== PUBLIC SLOTS === +void NativeWindow::toggleVisibility(){ + setProperty(NativeWindow::Visible, !property(NativeWindow::Visible).toBool() ); +} + +void NativeWindow::requestClose(){ + emit RequestClose(winid); +} + +void NativeWindow::requestKill(){ + emit RequestKill(winid); +} + +void NativeWindow::requestPing(){ + emit RequestPing(winid); +} diff --git a/src-qt5/src-cpp/NativeWindow.h b/src-qt5/src-cpp/NativeWindow.h new file mode 100644 index 00000000..67436259 --- /dev/null +++ b/src-qt5/src-cpp/NativeWindow.h @@ -0,0 +1,118 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is a container object for setting/announcing changes +// in a native window's properties. +// The WM will usually run the "setProperty" function on this object, +// and any other classes/widgets which watch this window can act appropriatly after-the-fact +// Non-WM classes should use the "Request" signals to ask the WM to do something, and listen for changes later +//=========================================== +#ifndef _LUMINA_DESKTOP_NATIVE_WINDOW_H +#define _LUMINA_DESKTOP_NATIVE_WINDOW_H + +#include +#include +#include +#include +#include +#include +#include + +class NativeWindow : public QObject{ + Q_OBJECT +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 Property{ /*QVariant Type*/ + None=0, /*null*/ + MinSize=1, /*QSize*/ + MaxSize=2, /*QSize*/ + Size=3, /*QSize*/ + GlobalPos=4, /*QPoint*/ + Title=5, /*QString*/ + ShortTitle=6, /*QString*/ + Icon=7, /*QIcon*/ + Name=8, /*QString*/ + Workspace=9, /*int*/ + States=10, /*QList : Current state of the window */ + WinTypes=11, /*QList : Current type of window (typically does not change)*/ + WinActions=12, /*QList : Current actions that the window allows (Managed/set by the WM)*/ + FrameExtents=13, /*QList : [Left, Right, Top, Bottom] in pixels */ + RelatedWindows=14, /* QList - better to use the "isRelatedTo(WId)" function instead of reading this directly*/ + Active=15, /*bool*/ + Visible=16 /*bool*/ + }; + + static QList allProperties(){ + //Return all the available properties (excluding "None" and "FrameExtents" (WM control only) ) + QList props; + props << MinSize << MaxSize << Size << GlobalPos << Title << ShortTitle << Icon << Name << Workspace \ + << States << WinTypes << WinActions << RelatedWindows << Active << Visible; + return props; + }; + + NativeWindow(WId id); + ~NativeWindow(); + + void addFrameWinID(WId); + void addDamageID(unsigned int); + bool isRelatedTo(WId); + + WId id(); + WId frameId(); + unsigned int damageId(); + + //QWindow* window(); + + QVariant property(NativeWindow::Property); + void setProperty(NativeWindow::Property, QVariant, bool force = false); + void setProperties(QList, QList, bool force = false); + void requestProperty(NativeWindow::Property, QVariant, bool force = false); + void requestProperties(QList, QList, bool force = false); + + QRect geometry(); //this returns the "full" geometry of the window (window + frame) + +public slots: + void toggleVisibility(); + void requestClose(); //ask the app to close the window (may/not depending on activity) + void requestKill(); //ask the WM to kill the app associated with this window (harsh - only use if not responding) + void requestPing(); //ask the app if it is still active (a WindowNotResponding signal will get sent out if there is no reply); + +private: + QHash hash; + //QWindow *WIN; + WId winid, frameid; + QList relatedTo; + unsigned int dmgID; + +signals: + //General Notifications + void PropertiesChanged(QList, QList); + void RequestPropertiesChange(WId, QList, QList); + 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 NativeWindow id() + void RequestClose(WId); //Close the window + void RequestKill(WId); //Kill the window/app (usually from being unresponsive) + void RequestPing(WId); //Verify that the window is still active (such as not closing after a request + void RequestReparent(WId, WId, QPoint); //client window, frame window, relative origin point in frame + // System Tray Icon Embed/Unembed Requests + //void RequestEmbed(WId, QWidget*); + //void RequestUnEmbed(WId, QWidget*); +}; + +// Declare the enumerations as Qt MetaTypes +Q_DECLARE_METATYPE(NativeWindow::Type); +Q_DECLARE_METATYPE(NativeWindow::Action); +Q_DECLARE_METATYPE(NativeWindow::State); +Q_DECLARE_METATYPE(NativeWindow::Property); + +#endif diff --git a/src-qt5/src-cpp/NativeWindow.pri b/src-qt5/src-cpp/NativeWindow.pri new file mode 100644 index 00000000..c2ac0137 --- /dev/null +++ b/src-qt5/src-cpp/NativeWindow.pri @@ -0,0 +1,17 @@ + +# Files +QT *= x11extras +LIBS *= -lc -lxcb -lxcb-ewmh -lxcb-icccm -lxcb-image -lxcb-composite -lxcb-damage -lxcb-util -lxcb-keysyms -lXdamage + +SOURCES *= $${PWD}/NativeWindow.cpp \ + $${PWD}/NativeWindowSystem.cpp \ + $${PWD}/NativeKeyToQt.cpp \ + $${PWD}/NativeEventFilter.cpp \ + $${PWD}/NativeEmbedWidget.cpp + +HEADERS *= $${PWD}/NativeWindow.h \ + $${PWD}/NativeWindowSystem.h \ + $${PWD}/NativeEventFilter.h \ + $${PWD}/NativeEmbedWidget.h + +INCLUDEPATH *= $${PWD} diff --git a/src-qt5/src-cpp/NativeWindowSystem.cpp b/src-qt5/src-cpp/NativeWindowSystem.cpp new file mode 100644 index 00000000..e8e9655a --- /dev/null +++ b/src-qt5/src-cpp/NativeWindowSystem.cpp @@ -0,0 +1,986 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the XCB version of the NativeWindowSystem class, +// used for interacting with the X11 display system on BSD/Linux/Unix systems +//=========================================== +#include "NativeWindowSystem.h" + +//Additional Qt includes +#include +#include +#include +#include +#include +#include +#include + + +//XCB Library includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//XLib includes (XCB Damage lib does not appear to register for damage events properly) +#include + +//SYSTEM TRAY STANDARD DEFINITIONS +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 +#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + +#define URGENCYHINT (1L << 8) //For window urgency detection + +#define ROOT_WIN_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_BUTTON_PRESS | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_POINTER_MOTION | \ + XCB_EVENT_MASK_PROPERTY_CHANGE | \ + XCB_EVENT_MASK_FOCUS_CHANGE | \ + XCB_EVENT_MASK_ENTER_WINDOW) + +#define NORMAL_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ + XCB_EVENT_MASK_BUTTON_RELEASE | \ + XCB_EVENT_MASK_POINTER_MOTION | \ + XCB_EVENT_MASK_BUTTON_MOTION | \ + XCB_EVENT_MASK_EXPOSURE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_ENTER_WINDOW | \ + XCB_EVENT_MASK_PROPERTY_CHANGE | \ + XCB_EVENT_MASK_FOCUS_CHANGE) + +#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_FOCUS_CHANGE | \ + XCB_EVENT_MASK_POINTER_MOTION) + +#define FRAME_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ + XCB_EVENT_MASK_BUTTON_RELEASE | \ + XCB_EVENT_MASK_POINTER_MOTION | \ + XCB_EVENT_MASK_EXPOSURE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_ENTER_WINDOW) + +inline void registerClientEvents(WId id, bool client = true){ + uint32_t values[] = {XCB_NONE}; + values[0] = client ? CLIENT_EVENT_MASK : FRAME_EVENT_MASK ; + /*{ (XCB_EVENT_MASK_PROPERTY_CHANGE + | XCB_EVENT_MASK_BUTTON_PRESS + | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_POINTER_MOTION + | XCB_EVENT_MASK_BUTTON_MOTION + | XCB_EVENT_MASK_EXPOSURE + | XCB_EVENT_MASK_STRUCTURE_NOTIFY + | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT + | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY + | XCB_EVENT_MASK_ENTER_WINDOW) + };*/ + xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, values); +} + +/*inline void registerClientEvents(WId id){ + uint32_t value_list[1] = {NORMAL_WIN_EVENT_MASK}; + xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list); +}*/ + +//Internal XCB private objects class +class NativeWindowSystem::p_objects{ +public: + xcb_ewmh_connection_t EWMH; //This is where all the screen info and atoms are located + QHash ATOMS; + xcb_screen_t *root_screen; + xcb_window_t root_window, wm_window, tray_window; + + //Functions for setting up these objects as needed + bool init_ATOMS(){ + xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH); + if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){ + qDebug() << "Error with XCB atom initializations"; + return false; + } + + QStringList atoms; + atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS" << "_NET_WM_WINDOW_OPACITY" + << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION" << "_XEMBED" + << "_NET_SYSTEM_TRAY_VISUAL" << QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())); + //Create all the requests for the atoms + QList reply; + for(int i=0; iatom); + free(reply[i]); //done with this reply + }else{ + //Invalid atom - could not be created + qDebug() << "Could not initialize XCB atom:" << atoms[i]; + } + } //loop over reply + return (ATOMS.keys().length() == atoms.length()); + } + + WId getTransientFor(WId win){ + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_transient_for_unchecked(QX11Info::connection(), win); + xcb_window_t trans; + if(1!= xcb_icccm_get_wm_transient_for_reply(QX11Info::connection(), cookie, &trans, NULL) ){ + return win; //error in fetching transient window ID (or none found) + }else{ + return trans; + } +} + + bool register_wm(){ + uint32_t value_list[1] = {ROOT_WIN_EVENT_MASK}; + xcb_generic_error_t *status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), root_window, XCB_CW_EVENT_MASK, value_list)); + if(status!=0){ return false; } + uint32_t params[] = {1}; + wm_window = xcb_generate_id(QX11Info::connection()); //need a new ID + xcb_create_window(QX11Info::connection(), root_screen->root_depth, \ + wm_window, root_window, -1, -1, 1, 1, 0, \ + XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \ + XCB_CW_OVERRIDE_REDIRECT, params); + if(wm_window==0){ return false; } + //Set the _NET_SUPPORTING_WM property on the root window first + xcb_ewmh_set_supporting_wm_check(&EWMH, root_window, wm_window); + //Also set this property on the child window (pointing to itself) + xcb_ewmh_set_supporting_wm_check(&EWMH, wm_window, wm_window); + //Now also setup the root event mask on the wm_window + status = xcb_request_check( QX11Info::connection(), xcb_change_window_attributes_checked(QX11Info::connection(), wm_window, XCB_CW_EVENT_MASK, value_list)); + if(status!=0){ return false; } + return true; + } + + bool start_system_tray(){ + xcb_atom_t _NET_SYSTEM_TRAY_S = ATOMS.value( QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())) ); + //Make sure that there is no other system tray running + xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \ + xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL); + if(ownreply == 0){ + qWarning() << " - Could not get owner selection reply"; + return false; + }else if(ownreply->owner != 0){ + free(ownreply); + qWarning() << " - An alternate system tray is currently in use"; + return false; + } + free(ownreply); + //Now create the window to use (just offscreen) + tray_window = xcb_generate_id(QX11Info::connection()); //need a new ID + uint32_t params[] = {1}; + xcb_create_window(QX11Info::connection(), root_screen->root_depth, \ + tray_window, root_screen->root, -1, -1, 1, 1, 0, \ + XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \ + XCB_CW_OVERRIDE_REDIRECT, params); + //Now register this widget as the system tray + xcb_set_selection_owner(QX11Info::connection(), tray_window, _NET_SYSTEM_TRAY_S, XCB_CURRENT_TIME); + //Make sure that it was registered properly + ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \ + xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL); + if(ownreply==0 || ownreply->owner != tray_window){ + if(ownreply!=0){ free(ownreply); } + qWarning() << " - Could not register the system tray"; + xcb_destroy_window(QX11Info::connection(), tray_window); + return false; + } + free(ownreply); //done with structure + //Now register the orientation of the system tray + uint32_t orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; + xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \ + ATOMS.value("_NET_SYSTEM_TRAY_ORIENTATION"), XCB_ATOM_CARDINAL, 32, 1, &orient); + + //Now set the visual ID for the system tray (same as the root window, but TrueColor) + xcb_visualtype_t *type = xcb_aux_find_visual_by_attrs(root_screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32); + if(type!=0){ + xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, tray_window, \ + ATOMS.value("_NET_SYSTEM_TRAY_VISUAL"), XCB_ATOM_VISUALID, 32, 1, &type->visual_id); + }else{ + qWarning() << " - Could not set TrueColor visual for system tray"; + } + + //Finally, send out an X event letting others know that the system tray is up and running + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = root_screen->root; + event.type = EWMH.MANAGER; //MANAGER atom + event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; + event.data.data32[1] = _NET_SYSTEM_TRAY_S; //_NET_SYSTEM_TRAY_S atom + event.data.data32[2] = tray_window; + event.data.data32[3] = 0; + event.data.data32[4] = 0; + + xcb_send_event(QX11Info::connection(), 0, root_screen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + return true; + } + +}; //end private objects class + + +//inline functions for setting up the internal objects + + +// === PUBLIC === +NativeWindowSystem::NativeWindowSystem() : QObject(){ + obj = 0; + pingTimer = 0; + screenLocked = false; +} + +NativeWindowSystem::~NativeWindowSystem(){ + xcb_ewmh_connection_wipe(&(obj->EWMH)); + free(obj); +} + +//Overarching start/stop functions +bool NativeWindowSystem::start(){ + //Initialize the XCB/EWMH objects + if(obj==0){ + obj = new p_objects(); //instantiate the private objects + obj->wm_window = 0; + obj->tray_window = 0; + xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &obj->EWMH); + if(!xcb_ewmh_init_atoms_replies(&obj->EWMH, cookie, NULL) ){ + qDebug() << "Error with XCB atom initializations"; + return false; + } + obj->root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen()); + obj->root_window = obj->root_screen->root; //simplification for later - minor duplication of memory (unsigned int) + //Initialize all the extra atoms that the EWMH object does not have + if( !obj->init_ATOMS() ){ return false; } + } //Done with private object init + bool ok = obj->register_wm(); + if(ok){ + setRoot_supportedActions(); + ok = obj->start_system_tray(); + }else{ + qWarning() << "Could not register the WM"; + } + return ok; +} + +void NativeWindowSystem::stop(){ + +} + +// === PRIVATE === +NativeWindow* NativeWindowSystem::findWindow(WId id, bool checkRelated){ + //qDebug() << "Find Window:" << id; + for(int i=0; iid() ){ return NWindows[i]; } + else if(id==NWindows[i]->frameId() ){ return NWindows[i]; } + //if(checkRelated && NWindows[i]->isRelatedTo(id)){ return NWindows[i]; } + //else if(!checkRelated && id==NWindows[i]->id()){ return NWindows[i]; } + } + //Check to see if this is a transient for some other window + if(checkRelated){ + //WId tid = obj->getTransientFor(id); + //if(tid!=id){ return findWindow(tid, checkRelated); } //call it recursively as needed + //qDebug() << " -- Could not find Window!"; + } + return 0; +} + +NativeWindow* NativeWindowSystem::findTrayWindow(WId id){ + for(int i=0; iisRelatedTo(id)){ return TWindows[i]; } + } + return 0; +} + +void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props){ + //Put the properties in logical groups as appropriate (some XCB calls return multiple properties) + if(props.contains(NativeWindow::Title)){ + //Try the EWMH standards first + // _NET_WM_NAME + QString name; + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked(&obj->EWMH, win->id()); + if(cookie.sequence != 0){ + xcb_ewmh_get_utf8_strings_reply_t data; + if( 1 == xcb_ewmh_get_wm_name_reply(&obj->EWMH, cookie, &data, NULL) ){ + name = QString::fromUtf8(data.strings, data.strings_len); + } + } + if(name.isEmpty()){ + //_NET_WM_VISIBLE_NAME + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_name_unchecked(&obj->EWMH, win->id()); + if(cookie.sequence != 0){ + xcb_ewmh_get_utf8_strings_reply_t data; + if( 1 == xcb_ewmh_get_wm_visible_name_reply(&obj->EWMH, cookie, &data, NULL) ){ + name = QString::fromUtf8(data.strings, data.strings_len); + } + } + } + if(name.isEmpty()){ + //Now try the ICCCM standard + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_name_unchecked(QX11Info::connection(), win->id()); + xcb_icccm_get_text_property_reply_t reply; + if(1 == xcb_icccm_get_wm_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){ + name = QString::fromLocal8Bit(reply.name, reply.name_len); + xcb_icccm_get_text_property_reply_wipe(&reply); + } + } + win->setProperty(NativeWindow::Title, name); + } //end TITLE property + + if(props.contains(NativeWindow::ShortTitle)){ + //Try the EWMH standards first + // _NET_WM_ICON_NAME + QString name; + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name_unchecked(&obj->EWMH, win->id()); + if(cookie.sequence != 0){ + xcb_ewmh_get_utf8_strings_reply_t data; + if( 1 == xcb_ewmh_get_wm_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){ + name = QString::fromUtf8(data.strings, data.strings_len); + } + } + if(name.isEmpty()){ + //_NET_WM_VISIBLE_ICON_NAME + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_icon_name_unchecked(&obj->EWMH, win->id()); + if(cookie.sequence != 0){ + xcb_ewmh_get_utf8_strings_reply_t data; + if( 1 == xcb_ewmh_get_wm_visible_icon_name_reply(&obj->EWMH, cookie, &data, NULL) ){ + name = QString::fromUtf8(data.strings, data.strings_len); + } + } + } + if(name.isEmpty()){ + //Now try the ICCCM standard + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_icon_name_unchecked(QX11Info::connection(), win->id()); + xcb_icccm_get_text_property_reply_t reply; + if(1 == xcb_icccm_get_wm_icon_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){ + name = QString::fromLocal8Bit(reply.name, reply.name_len); + xcb_icccm_get_text_property_reply_wipe(&reply); + } + } + win->setProperty(NativeWindow::ShortTitle, name); + } //end SHORTTITLE property + + if(props.contains(NativeWindow::Icon)){ + //See if this is a tray icon first (different routine - entire app window is the icon) + QIcon icon; + if(win == findTrayWindow(win->id())){ + //Tray Icon Window + QPixmap pix; + //Get the current QScreen (for XCB->Qt conversion) + QList scrnlist = QApplication::screens(); + //Try to grab the given window directly with Qt + for(int i=0; igrabWindow(win->id()); + } + icon.addPixmap(pix); + }else{ + //Standard window + //Fetch the _NET_WM_ICON for the window and return it as a QIcon + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_unchecked(&obj->EWMH, win->id()); + xcb_ewmh_get_wm_icon_reply_t reply; + if(1 == xcb_ewmh_get_wm_icon_reply(&obj->EWMH, cookie, &reply, NULL)){ + xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&reply); + //Just use the first + bool done =false; + while(!done){ + //Now convert the current data into a Qt image + // - first 2 elements are width and height (removed via XCB functions) + // - data in rows from left to right and top to bottom + QImage image(iter.width, iter.height, QImage::Format_ARGB32); //initial setup + uint* dat = iter.data; + //dat+=2; //remember the first 2 element offset + for(int i=0; isetProperty(NativeWindow::Icon, icon); + } //end ICON property + + if(props.contains(NativeWindow::MinSize) || props.contains(NativeWindow::MaxSize) + || props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){ + //Try the ICCCM "Normal Hints" structure first (newer spec?) + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_normal_hints_unchecked(QX11Info::connection(), win->id()); + xcb_size_hints_t reply; + bool ok = false; + if(1==xcb_icccm_get_wm_normal_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; } + else{ + //Could not find normal hints, try the older "size hints" instead + cookie = xcb_icccm_get_wm_size_hints_unchecked(QX11Info::connection(), win->id(), XCB_ATOM_WM_SIZE_HINTS); + if(1==xcb_icccm_get_wm_size_hints_reply(QX11Info::connection(), cookie, &reply, NULL) ){ ok = true; } + } + if(ok){ + bool initsize = win->property(NativeWindow::Size).isNull(); //initial window size + if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_POSITION)==XCB_ICCCM_SIZE_HINT_US_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); } + if( (reply.flags&XCB_ICCCM_SIZE_HINT_US_SIZE)==XCB_ICCCM_SIZE_HINT_US_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); } + if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_POSITION)==XCB_ICCCM_SIZE_HINT_P_POSITION ){ win->setProperty(NativeWindow::GlobalPos, QPoint(reply.x,reply.y)); } + if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_SIZE)==XCB_ICCCM_SIZE_HINT_P_SIZE ){ win->setProperty(NativeWindow::Size, QSize(reply.width, reply.height)); } + if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MIN_SIZE)==XCB_ICCCM_SIZE_HINT_P_MIN_SIZE ){ win->setProperty(NativeWindow::MinSize, QSize(reply.min_width, reply.min_height)); } + if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)==XCB_ICCCM_SIZE_HINT_P_MAX_SIZE ){ win->setProperty(NativeWindow::MaxSize, QSize(reply.max_width, reply.max_height)); } + if( (reply.flags&XCB_ICCCM_SIZE_HINT_BASE_SIZE)==XCB_ICCCM_SIZE_HINT_BASE_SIZE && initsize ){ win->setProperty(NativeWindow::Size, QSize(reply.base_width, reply.base_height)); } + //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_RESIZE_INC)==XCB_ICCCM_SIZE_HINT_P_RESIZE_INC ){ hints.width_inc=reply.width_inc; hints.height_inc=reply.height_inc; } + //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_ASPECT)==XCB_ICCCM_SIZE_HINT_P_ASPECT ){ hints.min_aspect_num=reply.min_aspect_num; hints.min_aspect_den=reply.min_aspect_den; hints.max_aspect_num=reply.max_aspect_num; hints.max_aspect_den=reply.max_aspect_den;} + //if( (reply.flags&XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)==XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY ){ hints.win_gravity=reply.win_gravity; } + } + } //end of geometry properties + + if(props.contains(NativeWindow::Name)){ + //Put the app/class name here (much more static than the "Title" properties + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_class_unchecked(QX11Info::connection(), win->id()); + xcb_icccm_get_wm_class_reply_t reply; + if(1 == xcb_icccm_get_wm_class_reply(QX11Info::connection(), cookie, &reply, NULL) ){ + //Returns: "::::" + win->setProperty(NativeWindow::Name, ( QString::fromLocal8Bit(reply.instance_name)+"::::"+QString::fromLocal8Bit(reply.class_name) )); + xcb_icccm_get_wm_class_reply_wipe(&reply); + } + } //end NAME property + + if(props.contains(NativeWindow::Workspace)){ + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_desktop_unchecked(&obj->EWMH, win->id()); + uint32_t num = 0; + int wkspace = -1; + if(1==xcb_ewmh_get_wm_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){ + if(num!=0xFFFFFFFF){ wkspace = num; } + }/*else{ + //Error in fetching property (not set?) + // - put it on the current screen + out = WM_Get_Current_Desktop(); + }*/ + win->setProperty(NativeWindow::Workspace, wkspace); + } + if(props.contains(NativeWindow::FrameExtents)){ + //Just assign default values to this - need to automate it later + //win->setProperty(NativeWindow::FrameExtents, QVariant::fromValue >(QList() << 5 << 5 << 5+QFontMetrics(QFont()).height() << 5) ); + } + if(props.contains(NativeWindow::RelatedWindows)){ + WId orig = win->id(); + WId tid = obj->getTransientFor(orig); + QList list; + while(tid != orig){ + list << tid; + orig = tid; + tid = obj->getTransientFor(orig); + } + win->setProperty(NativeWindow::RelatedWindows, QVariant::fromValue(list)); + } + if(props.contains(NativeWindow::Visible)){ + xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), xcb_get_window_attributes(QX11Info::connection(), win->id()) , NULL); + if(attr != 0){ + win->setProperty(NativeWindow::Visible, attr->map_state == XCB_MAP_STATE_VIEWABLE); + free(attr); + } + } + if(props.contains(NativeWindow::WinTypes)){ + QList< NativeWindow::Type> types; + xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_window_type_unchecked(&obj->EWMH, win->id()); + xcb_ewmh_get_atoms_reply_t reply; + if(1==xcb_ewmh_get_wm_window_type_reply(&obj->EWMH, cookie, &reply, NULL) ){ + for(unsigned int i=0; iEWMH._NET_WM_WINDOW_TYPE_DESKTOP){ types << NativeWindow::T_DESKTOP; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DOCK){ types << NativeWindow::T_DOCK; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR){ types << NativeWindow::T_TOOLBAR; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_MENU){ types << NativeWindow::T_MENU; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY){ types << NativeWindow::T_UTILITY; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH){ types << NativeWindow::T_SPLASH; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG){ types << NativeWindow::T_DIALOG; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU){ types << NativeWindow::T_DROPDOWN_MENU; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU){ types << NativeWindow::T_POPUP_MENU; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP){ types << NativeWindow::T_TOOLTIP; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION){ types << NativeWindow::T_NOTIFICATION; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_COMBO){ types << NativeWindow::T_COMBO; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_DND){ types << NativeWindow::T_DND; } + else if(reply.atoms[i]==obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL){ types << NativeWindow::T_NORMAL; } + } + } + if(types.isEmpty()){ types << NativeWindow::T_NORMAL; } + win->setProperty(NativeWindow::WinTypes, QVariant::fromValue< QList >(types) ); + } +} + +void NativeWindowSystem::ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList vals){ + if(props.length() == 0 || vals.length()!=props.length() || win ==0 ){ return; } + //qDebug() << "Change Window Properties:" << props << vals; + if(props.contains(NativeWindow::Title)){ + + } + if(props.contains(NativeWindow::ShortTitle)){ + + } + if(props.contains(NativeWindow::Icon)){ + + } + if(props.contains(NativeWindow::Size) || props.contains(NativeWindow::GlobalPos) ){ + /*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(NativeWindow::Size).toSize(); + if(props.contains(NativeWindow::Size)){ + sz = vals[ props.indexOf(NativeWindow::Size) ] .toSize(); + } + valList.width = sz.width(); + valList.height = sz.height(); + if(props.contains(NativeWindow::GlobalPos)){ + QPoint pt = vals[ props.indexOf(NativeWindow::GlobalPos) ] .toPoint(); + valList.x = pt.x(); + valList.y = pt.y(); + }else{ + valList.x = win->property(NativeWindow::GlobalPos).toPoint().x(); + valList.y = win->property(NativeWindow::GlobalPos).toPoint().y(); + } + 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);*/ + } + if(props.contains(NativeWindow::Name)){ + + } + if(props.contains(NativeWindow::Workspace)){ + int num = vals[ props.indexOf(NativeWindow::Workspace) ].toInt(); + xcb_ewmh_set_wm_desktop(&obj->EWMH, win->id(), (num<0 ? 0xFFFFFFFF : qAbs(num) ) ); + } + if(props.contains(NativeWindow::RelatedWindows)){ + + } + if(props.contains(NativeWindow::Visible)){ + //qDebug() << "Check Window Visibility:" << vals[ props.indexOf(NativeWindow::Visible) ]; + if( vals[ props.indexOf(NativeWindow::Visible) ].toBool() ){ + //qDebug() << " - Map it!"; + xcb_map_window(QX11Info::connection(), win->id()); + }else{ + //qDebug() << " - Unmap it!"; + xcb_unmap_window(QX11Info::connection(), win->id()); + } + } + if(props.contains(NativeWindow::Active)){ + //Only one window can be "Active" at a time - so only do anything if this window wants to be active + if(vals[props.indexOf(NativeWindow::Active)].toBool() ){ + //Lower the currently active window (invisible window) to the bottom of the stack + xcb_window_t cactive; + if( 1 == xcb_ewmh_get_active_window_reply( &obj->EWMH, + xcb_ewmh_get_active_window_unchecked(&obj->EWMH, QX11Info::appScreen()), + &cactive, NULL) ){ + uint32_t val = XCB_STACK_MODE_BELOW; + xcb_configure_window(QX11Info::connection(), cactive, XCB_CONFIG_WINDOW_STACK_MODE, &val); + } + + xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win->id() ); + //Also send the active window a message to take input focus + xcb_set_input_focus(QX11Info::connection(), XCB_INPUT_FOCUS_PARENT, win->id(), XCB_CURRENT_TIME); + //Send the window a WM_TAKE_FOCUS message +/* xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = win->id(); + event.type = obj->ATOMS["WM_PROTOCOLS"]; + event.data.data32[0] = obj->ATOMS["WM_TAKE_FOCUS"]; + event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime; + event.data.data32[2] = 0; + event.data.data32[3] = 0; + event.data.data32[4] = 0; + + xcb_send_event(QX11Info::connection(), 0, win->id(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + xcb_flush(QX11Info::connection()); +*/ + } + } + +} + +// === PUBLIC SLOTS === +//These are the slots which are typically only used by the desktop system itself or the NativeEventFilter +void NativeWindowSystem::RegisterVirtualRoot(WId id){ + //Convert to XCB array + xcb_window_t array[1]; + array[0] = id; + //Set the property + xcb_ewmh_set_virtual_roots(&obj->EWMH, QX11Info::appScreen(), 1, array); + //Now also enable automatic compositing for children of this window + //xcb_composite_redirect_window(QX11Info::connection(), id, XCB_COMPOSITE_REDIRECT_AUTOMATIC); + //xcb_composite_redirect_subwindows(QX11Info::connection(), id, XCB_COMPOSITE_REDIRECT_AUTOMATIC); +} + +void NativeWindowSystem::setRoot_supportedActions(){ +//NET_WM standards (ICCCM implied - no standard way to list those) + xcb_atom_t list[] = {obj->EWMH._NET_WM_NAME, + obj->EWMH._NET_WM_ICON, + obj->EWMH._NET_WM_ICON_NAME, + obj->EWMH._NET_WM_DESKTOP, + /*obj->ATOMS["_NET_WM_WINDOW_OPACITY"],*/ + /*_NET_WINDOW_TYPE (and all the various types - 15 in total*/ + obj->EWMH._NET_WM_WINDOW_TYPE, obj->EWMH._NET_WM_WINDOW_TYPE_DESKTOP, obj->EWMH._NET_WM_WINDOW_TYPE_DOCK, + obj->EWMH._NET_WM_WINDOW_TYPE_TOOLBAR, obj->EWMH._NET_WM_WINDOW_TYPE_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_UTILITY, + obj->EWMH._NET_WM_WINDOW_TYPE_SPLASH, obj->EWMH._NET_WM_WINDOW_TYPE_DIALOG, obj->EWMH._NET_WM_WINDOW_TYPE_NORMAL, + obj->EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU, obj->EWMH._NET_WM_WINDOW_TYPE_TOOLTIP, + obj->EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION, obj->EWMH._NET_WM_WINDOW_TYPE_COMBO, obj->EWMH._NET_WM_WINDOW_TYPE_DND, + }; + xcb_ewmh_set_supported(&obj->EWMH, QX11Info::appScreen(), 20,list); +} + +void NativeWindowSystem::setRoot_numberOfWorkspaces(QStringList names){ + if(names.isEmpty()){ names << "one"; } + //First set the overall number of workspaces + xcb_ewmh_set_number_of_desktops(&obj->EWMH, QX11Info::appScreen(), names.length()); + //Now set the names for the workspaces + //EWMH LIBRARY BROKEN - appears to be a mismatch in the function header (looking for a single char array, instead of a list of char arrays) + // Ken Moore - 6/27/17 + /* + char *array[ names.length() ]; + for(int i=0; iEWMH, QX11Info::appScreen(), names.length(), array); + */ +} + +void NativeWindowSystem::setRoot_currentWorkspace(int num){ + xcb_ewmh_set_current_desktop(&obj->EWMH, QX11Info::appScreen(), num); +} + +void NativeWindowSystem::setRoot_clientList(QList list, bool stackorder){ + //convert the QList into a generic array + xcb_window_t array[list.length()]; + for(int i=0; iEWMH, QX11Info::appScreen(), list.length(), array); + }else{ + xcb_ewmh_set_client_list(&obj->EWMH, QX11Info::appScreen(), list.length(), array); + } +} + +void NativeWindowSystem::setRoot_desktopGeometry(QRect geom){ + //This one is a combo function + // This will set the "DESKTOP_VIEWPORT" property (point) + // as well as the "DESKTOP_GEOMETRY" property (size) + //Turn the QList into xcb_ewmh_coordinates_t* + xcb_ewmh_coordinates_t array[1]; + array[0].x=geom.x(); array[0].y=geom.y(); + //Now set the property + xcb_ewmh_set_desktop_viewport(&obj->EWMH, QX11Info::appScreen(), 1, array); + xcb_ewmh_set_desktop_geometry(&obj->EWMH, QX11Info::appScreen(), geom.width(), geom.height()); +} + +void NativeWindowSystem::setRoot_desktopWorkarea(QList list){ + //Convert to the XCB/EWMH data structures + xcb_ewmh_geometry_t array[list.length()]; + for(int i=0; iEWMH, QX11Info::appScreen(), list.length(), array); +} + +void NativeWindowSystem::setRoot_activeWindow(WId win){ + /*xcb_ewmh_set_active_window(&obj->EWMH, QX11Info::appScreen(), win); + //Also send the active window a message to take input focus + //Send the window a WM_TAKE_FOCUS message + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = win; + event.type = obj->ATOMS["WM_PROTOCOLS"]; + event.data.data32[0] = obj->ATOMS["WM_TAKE_FOCUS"]; + event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime; + event.data.data32[2] = 0; + event.data.data32[3] = 0; + event.data.data32[4] = 0; + + xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + xcb_flush(QX11Info::connection());*/ +} + +int NativeWindowSystem::currentWorkspace(){ + xcb_get_property_cookie_t cookie = xcb_ewmh_get_current_desktop_unchecked(&obj->EWMH, QX11Info::appScreen()); + uint32_t num = 0; + if(1==xcb_ewmh_get_current_desktop_reply(&obj->EWMH, cookie, &num, NULL) ){ + return num; + }else{ + return 0; + } +} + +//NativeWindowEventFilter interactions +void NativeWindowSystem::NewWindowDetected(WId id){ + //Make sure this can be managed first + if(findWindow(id, false) != 0){ findWindow(id,false)->setProperty(NativeWindow::Visible, true, true); return; } //already managed + xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id); + xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL); + if(attr == 0){ return; } //could not get attributes of window + if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage) + free(attr); + //Now go ahead and create/populate the container for this window + NativeWindow *win = new NativeWindow(id); + //Register for events from this window + registerClientEvents(win->id()); + NWindows << win; + UpdateWindowProperties(win, NativeWindow::allProperties()); + qDebug() << "New Window [& associated ID's]:" << win->id() << win->property(NativeWindow::Name).toString(); + //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, QList)), this, SLOT(RequestPropertiesChange(WId, QList, QList)) ); + emit NewWindowAvailable(win); +} + +void NativeWindowSystem::NewTrayWindowDetected(WId id){ + //Make sure this can be managed first + if(findTrayWindow(id) != 0){ return; } //already managed + xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), id); + xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL); + if(attr == 0){ return; } //could not get attributes of window + if(attr->override_redirect){ free(attr); return; } //window has override redirect set (do not manage) + free(attr); + //Register for events from this window + #define TRAY_WIN_EVENT_MASK (XCB_EVENT_MASK_BUTTON_PRESS | \ + XCB_EVENT_MASK_BUTTON_RELEASE | \ + XCB_EVENT_MASK_POINTER_MOTION | \ + XCB_EVENT_MASK_BUTTON_MOTION | \ + XCB_EVENT_MASK_EXPOSURE | \ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | \ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | \ + XCB_EVENT_MASK_ENTER_WINDOW) + + uint32_t value_list[1] = {TRAY_WIN_EVENT_MASK}; + xcb_change_window_attributes(QX11Info::connection(), id, XCB_CW_EVENT_MASK, value_list); + //Now go ahead and create/populate the container for this window + NativeWindow *win = new NativeWindow(id); + TWindows << win; + UpdateWindowProperties(win, NativeWindow::allProperties()); + emit NewTrayWindowAvailable(win); +} + +void NativeWindowSystem::WindowCloseDetected(WId id){ + NativeWindow *win = findWindow(id, false); + //qDebug() << "Got Window Closed" << id << win; + //qDebug() << "Old Window List:" << NWindows.length(); + if(win!=0){ + NWindows.removeAll(win); + //RequestReparent(id, QX11Info::appRootWindow(), QPoint(0,0)); + win->emit WindowClosed(id); + //qDebug() << "Visible Window Closed!!!"; + //win->deleteLater(); + }else{ + win = findTrayWindow(id); + if(win!=0){ + TWindows.removeAll(win); + win->emit WindowClosed(id); + win->deleteLater(); + } + } + //qDebug() << " - Now:" << NWindows.length(); +} + +void NativeWindowSystem::WindowPropertyChanged(WId id, NativeWindow::Property prop){ + //NOTE: This is triggered by the NativeEventFilter - not by changes to the NativeWindow objects themselves + NativeWindow *win = findWindow(id, prop!=NativeWindow::Visible); + if(win==0){ win = findTrayWindow(id); } + if(win!=0){ + UpdateWindowProperties(win, QList() << prop); + }else if(prop != 0){ + //Could not find the window for a specific property with an undefined value + // - update this property for all the windows just in case + for(int i=0; i() << prop); + } + } +} + +void NativeWindowSystem::WindowPropertiesChanged(WId id, QList props){ + //NOTE: This is triggered by the NativeEventFilter - not by changes to the NativeWindow objects themselves + NativeWindow *win = findWindow(id); + if(win==0){ win = findTrayWindow(id); } + if(win!=0){ + UpdateWindowProperties(win, props); + }else{ + //Could not find the window for a specific property with an undefined value + // - update this property for all the windows just in case + for(int i=0; isetProperty(prop, val); + } +} + +void NativeWindowSystem::WindowPropertiesChanged(WId id, QList props, QList vals){ + NativeWindow *win = findWindow(id); + if(win==0){ win = findTrayWindow(id); } + if(win!=0){ + for(int i=0; isetProperty(props[i], vals[i]); } + } +} + +void NativeWindowSystem::RequestPropertyChange(WId id, NativeWindow::Property prop, QVariant val){ + //This is just a simplified version of the multiple-property function + RequestPropertiesChange(id, QList() << prop, QList() << val); +} + +void NativeWindowSystem::RequestPropertiesChange(WId win, QList props, QList vals){ + //Find the window object associated with this id + bool istraywin = false; //just in case we care later if it is a tray window or a regular window + NativeWindow *WIN = findWindow(win); + if(WIN==0){ istraywin = true; WIN = findTrayWindow(win); } + if(WIN==0){ return; } //invalid window ID - no longer available + //Now make any changes as needed + ChangeWindowProperties(WIN, props, vals); +} + +void NativeWindowSystem::GotPong(WId id){ + if(waitingForPong.contains(id)){ + waitingForPong.remove(id); + } + if(waitingForPong.isEmpty() && pingTimer!=0){ pingTimer->stop(); } +} + +void NativeWindowSystem::NewKeyPress(int keycode, WId win){ + emit NewInputEvent(); + if(screenLocked){ return; } + Qt::Key key = KeycodeToQt(keycode); + if(key!=Qt::Key_unknown){ emit KeyPressDetected(win, key); } +} + +void NativeWindowSystem::NewKeyRelease(int keycode, WId win){ + emit NewInputEvent(); + if(screenLocked){ return; } + Qt::Key key = KeycodeToQt(keycode); + if(key!=Qt::Key_unknown){ emit KeyReleaseDetected(win, key); } +} + +void NativeWindowSystem::NewMousePress(int buttoncode, WId win){ + emit NewInputEvent(); + if(screenLocked){ return; } + emit MousePressDetected(win, MouseToQt(buttoncode)); +} + +void NativeWindowSystem::NewMouseRelease(int buttoncode, WId win){ + emit NewInputEvent(); + if(screenLocked){ return; } + emit MouseReleaseDetected(win, MouseToQt(buttoncode)); +} + +void NativeWindowSystem::CheckDamageID(WId win){ + for(int i=0; idamageId() == win || NWindows[i]->id() == win || NWindows[i]->frameId()==win){ + NWindows[i]->emit VisualChanged(); + //qDebug() << "Got DAMAGE Event"; + return; + } + } + NativeWindow *WIN = findTrayWindow(win); + if(WIN!=0){ + UpdateWindowProperties(WIN, QList() << NativeWindow::Icon); + } +} + +// === PRIVATE SLOTS === +//These are the slots which are built-in and automatically connected when a new NativeWindow is created + +void NativeWindowSystem::RequestClose(WId win){ + //Send the window a WM_DELETE_WINDOW message + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = win; + event.type = obj->ATOMS.value("WM_PROTOCOLS"); + event.data.data32[0] = obj->ATOMS.value("WM_DELETE_WINDOW"); + event.data.data32[1] = XCB_TIME_CURRENT_TIME; //CurrentTime; + event.data.data32[2] = 0; + event.data.data32[3] = 0; + event.data.data32[4] = 0; + + xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + xcb_flush(QX11Info::connection()); +} + +void NativeWindowSystem::RequestKill(WId win){ + xcb_kill_client(QX11Info::connection(), win); +} + +void NativeWindowSystem::RequestPing(WId win){ + waitingForPong.insert(win, QDateTime::currentDateTime().addSecs(5) ); + xcb_ewmh_send_wm_ping(&obj->EWMH, win, XCB_CURRENT_TIME); + if(pingTimer==0){ + pingTimer = new QTimer(this); + pingTimer->setInterval(2000); //2seconds + connect(pingTimer, SIGNAL(timeout()), this, SLOT(checkPings()) ); + } + pingTimer->start(); +} + +void NativeWindowSystem::RequestReparent(WId win, WId container, QPoint relorigin){ + NativeWindow *WIN = findWindow(win); + if(WIN==0){ return; } //could not find corresponding window structure +//Reparent the window into the container + xcb_reparent_window(QX11Info::connection(), win, container, relorigin.x(), relorigin.y()); + //xcb_map_window(QX11Info::connection(), win); + + //Now send the embed event to the app + //qDebug() << " - send _XEMBED event"; + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = win; + event.type = obj->ATOMS["_XEMBED"]; //_XEMBED + event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; + event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY + event.data.data32[2] = 0; + event.data.data32[3] = container; //WID of the container + event.data.data32[4] = 0; + + xcb_send_event(QX11Info::connection(), 0, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); + + //Now setup any redirects and return + //this->SelectInput(win, true); //Notify of structure changes + registerClientEvents(win); + //xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL); //XCB_COMPOSITE_REDIRECT_[MANUAL/AUTOMATIC]); + + //Now map the window (will be a transparent child of the container) + xcb_map_window(QX11Info::connection(), win); + xcb_map_window(QX11Info::connection(), container); + //Now create/register the damage handler + // -- XCB (Note: The XCB damage registration is completely broken at the moment - 9/15/15, Ken Moore) + // -- Retested 6/29/17 (no change) Ken Moore + //xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer + //xcb_damage_create(QX11Info::connection(), dmgID, win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES); + // -- XLib (Note: This is only used because the XCB routine above does not work - needs to be fixed upstream in XCB itself). + Damage dmgID = XDamageCreate(QX11Info::display(), win, XDamageReportRawRectangles); + WIN->addDamageID( (uint) dmgID); //save this for later + //qDebug() << " - Done"; + //return ( (uint) dmgID ); +} +/* + xcb_reparent_window(QX11Info::connection(), client, parent, relorigin.x(), relorigin.y()); + + //Now ensure that we still get event for these windows + registerClientEvents(client); //make sure we re-do this after reparenting + registerClientEvents(parent); + xcb_map_window(QX11Info::connection(), parent); +}*/ diff --git a/src-qt5/src-cpp/NativeWindowSystem.h b/src-qt5/src-cpp/NativeWindowSystem.h new file mode 100644 index 00000000..b67ecc94 --- /dev/null +++ b/src-qt5/src-cpp/NativeWindowSystem.h @@ -0,0 +1,139 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is a Qt5/Lumina wrapper around native graphics system calls +// It is primarily designed around the creation/modification of instances of +// the "NativeWindow" class for passing information around +//=========================================== +#ifndef _LUMINA_NATIVE_WINDOW_SYSTEM_H +#define _LUMINA_NATIVE_WINDOW_SYSTEM_H + +#include "NativeWindow.h" +#include +#include +#include + +class NativeWindowSystem : public QObject{ + Q_OBJECT +private: + QList NWindows; + QList TWindows; + + //Simplifications to find an already-created window object + NativeWindow* findWindow(WId id, bool checkRelated = true); + + NativeWindow* 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; + p_objects* obj; + + //Internal timers/variables for managing pings + QTimer *pingTimer; + QHash waitingForPong; + void checkPings(){ + QDateTime cur = QDateTime::currentDateTime(); + QList waiting = waitingForPong.keys(); + for(int i=0; istop(); } + NativeWindow *win = findWindow(waiting[i]); + if(win==0){ win = findTrayWindow(waiting[i]); } + if(win!=0){ win->emit WindowNotResponding(waiting[i]); } + } + } + } + + // 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(NativeWindow* win, QList< NativeWindow::Property > props); + void ChangeWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props, QList vals); + + //Generic private variables + bool screenLocked; + +public: + //enum Property{ None, CurrentWorkspace, Workspaces, VirtualRoots, WorkAreas }; + enum MouseButton{NoButton, LeftButton, RightButton, MidButton, BackButton, ForwardButton, TaskButton, WheelUp, WheelDown, WheelLeft, WheelRight}; + + NativeWindowSystem(); + ~NativeWindowSystem(); + + //Overarching start/stop functions + bool start(); + void stop(); + + //General-purpose listing functions + QList currentWindows(){ return NWindows; } + QList currentTrayWindows(){ return TWindows; } + + //Small simplification functions + static Qt::Key KeycodeToQt(int keycode); + static NativeWindowSystem::MouseButton MouseToQt(int button); + +public slots: + //These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter + + //This is called by the lock screen to keep the NWS aware of the current status + // it is **NOT** the function to call for the user to actually lock the session (that is in the screensaver/lockscreen class) + void ScreenLockChanged(bool lock){ + screenLocked = lock; + } + + //Root Window property registrations + void RegisterVirtualRoot(WId); + void setRoot_supportedActions(); + void setRoot_numberOfWorkspaces(QStringList names); + void setRoot_currentWorkspace(int); + void setRoot_clientList(QList, bool stackorder = false); + void setRoot_desktopGeometry(QRect); + void setRoot_desktopWorkarea(QList); + void setRoot_activeWindow(WId); + + // - Workspaces + int currentWorkspace(); + //void GoToWorkspace(int); + + + //NativeWindowEventFilter interactions + void NewWindowDetected(WId); //will automatically create the new NativeWindow object + void NewTrayWindowDetected(WId); //will automatically create the new NativeWindow object + void WindowCloseDetected(WId); //will update the lists and make changes if needed + void WindowPropertyChanged(WId, NativeWindow::Property); //will rescan the window and update the object as needed + void WindowPropertiesChanged(WId, QList); + void WindowPropertyChanged(WId, NativeWindow::Property, QVariant); //will save that property/value to the right object + void WindowPropertiesChanged(WId, QList, QList); + void RequestPropertyChange(WId, NativeWindow::Property, QVariant); + void RequestPropertiesChange(WId, QList, QList); + void GotPong(WId); + + void NewKeyPress(int keycode, WId win = 0); + void NewKeyRelease(int keycode, WId win = 0); + void NewMousePress(int buttoncode, WId win = 0); + void NewMouseRelease(int buttoncode, WId win = 0); + void CheckDamageID(WId); + +private slots: + //These are the slots which are built-in and automatically connected when a new NativeWindow is created + void RequestClose(WId); + void RequestKill(WId); + void RequestPing(WId); + void RequestReparent(WId, WId, QPoint); //client, parent, relative origin point in parent + +signals: + void NewWindowAvailable(NativeWindow*); + void NewTrayWindowAvailable(NativeWindow*); + void NewInputEvent(); //a mouse or keypress was detected (lock-state independent); + void KeyPressDetected(WId, Qt::Key); //only emitted if lockstate = false + void KeyReleaseDetected(WId, Qt::Key); //only emitted if lockstate = false + void MousePressDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false + void MouseReleaseDetected(WId, NativeWindowSystem::MouseButton); //only emitted if lockstate = false + +}; + +#endif diff --git a/src-qt5/src-cpp/RootDesktopObject.cpp b/src-qt5/src-cpp/RootDesktopObject.cpp index 088c88b7..e7873991 100644 --- a/src-qt5/src-cpp/RootDesktopObject.cpp +++ b/src-qt5/src-cpp/RootDesktopObject.cpp @@ -5,9 +5,13 @@ // See the LICENSE file for full details //=========================================== #include "RootDesktopObject.h" +#include +#include +#include + // === PUBLIC === -RootDesktopObject::RootDesktopObject(QObject *parent = 0){ +RootDesktopObject::RootDesktopObject(QObject *parent) : QObject(parent){ updateScreens(); //make sure the internal list is updated right away } @@ -15,14 +19,24 @@ RootDesktopObject::~RootDesktopObject(){ } -static RootDesktopObject* RootDesktopObject::instance(){ +void RootDesktopObject::RegisterType(){ + qmlRegisterType("Lumina.Backend.RootDesktopObject", 2, 0, "RootDesktopObject"); + //Also register any types that are needed by this class + ScreenObject::RegisterType(); +} + +RootDesktopObject* RootDesktopObject::instance(){ static RootDesktopObject* r_obj = new RootDesktopObject(); return r_obj; } //QML Read Functions -QList RootDesktopObject::screens(){ - return ; +QList RootDesktopObject::screens(){ + return s_objects; +} + +void RootDesktopObject::logout(){ + emit startLogout(); } // === PUBLIC SLOTS === @@ -32,7 +46,7 @@ void RootDesktopObject::updateScreens(){ for(int i=0; iname()==scrns[i]->name()){ found = true; tmp << s_objects.takeAt(j); } } if(!found){ tmp << new ScreenObject(scrns[i], this); } } @@ -41,4 +55,10 @@ void RootDesktopObject::updateScreens(){ s_objects = tmp; } +void RootDesktopObject::ChangeWallpaper(QString screen, QString value){ + for(int i=0; iname()==screen){ s_objects[i]->setBackground(value); break; } + } +} + // === PRIVATE === diff --git a/src-qt5/src-cpp/RootDesktopObject.h b/src-qt5/src-cpp/RootDesktopObject.h index b706bcb6..0c280c2a 100644 --- a/src-qt5/src-cpp/RootDesktopObject.h +++ b/src-qt5/src-cpp/RootDesktopObject.h @@ -6,10 +6,13 @@ //=========================================== // This is the base C++ object that is used to pass information to the QML "RootDesktop" object //=========================================== -#ifndef _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H -#define _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H +#ifndef _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H +#define _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H +#include +#include #include "ScreenObject.h" + class RootDesktopObject : public QObject{ Q_OBJECT //Define all the QML Properties here (interface between QML and the C++ methods below) @@ -20,7 +23,7 @@ public: RootDesktopObject(QObject *parent = 0); ~RootDesktopObject(); - static void RegisterType(){ qmlRegisterType("Lumina.Backend.RootDesktopObject",2,0, "RootDesktopObject"); + static void RegisterType(); //primary interface to fetch the current instance of the class (so only one is running at any given time) static RootDesktopObject* instance(); @@ -36,11 +39,13 @@ private: public slots: void updateScreens(); //rescan/update screen objects + void ChangeWallpaper(QString screen, QString); private slots: signals: void screensChanged(); + void startLogout(); }; #endif diff --git a/src-qt5/src-cpp/ScreenObject.cpp b/src-qt5/src-cpp/ScreenObject.cpp new file mode 100644 index 00000000..354b4cba --- /dev/null +++ b/src-qt5/src-cpp/ScreenObject.cpp @@ -0,0 +1,30 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "ScreenObject.h" +#include + +ScreenObject::ScreenObject(QScreen *scrn, QObject *parent) : QObject(parent){ + bg_screen = scrn; +} + +void ScreenObject::RegisterType(){ + qmlRegisterType("Lumina.Backend.ScreenObject",2,0, "ScreenObject"); +} + +QString ScreenObject::name(){ return bg_screen->name(); } +QString ScreenObject::background(){ return bg; } +int ScreenObject::x(){ return bg_screen->geometry().x(); } +int ScreenObject::y(){ return bg_screen->geometry().y(); } +int ScreenObject::width(){ return bg_screen->geometry().width(); } +int ScreenObject::height(){ return bg_screen->geometry().height(); } + +void ScreenObject::setBackground(QString fileOrColor){ + if(bg!=fileOrColor){ + bg = fileOrColor; + emit backgroundChanged(); + } +} diff --git a/src-qt5/src-cpp/ScreenObject.h b/src-qt5/src-cpp/ScreenObject.h index 49f266c3..5cb16bfc 100644 --- a/src-qt5/src-cpp/ScreenObject.h +++ b/src-qt5/src-cpp/ScreenObject.h @@ -4,12 +4,15 @@ // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== -// This is the base C++ object that is used to pass information to the QML "RootDesktop" object +// This is the base C++ object that is used to pass Screen/Wallpaper info to the QML classes //=========================================== -#ifndef _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H -#define _LUMINA_DESKTOP_ROOT_DESKTOP_OBJECT_H +#ifndef _LUMINA_DESKTOP_SCREEN_DESKTOP_OBJECT_H +#define _LUMINA_DESKTOP_SCREEN_DESKTOP_OBJECT_H +#include +#include +#include -class ScreenObject : public QObject{ +class ScreenObject : public QObject { Q_OBJECT Q_PROPERTY( QString name READ name ) Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) @@ -22,29 +25,24 @@ private: QScreen *bg_screen; QString bg; -public - ScreenObject(QScreen *scrn, QObject *parent = 0) : QObject(parent){ - bg_screen = scrn; - } +public: + ScreenObject(QScreen *scrn = 0, QObject *parent = 0); - static void RegisterType(){ qmlRegisterType("Lumina.Backend.ScreenObject",2,0, "ScreenObject"); + static void RegisterType(); - QString name(){ return bg_screen->name(); } - QString background(){ return bg; } - int x(){ return bg_screen->geometry().x(); } - int y(){ return bg_screen->geometry().y(); } - int width(){ return bg_screen->geometry().width(); } - int height(){ return bg_screen->geometry().height(); } + QString name(); + QString background(); + int x(); + int y(); + int width(); + int height(); public slots: - void setBackground(QString fileOrColor){ - if(bg!=fileOrColor){ - bg = fileOrColor; - emit backgroundChanged(); - } - } + void setBackground(QString fileOrColor); signals: void backgroundChanged(); void geomChanged(); }; + +#endif diff --git a/src-qt5/src-qml/RootDesktop.qml b/src-qt5/src-qml/RootDesktop.qml index 0003366b..b9d62894 100644 --- a/src-qt5/src-qml/RootDesktop.qml +++ b/src-qt5/src-qml/RootDesktop.qml @@ -22,12 +22,12 @@ import Lumina.Backend.RootDesktopObject 2.0 import Lumina.Backend.ScreenObject 2.0 Rectangle { - id: RootCanvas + id: rootCanvas color: "black" //Setup the right-click context menu MouseArea { - anchors.fill: RootCanvas + anchors.fill: rootCanvas acceptedButton: Qt.RightButton onClicked: { contextMenu.open() } } @@ -51,7 +51,7 @@ Rectangle { Repeater{ model: RootObject.screens AnimatedImage { - id: modelData.name + id: ("screen_"+modelData.name) asynchronous: true clip: true source: modelData.background diff --git a/src-qt5/src-qml/src-qml.pri b/src-qt5/src-qml/src-qml.pri index bcdd439d..43af4b5a 100644 --- a/src-qt5/src-qml/src-qml.pri +++ b/src-qt5/src-qml/src-qml.pri @@ -3,7 +3,7 @@ QT *= quick qml lupdate_only{ - SOURCES *= RootDesktop.qml + SOURCES *= $${PWD}/RootDesktop.qml } -RESOURCES *= src-qml.qrc +RESOURCES *= $${PWD}/src-qml.qrc diff --git a/src-qt5/src-qml/src-qml.qrc b/src-qt5/src-qml/src-qml.qrc index 41f9d54b..5bedb4a5 100644 --- a/src-qt5/src-qml/src-qml.qrc +++ b/src-qt5/src-qml/src-qml.qrc @@ -1,5 +1,5 @@ - + RootDesktop.qml -- cgit From c1b01a5e939aa39b52d13f91ebd73fe1092c4669 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 16 Oct 2017 09:30:19 -0400 Subject: Update the backend process-running routine for Lumina (LUtils) This gives us an extra function with additional hooks (environment, working directory) It also gets rid of all that ugly QFuture stuff which never quite worked as expected anyway. --- src-qt5/core/libLumina/LUtils.cpp | 80 +++++++++++++++++++++------------------ src-qt5/core/libLumina/LUtils.h | 3 ++ 2 files changed, 47 insertions(+), 36 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LUtils.cpp b/src-qt5/core/libLumina/LUtils.cpp index 491778ca..820b55e8 100644 --- a/src-qt5/core/libLumina/LUtils.cpp +++ b/src-qt5/core/libLumina/LUtils.cpp @@ -14,7 +14,7 @@ #include -inline QStringList ProcessRun(QString cmd, QStringList args){ +/*inline QStringList ProcessRun(QString cmd, QStringList args){ //Assemble outputs QStringList out; out << "1" << ""; //error code, string output QProcess proc; @@ -38,50 +38,58 @@ inline QStringList ProcessRun(QString cmd, QStringList args){ out[0] = QString::number(proc.exitCode()); out[1] = info+QString(proc.readAllStandardOutput()); return out; -} +}*/ + //============= // LUtils Functions //============= -int LUtils::runCmd(QString cmd, QStringList args){ - /*QProcess proc; - proc.setProcessChannelMode(QProcess::MergedChannels); - if(args.isEmpty()){ - proc.start(cmd); - }else{ - proc.start(cmd, args); +QString LUtils::runCommand(bool &success, QString command, QStringList arguments, QString workdir, QStringList env){ + QProcess proc; + proc.setProcessChannelMode(QProcess::MergedChannels); //need output + //First setup the process environment as necessary + QProcessEnvironment PE = QProcessEnvironment::systemEnvironment(); + if(!env.isEmpty()){ + for(int i=0; i future = QtConcurrent::run(ProcessRun, cmd, args); - return future.result()[1].split("\n"); //Split the return message into lines + bool success; + QString log = LUtils::runCommand(success, cmd, args); + return log.split("\n"); + /*QFuture future = QtConcurrent::run(ProcessRun, cmd, args); + return future.result()[1].split("\n"); //Split the return message into lines*/ } QStringList LUtils::readFile(QString filepath){ diff --git a/src-qt5/core/libLumina/LUtils.h b/src-qt5/core/libLumina/LUtils.h index a494d4da..ee04c023 100644 --- a/src-qt5/core/libLumina/LUtils.h +++ b/src-qt5/core/libLumina/LUtils.h @@ -30,6 +30,9 @@ class LUtils{ public: + //Run an external command and return output & exit code + static QString runCommand(bool &success, QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList()); + //Run an external command and return the exit code static int runCmd(QString cmd, QStringList args = QStringList()); //Run an external command and return any text output (one line per entry) -- cgit From e152255ec8e2bb7c0604fbbe569d47f345678ea6 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 16 Oct 2017 11:54:07 -0400 Subject: Clean up the session file-init routine. Now the user files are scanned/created from within the start-lumina-desktop process, not the desktop process. This fixes the loading of the theme engine for the desktop process on first-run situations, and also ensures that the desktop process does not need to make any major changes to it's configs while it is still running. --- src-qt5/core/libLumina/LDesktopUtils.cpp | 5 +---- src-qt5/core/lumina-desktop/LSession.cpp | 16 +++++++++++----- src-qt5/core/lumina-desktop/LSession.h | 2 +- src-qt5/core/lumina-desktop/main.cpp | 25 +++++-------------------- src-qt5/core/lumina-session/main.cpp | 20 ++++++++++---------- src-qt5/core/lumina-session/session.cpp | 26 ++++++++++++++++++++++++-- src-qt5/core/lumina-session/session.h | 2 ++ 7 files changed, 54 insertions(+), 42 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index fb13a2a3..c65f6faf 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -483,10 +483,7 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ //Convert from the old desktop numbering system to the new one (change occured with 1.0.1) if(oldversion<=1000001){ QStringList DS = LUtils::readFile(dset); - char *tmp; - int tmpN = 0; - QApplication A(tmpN, &tmp); - QList screens = A.screens(); + QList screens = QApplication::screens(); for(int i=0; i 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] + qDebug() << "Check User Files"; + //char tmp[] = "junk\0"; + //int tmpN = 0; + //QApplication A(tmpN, (char **)&tmp); QSettings sset("lumina-desktop", "sessionsettings"); QString OVS = sset.value("DesktopVersion","0").toString(); //Old Version String - char *tmp; - int tmpN = 0; - QApplication *A = new QApplication(tmpN, &tmp); + qDebug() << " - Old Version:" << OVS; + qDebug() << " - Current Version:" << LDesktopUtils::LuminaDesktopVersion(); bool changed = LDesktopUtils::checkUserFiles(OVS, LDesktopUtils::LuminaDesktopVersion()); + qDebug() << " - Made Changes:" << changed; if(changed){ //Save the current version of the session to the settings file (for next time) sset.setValue("DesktopVersion", LDesktopUtils::LuminaDesktopVersion()); } - delete A; + qDebug() << "Finished with user files check"; + //delete A; + return changed; } void LSession::refreshWindowManager(){ diff --git a/src-qt5/core/lumina-desktop/LSession.h b/src-qt5/core/lumina-desktop/LSession.h index 43cddac7..a25f3c15 100644 --- a/src-qt5/core/lumina-desktop/LSession.h +++ b/src-qt5/core/lumina-desktop/LSession.h @@ -52,7 +52,7 @@ public: LSession(int &argc, char **argv); ~LSession(); - static void checkUserFiles(); + static bool checkUserFiles(); //Functions to be called during startup void setupSession(); diff --git a/src-qt5/core/lumina-desktop/main.cpp b/src-qt5/core/lumina-desktop/main.cpp index c272f263..826d697c 100644 --- a/src-qt5/core/lumina-desktop/main.cpp +++ b/src-qt5/core/lumina-desktop/main.cpp @@ -76,36 +76,21 @@ int main(int argc, char ** argv) setenv("QT_QPA_PLATFORMTHEME", "lthemeengine", 1); unsetenv("QT_AUTO_SCREEN_SCALE_FACTOR"); //causes pixel-specific scaling issues with the desktop - turn this on after-the-fact for other apps //Startup the session - LSession::checkUserFiles(); //make sure to create any config files before creating the QApplication LSession a(argc, argv); if(!a.isPrimaryProcess()){ return 0; } + //Ensure that the user's config files exist + /*if( LSession::checkUserFiles() ){ //make sure to create any config files before creating the QApplication + qDebug() << "User files changed - restarting the desktop session"; + return 787; //return special restart code + }*/ //Setup the log file - /* logfile.setFileName( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/logs/runtime.log" ); - qDebug() << "Lumina Log File:" << logfile.fileName(); - if(QFile::exists(logfile.fileName()+".old")){ QFile::remove(logfile.fileName()+".old"); } - if(logfile.exists()){ QFile::rename(logfile.fileName(), logfile.fileName()+".old"); } - //Make sure the parent directory exists - if(!QFile::exists(QDir::homePath()+"/.lumina/logs")){ - QDir dir; - dir.mkpath(QDir::homePath()+"/.lumina/logs"); - } - logfile.open(QIODevice::WriteOnly | QIODevice::Append);*/ QTime *timer=0; if(DEBUG){ timer = new QTime(); timer->start(); } - //Setup Log File - //qInstallMessageHandler(MessageOutput); - //if(DEBUG){ qDebug() << "Theme Init:" << timer->elapsed(); } - //LuminaThemeEngine theme(&a); - //QObject::connect(&theme, SIGNAL(updateIcons()), &a, SLOT(reloadIconTheme()) ); - //if(DEBUG){ qDebug() << "Load Locale:" << timer->elapsed(); } - //LUtils::LoadTranslation(&a, "lumina-desktop"); if(DEBUG){ qDebug() << "Session Setup:" << timer->elapsed(); } a.setupSession(); - //theme.refresh(); if(DEBUG){ qDebug() << "Exec Time:" << timer->elapsed(); delete timer;} int retCode = a.exec(); //qDebug() << "Stopping the window manager"; qDebug() << "Finished Closing Down Lumina"; - //logfile.close(); return retCode; } diff --git a/src-qt5/core/lumina-session/main.cpp b/src-qt5/core/lumina-session/main.cpp index 71244a8b..3b71bdca 100644 --- a/src-qt5/core/lumina-session/main.cpp +++ b/src-qt5/core/lumina-session/main.cpp @@ -55,14 +55,6 @@ int main(int argc, char ** argv) return QProcess::execute("xinit", args); } qDebug() << "Starting the Lumina desktop on current X11 session:" << disp; - //Setup any initialization values - LTHEME::LoadCustomEnvSettings(); - LXDG::setEnvironmentVars(); - setenv("DESKTOP_SESSION","Lumina",1); - setenv("XDG_CURRENT_DESKTOP","Lumina",1); - unsetenv("QT_QPA_PLATFORMTHEME"); //causes issues with Lumina themes - not many people have this by default... - //Check for any missing user config files - //Check for any stale desktop lock files and clean them up QString cfile = QDir::tempPath()+"/.LSingleApp-%1-%2-%3"; @@ -81,14 +73,22 @@ int main(int argc, char ** argv) } //Configure X11 monitors if needed - if(LUtils::isValidBinary("lumina-xconfig")){ + if(LUtils::isValidBinary("lumina-xconfig")){ qDebug() << " - Resetting monitor configuration to last-used settings"; QProcess::execute("lumina-xconfig --reset-monitors"); } qDebug() << " - Starting the session..."; + //Setup any initialization values + LTHEME::LoadCustomEnvSettings(); + LXDG::setEnvironmentVars(); + setenv("DESKTOP_SESSION","Lumina",1); + setenv("XDG_CURRENT_DESKTOP","Lumina",1); + unsetenv("QT_QPA_PLATFORMTHEME"); //causes issues with Lumina themes - not many people have this by default... //Startup the session - QCoreApplication a(argc, argv); + QApplication a(argc, argv); + setenv("QP_QPA_PLATFORMTHEME","lthemeengine",1); //make sure this is after the QApplication - not actually using the theme plugin for **this** process LSession sess; + sess.checkFiles(); //Make sure user files are created/installed first sess.start(unified); int retCode = a.exec(); qDebug() << "Finished Closing Down Lumina"; diff --git a/src-qt5/core/lumina-session/session.cpp b/src-qt5/core/lumina-session/session.cpp index 3fdf9e66..743fc396 100644 --- a/src-qt5/core/lumina-session/session.cpp +++ b/src-qt5/core/lumina-session/session.cpp @@ -15,6 +15,7 @@ #include #include +#include void LSession::stopall(){ stopping = true; @@ -38,8 +39,12 @@ void LSession::procFinished(){ stopped++; if(!stopping){ //See if this process is the main desktop binary - if(PROCS[i]->objectName()=="runtime"){ stopall(); } - else if(PROCS[i]->objectName()=="wm" && wmfails<2){ wmfails++; PROCS[i]->start(QIODevice::ReadOnly); wmTimer->start(); } //restart the WM + if(PROCS[i]->objectName()=="runtime"){ + qDebug() << "Got Desktop Process Finished:" << PROCS[i]->exitCode(); + //if(PROCS[i]->exitCode()==787){ PROCS[i]->start(QIODevice::ReadOnly); } //special internal restart code + //else{ + stopall(); //} + }else if(PROCS[i]->objectName()=="wm" && wmfails<2){ wmfails++; PROCS[i]->start(QIODevice::ReadOnly); wmTimer->start(); } //restart the WM //if(PROCS[i]->program().section("/",-1) == "lumina-desktop"){ stopall(); } //start closing down everything //else{ PROCS[i]->start(QIODevice::ReadOnly); } //restart the process //break; @@ -164,3 +169,20 @@ void LSession::start(bool unified){ startProcess("runtime","lumina-desktop-unified"); } } + +void LSession::checkFiles(){ +//internal version conversion examples: + // [1.0.0 -> 1000000], [1.2.3 -> 1002003], [0.6.1 -> 6001] + qDebug() << "[Lumina] Checking User Files"; + QSettings sset("lumina-desktop", "sessionsettings"); + QString OVS = sset.value("DesktopVersion","0").toString(); //Old Version String + qDebug() << " - Old Version:" << OVS; + qDebug() << " - Current Version:" << LDesktopUtils::LuminaDesktopVersion(); + bool changed = LDesktopUtils::checkUserFiles(OVS, LDesktopUtils::LuminaDesktopVersion()); + qDebug() << " - Made Changes:" << changed; + if(changed){ + //Save the current version of the session to the settings file (for next time) + sset.setValue("DesktopVersion", LDesktopUtils::LuminaDesktopVersion()); + } + qDebug() << "Finished with user files check"; +} diff --git a/src-qt5/core/lumina-session/session.h b/src-qt5/core/lumina-session/session.h index 5cf1ccfa..3bbcbb8e 100644 --- a/src-qt5/core/lumina-session/session.h +++ b/src-qt5/core/lumina-session/session.h @@ -83,4 +83,6 @@ public: void start(bool unified = false); + void checkFiles(); + }; -- cgit From cd928a79ff4bf6da55689bc100168355ec962b50 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Mon, 16 Oct 2017 21:00:07 -0400 Subject: Updated how video thumbnails are loaded. Now cached to stop crash when resizing. --- src-qt5/core/libLumina/LVideoLabel.cpp | 50 +++++++-------- src-qt5/core/libLumina/LVideoLabel.h | 9 ++- src-qt5/core/libLumina/LVideoLabel.pri | 5 +- src-qt5/core/libLumina/LuminaThemes.cpp | 6 ++ src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 12 +++- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 77 +++++------------------- src-qt5/desktop-utils/lumina-fm/Browser.h | 7 +-- src-qt5/desktop-utils/lumina-fm/BrowserWidget.h | 1 + src-qt5/desktop-utils/lumina-fm/lumina-fm.pro | 3 +- 9 files changed, 71 insertions(+), 99 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp index 20b2cad4..3b2ce468 100644 --- a/src-qt5/core/libLumina/LVideoLabel.cpp +++ b/src-qt5/core/libLumina/LVideoLabel.cpp @@ -1,40 +1,42 @@ #include "LVideoLabel.h" -LVideoLabel::LVideoLabel(QString file, bool video) : QLabel(){ - this->setScaledContents(true); - if(video) { - mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); - thumbnail = QPixmap(); - entered = false; - surface = new LVideoSurface(this); - mediaPlayer->setVideoOutput(surface); - mediaPlayer->setMedia(QUrl("file://" + file)); - mediaPlayer->setPlaybackRate(3); - mediaPlayer->setMuted(true); - mediaPlayer->play(); - mediaPlayer->pause(); - this->connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(stopVideo(QPixmap))); - this->connect(mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus))); - this->connect(this, SIGNAL(rollOver()), surface, SLOT(switchRollOver())); - }else{ - thumbnail = QPixmap(file); - this->setPixmap(thumbnail); - } +LVideoLabel::LVideoLabel(QString file, QWidget *parent) : QLabel(parent) { + this->setScaledContents(true); + mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); + thumbnail = QPixmap(); + this->setPixmap(thumbnail); + entered = false; + surface = new LVideoSurface(this); + mediaPlayer->setVideoOutput(surface); + mediaPlayer->setPlaybackRate(3); + mediaPlayer->setMuted(true); + mediaPlayer->setMedia(QUrl("file://" + file)); + mediaPlayer->play(); + mediaPlayer->pause(); + + this->connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(stopVideo(QPixmap))); + this->connect(mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus))); + this->connect(this, SIGNAL(rollOver()), surface, SLOT(switchRollOver())); } LVideoLabel::~LVideoLabel() { mediaPlayer->deleteLater(); - surface->deleteLater(); + delete surface; +} + +void LVideoLabel::setShrinkPixmap(bool shrink) { + this->shrink = shrink; } void LVideoLabel::stopVideo(QPixmap pix) { if(!entered) { + emit frameReceived(pix); if(thumbnail.isNull()) - thumbnail = QPixmap(pix.scaledToHeight(64)); - this->setPixmap(thumbnail); + thumbnail = pix; + this->setPixmap((shrink) ? thumbnail.scaledToHeight(64) : thumbnail); mediaPlayer->pause(); }else { - this->setPixmap(QPixmap(pix.scaledToHeight(64))); + this->setPixmap((shrink) ? pix.scaledToHeight(64) : pix); } } diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h index fd293200..fa590e5a 100644 --- a/src-qt5/core/libLumina/LVideoLabel.h +++ b/src-qt5/core/libLumina/LVideoLabel.h @@ -10,21 +10,24 @@ class LVideoLabel : public QLabel { Q_OBJECT public: - LVideoLabel(QString, bool); + LVideoLabel(QString, QWidget* parent=NULL); ~LVideoLabel(); + void setShrinkPixmap(bool); + protected: void enterEvent(QEvent*); void leaveEvent(QEvent*); signals: void rollOver(); - public slots: + void frameReceived(QPixmap); + private slots: void stopVideo(QPixmap); void setDuration(QMediaPlayer::MediaStatus); private: QMediaPlayer *mediaPlayer; LVideoSurface *surface; - QVideoWidget *videoPlayer; QPixmap thumbnail; bool entered; + bool shrink; }; #endif diff --git a/src-qt5/core/libLumina/LVideoLabel.pri b/src-qt5/core/libLumina/LVideoLabel.pri index f609df08..384b3aae 100644 --- a/src-qt5/core/libLumina/LVideoLabel.pri +++ b/src-qt5/core/libLumina/LVideoLabel.pri @@ -1,8 +1,11 @@ QT *= multimedia HEADERS *= $${PWD}/LVideoLabel.h +HEADERS *= $${PWD}/LVideoSurface.h SOURCES *= $${PWD}/LVideoLabel.cpp +SOURCES *= $${PWD}/LVideoSurface.cpp INCLUDEPATH *= ${PWD} -include(LVideoSurface.pri) +#Now the other dependendies of it +#include(LUtils.pri) diff --git a/src-qt5/core/libLumina/LuminaThemes.cpp b/src-qt5/core/libLumina/LuminaThemes.cpp index f6868651..857e604b 100644 --- a/src-qt5/core/libLumina/LuminaThemes.cpp +++ b/src-qt5/core/libLumina/LuminaThemes.cpp @@ -122,6 +122,8 @@ QStringList LTHEME::availableSystemCursors(){ //returns: [name] for each item //Save a new theme/color file bool LTHEME::saveLocalTheme(QString name, QStringList contents){ + Q_UNUSED(name); + Q_UNUSED(contents); return false; //old format - do not use!! //QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themes/"; //if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); } @@ -129,6 +131,8 @@ bool LTHEME::saveLocalTheme(QString name, QStringList contents){ } bool LTHEME::saveLocalColors(QString name, QStringList contents){ + Q_UNUSED(name); + Q_UNUSED(contents); return false; //old format - do not use!! // QString localdir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/colors/"; //if(!QFile::exists(localdir)){ QDir dir; dir.mkpath(localdir); } @@ -182,6 +186,8 @@ QString LTHEME::currentCursor(){ //Change the current Theme/Colors/Icons bool LTHEME::setCurrentSettings(QString themepath, QString colorpath, QString iconname, QString font, QString fontsize){ + Q_UNUSED(font); + Q_UNUSED(fontsize); //QIcon::setThemeName(iconname); //Save these settings into the theme engine settings QSettings engineset("lthemeengine","lthemeengine"); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index 4ec8fae7..58ef8cbd 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -80,12 +80,17 @@ void MainUI::LoadFile(QString path, QString type){ else{ ftype = INFO->suffix().toUpper(); } if(INFO->isHidden()){ ftype = QString(tr("Hidden %1")).arg(type); } ui->label_file_type->setText(ftype); + //Now load the icon for the file if(INFO->isImage()){ - ui->label_file_icon = new LVideoLabel(INFO->absoluteFilePath(), false); - //ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); + QPixmap pix(INFO->absoluteFilePath()); + ui->label_file_icon->setPixmap(pix.scaledToHeight(64)); + ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); }else if(INFO->isVideo()){ - ui->label_file_icon = new LVideoLabel(INFO->absoluteFilePath(), true); + ui->label_file_icon->hide(); + LVideoLabel *mediaLabel = new LVideoLabel(INFO->absoluteFilePath(), ui->tab_file); + mediaLabel->setShrinkPixmap(true); + ui->formLayout->replaceWidget(ui->label_file_icon, mediaLabel); }else{ ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); } @@ -101,6 +106,7 @@ void MainUI::LoadFile(QString path, QString type){ ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_file) ); } } + //Now load the special XDG desktop info qDebug() << "Check XDG Info:" << type; //qDebug() << INFO->isDesktopFile() << type; diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index 4665ccc4..d829fff0 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -68,8 +68,6 @@ void Browser::loadItem(QString info, Browser *obj){ pix = pix.scaled(256,256, Qt::KeepAspectRatio); } } - }else if(videoFormats.contains(info.section(".",-1).toLower()) ){ - videoList.push_back(info); } //qDebug() << " - done with item:" << info; obj->emit threadDone(info, pix); @@ -79,7 +77,6 @@ QIcon* Browser::loadIcon(QString icon){ if(!mimeIcons.contains(icon)){ mimeIcons.insert(icon, LXDG::findIcon(icon, "unknown")); } - return &mimeIcons[icon]; } @@ -102,72 +99,28 @@ void Browser::dirChanged(QString dir){ else if(dir.startsWith(currentDir)){ QtConcurrent::run(this, &Browser::loadItem, dir, this ); } } -void Browser::stopVideo(QMediaPlayer *player, QMediaPlayer::MediaStatus status) { - //qDebug() << status; - if(status == QMediaPlayer::BufferedMedia) { - //qDebug() << "stoppingVideo" << player << player->currentMedia().canonicalUrl(); - player->setPosition(player->duration() / 2); - player->pause(); - } -} - -void Browser::captureFrame(QPixmap pix, QIcon *ico) { - static int received = 0; - //qDebug() << "grabbing frame" << received+1; - *ico = pix/*.scaledToHeight(64)*/; - if(++received == videoList.size()) { - emit frameChanged(); - received = 0; - } -} - void Browser::futureFinished(QString name, QImage icon){ //Note: this will be called once for every item that loads + //Haven't added the extra files in a directory fix, but that should be easy to do + //Try to load a file with multiple videos and lots of other stuff before any other directory. It crashes for some reason + qDebug() << name << "here"; QIcon *ico = new QIcon(); LFileInfo *info = new LFileInfo(name); if(!icon.isNull() && showThumbs){ QPixmap pix = QPixmap::fromImage(icon); ico->addPixmap(pix); - } - if(ico->isNull()){ - if(videoFormats.contains(name.section(".",-1).toLower())) { - QElapsedTimer loadingTime; - //qDebug() << videoList; - //videoList.add(name); - //qDebug() << "Loading Video for" << name; - //qDebug() << "VIDEO" << info; - QMediaPlayer *player = new QMediaPlayer(0, QMediaPlayer::VideoSurface); - //qDebug() << " - created player" << player; - LVideoSurface *surface = new LVideoSurface(); - //qDebug() << " - Create objects"; - connect(surface, &LVideoSurface::frameReceived, this, [&] (QPixmap pix) { captureFrame(pix, ico); }); - connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); - player->setVideoOutput(surface); - player->setMuted(true); - QMediaResource video = QMediaResource(QUrl("file://"+info->absoluteFilePath())); - video.setResolution(QSize(64, 64)); - player->setMedia(video); - //player->setMedia(QUrl("file://"+info->absoluteFilePath())); - player->play(); - player->pause(); - - //qDebug() << "Started loop"; - loadingTime.start(); - QTimer timeout; - timeout.setSingleShot(true); - timeout.setInterval(5000); - QEventLoop loop; - connect(this, SIGNAL(frameChanged()), &loop, SLOT(quit()), Qt::DirectConnection); - connect(&timeout, SIGNAL(timeout()), &loop, SLOT(quit())); - loop.exec(); - //qDebug() << "Exited loop"; - - qDebug() << loadingTime.elapsed(); - delete player; - delete surface; - }else { - ico = loadIcon(info->iconfile()); + }else if(videoFormats.contains(name.section(".",-1).toLower())) { + if(videoImages.find(name) == videoImages.end()) { + LVideoLabel *mediaLabel = new LVideoLabel(name); + while(mediaLabel->pixmap()->isNull()) { QCoreApplication::processEvents(QEventLoop::AllEvents, 50); } + ico->addPixmap(*(mediaLabel->pixmap())); + videoImages.insert(name, *mediaLabel->pixmap()); + delete mediaLabel; + }else{ + ico->addPixmap(videoImages[name]); } + }else{ + ico = loadIcon(info->iconfile()); } this->emit itemDataAvailable( *ico, info); //qDebug() << " -- done:" << name; @@ -176,12 +129,12 @@ void Browser::futureFinished(QString name, QImage icon){ // PUBLIC SLOTS void Browser::loadDirectory(QString dir, bool force){ if(force){ lastcheck = QDateTime(); } //reset check time to force reloads - videoList.clear(); if(dir.isEmpty()){ dir = currentDir; } //reload current directory if(dir.isEmpty()){ return; } //nothing to do - nothing previously loaded //qDebug() << "Load Directory" << dir; bool dirupdate = true; if(currentDir != dir){ //let the main widget know to clear all current items (completely different dir) + videoImages.clear(); oldFiles.clear(); lastcheck = QDateTime(); //null time emit clearItems(); diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.h b/src-qt5/desktop-utils/lumina-fm/Browser.h index 3254db54..0f4a0abe 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.h +++ b/src-qt5/desktop-utils/lumina-fm/Browser.h @@ -17,6 +17,7 @@ #include #include +#include #include /*class FileItem{ public: @@ -46,7 +47,7 @@ private: QString currentDir; QDateTime lastcheck; QFileSystemWatcher *watcher; - QList videoList; + QMap videoImages; bool showHidden, showThumbs; QStringList imageFormats, videoFormats, oldFiles; QHash mimeIcons; //cache for quickly re-using QIcons @@ -57,8 +58,6 @@ private: private slots: void fileChanged(QString); //tied into the watcher - for file change notifications void dirChanged(QString); // tied into the watcher - for new/removed files in the current dir - void captureFrame(QPixmap, QIcon*); - void stopVideo(QMediaPlayer*, QMediaPlayer::MediaStatus); void futureFinished(QString, QImage); public slots: @@ -75,8 +74,6 @@ signals: //Internal signal for the alternate threads void threadDone(QString, QImage); - - void frameChanged(); }; #endif diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h index a9e58bf3..02fd910d 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h @@ -86,6 +86,7 @@ signals: void contextMenuRequested(); void DataDropped(QString, QStringList); void hasFocus(QString); //ID output + void stopLoop(); //Internal signal void dirChange(QString, bool); //current dir path, force diff --git a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro index 6cb4a537..e27dad25 100644 --- a/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro +++ b/src-qt5/desktop-utils/lumina-fm/lumina-fm.pro @@ -15,7 +15,8 @@ include(../../core/libLumina/LuminaXDG.pri) include(../../core/libLumina/LuminaSingleApplication.pri) include(../../core/libLumina/LuminaThemes.pri) include(../../core/libLumina/ExternalProcess.pri) -include(../../core/libLumina/LVideoSurface.pri) +#include(../../core/libLumina/LVideoSurface.pri) +include(../../core/libLumina/LVideoLabel.pri) SOURCES += main.cpp \ MainUI.cpp \ -- cgit From 7a3e9e46423d999d47e19b26e910c849028599de Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 18 Oct 2017 11:58:59 -0400 Subject: Another quick checkpoint for Lumina 2 files. Nothing too spectacular yet - still in the experimental stage for the QML usage. --- src-qt5/core/libLumina/LuminaXDG.cpp | 8 ++--- src-qt5/core/lumina-desktop-unified/LSession.cpp | 12 +++---- .../src-desktop/RootWindow.cpp | 21 +++++++++--- .../src-desktop/RootWindow.h | 2 ++ src-qt5/src-cpp/RootDesktopObject.cpp | 6 ++++ src-qt5/src-cpp/RootDesktopObject.h | 3 +- src-qt5/src-qml/RootDesktop.qml | 40 +++++++++++++++------- 7 files changed, 63 insertions(+), 29 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index ab1000ab..fdf51a11 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -664,11 +664,11 @@ LFileInfo::LFileInfo(){ LFileInfo::LFileInfo(QString filepath){ //overloaded contructor this->setFile(filepath); loadExtraInfo(); -} +} LFileInfo::LFileInfo(QFileInfo info){ //overloaded contructor this->swap(info); //use the given QFileInfo without re-loading it loadExtraInfo(); -} +} //Functions for accessing the extra information // -- Return the mimetype for the file @@ -683,7 +683,7 @@ QString LFileInfo::iconfile(){ return icon; }else{ if(!mime.isEmpty()){ - QString tmp = mime; + QString tmp = mime; tmp.replace("/","-"); return tmp; }else if(this->isExecutable()){ @@ -696,7 +696,7 @@ QString LFileInfo::iconfile(){ // -- Check if this is an XDG desktop file bool LFileInfo::isDesktopFile(){ if(desk==0){ return false; } - return (!desk->filePath.isEmpty()); + return (!desk->filePath.isEmpty()); } // -- Allow access to the XDG desktop data structure diff --git a/src-qt5/core/lumina-desktop-unified/LSession.cpp b/src-qt5/core/lumina-desktop-unified/LSession.cpp index cc754005..426b91b4 100644 --- a/src-qt5/core/lumina-desktop-unified/LSession.cpp +++ b/src-qt5/core/lumina-desktop-unified/LSession.cpp @@ -104,7 +104,7 @@ void LSession::setupSession(){ splash.showScreen("user"); if(DEBUG){ qDebug() << " - Init User Files:" << timer->elapsed();} //checkUserFiles(); //adds these files to the watcher as well - + Lumina::ROOTWIN->start(); //Initialize the internal variables //DESKTOPS.clear(); @@ -116,7 +116,6 @@ void LSession::setupSession(){ if(DEBUG){ qDebug() << " - Populate App List:" << timer->elapsed();} Lumina::APPLIST->updateList(); //appmenu = new AppMenu(); - splash.showScreen("menus"); //if(DEBUG){ qDebug() << " - Init SettingsMenu:" << timer->elapsed();} //settingsmenu = new SettingsMenu(); @@ -129,12 +128,13 @@ void LSession::setupSession(){ QList scrns= QApplication::screens(); for(int i=0; iname(); - RootDesktopObject::instance()->ChangeWallpaper(scrns[i]->name(), LOS::LuminaShare()+"desktop-background.jpg"); + RootDesktopObject::instance()->ChangeWallpaper(scrns[i]->name(),QUrl::fromLocalFile(LOS::LuminaShare()+"desktop-background.jpg").toString() ); } - //Lumina::ROOTWIN->start(); Lumina::NWS->setRoot_numberOfWorkspaces(QStringList() << "one" << "two"); Lumina::NWS->setRoot_currentWorkspace(0); + if(DEBUG){ qDebug() << " - Create Desktop Context Menu"; } + /*DesktopContextMenu *cmenu = new DesktopContextMenu(Lumina::ROOTWIN); connect(cmenu, SIGNAL(showLeaveDialog()), this, SLOT(StartLogout()) ); cmenu->start();*/ @@ -228,8 +228,8 @@ void LSession::setupGlobalConnections(){ //Root window connections connect(Lumina::ROOTWIN, SIGNAL(RegisterVirtualRoot(WId)), Lumina::NWS, SLOT(RegisterVirtualRoot(WId)) ); connect(Lumina::ROOTWIN, SIGNAL(RootResized(QRect)), Lumina::NWS, SLOT(setRoot_desktopGeometry(QRect)) ); - connect(Lumina::ROOTWIN, SIGNAL(MouseMoved()), Lumina::SS, SLOT(newInputEvent()) ); - connect(Lumina::ROOTWIN, SIGNAL(startLogout()), this, SLOT(StartLogout()) ); + connect(RootDesktopObject::instance(), SIGNAL(mouseMoved()), Lumina::SS, SLOT(newInputEvent()) ); + connect(RootDesktopObject::instance(), SIGNAL(startLogout()), this, SLOT(StartLogout()) ); //Native Window Class connections connect(Lumina::NEF, SIGNAL(WindowCreated(WId)), Lumina::NWS, SLOT(NewWindowDetected(WId))); 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 c0710bbc..2aac6f3e 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp @@ -6,7 +6,7 @@ //=========================================== #include "RootWindow.h" -RootWindow::RootWindow(){ +RootWindow::RootWindow() : QObject(){ root_win = QWindow::fromWinId( QX11Info::appRootWindow() ); // root_view = new QQuickView(root_win); //make it a child of the root window root_obj = RootDesktopObject::instance(); @@ -16,8 +16,7 @@ RootWindow::RootWindow(){ //Now setup the QQuickView root_view->setResizeMode(QQuickView::SizeRootObjectToView); root_view->engine()->rootContext()->setContextProperty("RootObject", root_obj); - root_view->setSource(QUrl("qrc:///qml/RootDesktop")); - root_view->show(); + RootDesktopObject::RegisterType(); //make sure object classes are registered with the QML subsystems } RootWindow::~RootWindow(){ @@ -25,9 +24,21 @@ RootWindow::~RootWindow(){ root_obj->deleteLater(); } +void RootWindow::start(){ + root_view->setSource(QUrl("qrc:///qml/RootDesktop")); + root_win->show(); + root_view->show(); +} + void RootWindow::syncRootSize(){ - if(root_win->width() != root_view->width() || root_win->height() != root_view->height()){ - root_view->setGeometry(0, 0, root_win->width(), root_win->height() ); + //qDebug() << "Sync Root Size:" << root_win->width() << root_win->height() << root_view->geometry(); + QList screens = QApplication::screens(); + QRect unif; + for(int i=0; igeometry()); } + if(unif.width() != root_view->width() || unif.height() != root_view->height()){ + root_view->setGeometry(0, 0, unif.width(), unif.height() ); emit RootResized(root_view->geometry()); } + root_obj->updateScreens(); + //qDebug() << " - after:" << root_view->geometry(); } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h index 1050ba21..ba489465 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.h @@ -19,6 +19,8 @@ public: RootWindow(); ~RootWindow(); + void start(); + public slots: void syncRootSize(); diff --git a/src-qt5/src-cpp/RootDesktopObject.cpp b/src-qt5/src-cpp/RootDesktopObject.cpp index e7873991..d151653b 100644 --- a/src-qt5/src-cpp/RootDesktopObject.cpp +++ b/src-qt5/src-cpp/RootDesktopObject.cpp @@ -9,6 +9,7 @@ #include #include +#include // === PUBLIC === RootDesktopObject::RootDesktopObject(QObject *parent) : QObject(parent){ @@ -39,6 +40,10 @@ void RootDesktopObject::logout(){ emit startLogout(); } +void RootDesktopObject::mousePositionChanged(){ + emit mouseMoved(); +} + // === PUBLIC SLOTS === void RootDesktopObject::updateScreens(){ QList scrns = QApplication::screens(); @@ -53,6 +58,7 @@ void RootDesktopObject::updateScreens(){ //Delete any leftover objects for(int i=0; ideleteLater(); } s_objects = tmp; + emit screensChanged(); } void RootDesktopObject::ChangeWallpaper(QString screen, QString value){ diff --git a/src-qt5/src-cpp/RootDesktopObject.h b/src-qt5/src-cpp/RootDesktopObject.h index 0c280c2a..4bc568d3 100644 --- a/src-qt5/src-cpp/RootDesktopObject.h +++ b/src-qt5/src-cpp/RootDesktopObject.h @@ -33,7 +33,7 @@ public: //QML Access Functions Q_INVOKABLE void logout(); - + Q_INVOKABLE void mousePositionChanged(); private: QList s_objects; @@ -46,6 +46,7 @@ private slots: signals: void screensChanged(); void startLogout(); + void mouseMoved(); }; #endif diff --git a/src-qt5/src-qml/RootDesktop.qml b/src-qt5/src-qml/RootDesktop.qml index b9d62894..a2576f2e 100644 --- a/src-qt5/src-qml/RootDesktop.qml +++ b/src-qt5/src-qml/RootDesktop.qml @@ -15,8 +15,11 @@ // root->setResizeMode(QQuickView::SizeRootObjectToView); // root->engine()->rootContext()->setContextProperty("RootObject", rootobj); //=========================================== -import QtQuick 2.0 +import QtQuick 2.2 import QtQuick.Window 2.2 +import QtQuick.Controls 1.4 + +import "." import Lumina.Backend.RootDesktopObject 2.0 import Lumina.Backend.ScreenObject 2.0 @@ -28,22 +31,33 @@ Rectangle { //Setup the right-click context menu MouseArea { anchors.fill: rootCanvas - acceptedButton: Qt.RightButton - onClicked: { contextMenu.open() } + acceptedButtons: Qt.RightButton + onClicked: { + //contextMenu.x = mouseX + //contextMenu.y = mouseY + contextMenu.popup() + } + onPositionChanged: { + RootObject.mousePositionChanged() + } } //Create the context menu itself Menu { id: contextMenu - + //closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside MenuItem { - test: qtTr("Logout") - indicator: Image{ + text: "Logout" + iconName: "system-logout" + /*indicator: Image{ asynchronous: true - autoTransform: true + //autoTransform: true source: "image://theme/system-logout" + }*/ + onTriggered: { + RootObject.logout() + //contextMenu.close() } - onTriggered: RootObject.logout() } } @@ -51,14 +65,14 @@ Rectangle { Repeater{ model: RootObject.screens AnimatedImage { - id: ("screen_"+modelData.name) asynchronous: true clip: true source: modelData.background - x: modelData.screen.virtualX - y: modelData.screen.virtualY - width: modelData.screen.width - height: modelData.screen.height + x: modelData.x + y: modelData.y + z: 0+index + width: modelData.width + height: modelData.height } } } -- cgit From e5f8846fd775269314e5be502261284b9183205e Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 18 Oct 2017 12:10:10 -0400 Subject: Make LVideoLabel thread-safe. Couple quick fixes for the Browser class in lumina-fm too (minor cleanup). --- src-qt5/core/libLumina/LVideoLabel.cpp | 31 ++++++++++++++++------------- src-qt5/core/libLumina/LVideoLabel.h | 11 +++++++--- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 4 ++-- 3 files changed, 27 insertions(+), 19 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp index 3b2ce468..dcc0ad58 100644 --- a/src-qt5/core/libLumina/LVideoLabel.cpp +++ b/src-qt5/core/libLumina/LVideoLabel.cpp @@ -1,16 +1,28 @@ #include "LVideoLabel.h" - +#include LVideoLabel::LVideoLabel(QString file, QWidget *parent) : QLabel(parent) { this->setScaledContents(true); - mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); - thumbnail = QPixmap(); - this->setPixmap(thumbnail); + this->setPixmap(thumbnail); //blank pixmap by default entered = false; + filepath = file; + QTimer::singleShot(0, this, SLOT(initializeBackend()) ); +} + +LVideoLabel::~LVideoLabel() { + +} + +void LVideoLabel::setShrinkPixmap(bool shrink) { + this->shrink = shrink; +} + +void LVideoLabel::initializeBackend(){ + mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); surface = new LVideoSurface(this); mediaPlayer->setVideoOutput(surface); mediaPlayer->setPlaybackRate(3); mediaPlayer->setMuted(true); - mediaPlayer->setMedia(QUrl("file://" + file)); + mediaPlayer->setMedia(QUrl::fromLocalFile(filepath)); mediaPlayer->play(); mediaPlayer->pause(); @@ -19,15 +31,6 @@ LVideoLabel::LVideoLabel(QString file, QWidget *parent) : QLabel(parent) { this->connect(this, SIGNAL(rollOver()), surface, SLOT(switchRollOver())); } -LVideoLabel::~LVideoLabel() { - mediaPlayer->deleteLater(); - delete surface; -} - -void LVideoLabel::setShrinkPixmap(bool shrink) { - this->shrink = shrink; -} - void LVideoLabel::stopVideo(QPixmap pix) { if(!entered) { emit frameReceived(pix); diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h index fa590e5a..110e3305 100644 --- a/src-qt5/core/libLumina/LVideoLabel.h +++ b/src-qt5/core/libLumina/LVideoLabel.h @@ -1,5 +1,5 @@ -#ifndef LVIDEOLABEL_H -#define LVIDEOLABEL_H +#ifndef LVIDEOLABEL_H +#define LVIDEOLABEL_H #include #include @@ -13,21 +13,26 @@ class LVideoLabel : public QLabel { LVideoLabel(QString, QWidget* parent=NULL); ~LVideoLabel(); void setShrinkPixmap(bool); - + protected: void enterEvent(QEvent*); void leaveEvent(QEvent*); + signals: void rollOver(); void frameReceived(QPixmap); + private slots: + void initializeBackend(); void stopVideo(QPixmap); void setDuration(QMediaPlayer::MediaStatus); + private: QMediaPlayer *mediaPlayer; LVideoSurface *surface; QPixmap thumbnail; bool entered; bool shrink; + QString filepath; }; #endif diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index d829fff0..a68b8580 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -103,13 +103,13 @@ void Browser::futureFinished(QString name, QImage icon){ //Note: this will be called once for every item that loads //Haven't added the extra files in a directory fix, but that should be easy to do //Try to load a file with multiple videos and lots of other stuff before any other directory. It crashes for some reason - qDebug() << name << "here"; + //qDebug() << name << "here"; QIcon *ico = new QIcon(); LFileInfo *info = new LFileInfo(name); if(!icon.isNull() && showThumbs){ QPixmap pix = QPixmap::fromImage(icon); ico->addPixmap(pix); - }else if(videoFormats.contains(name.section(".",-1).toLower())) { + }else if(info->isVideo() && showThumbs) { if(videoImages.find(name) == videoImages.end()) { LVideoLabel *mediaLabel = new LVideoLabel(name); while(mediaLabel->pixmap()->isNull()) { QCoreApplication::processEvents(QEventLoop::AllEvents, 50); } -- cgit From f7087ae6823c95ff899f35c88fa81516108148f6 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 18 Oct 2017 12:16:50 -0400 Subject: Add a semi-functional "VideoItemWidget" class to lumina-fm sources (not tied to build). This is a mostly-complete implementation of a roll-over video thumbnail widget. --- src-qt5/desktop-utils/lumina-fm/VideoItemWidget.h | 144 ++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src-qt5/desktop-utils/lumina-fm/VideoItemWidget.h (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/VideoItemWidget.h b/src-qt5/desktop-utils/lumina-fm/VideoItemWidget.h new file mode 100644 index 00000000..894394d4 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/VideoItemWidget.h @@ -0,0 +1,144 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2016, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_VIDEO_ITEM_WIDGET_H +#define _LUMINA_VIDEO_ITEM_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class RolloverVideoWidget : public QVideoWidget{ + Q_OBJECT +public: + RolloverVideoWidget(QWidget *parent = 0) : QVideoWidget(parent){ + this->setMouseTracking(true); + } +signals: + void OverWidget(); + void NotOverWidget(); + +protected: + /*void mouseMoveEvent(QMouseEvent *ev){ + QWidget::mouseMoveEvent(ev); + qDebug() << "Got video rollover"; + emit OverWidget(); + }*/ + void enterEvent(QEvent *ev){ + QWidget::enterEvent(ev); + qDebug() << "Got video enter"; + emit OverWidget(); + } + void leaveEvent(QEvent *ev){ + QWidget::leaveEvent(ev); + if(!this->underMouse()){ + qDebug() << "Got video leave"; + emit NotOverWidget(); + } + } +}; + +class VideoItemWidget : public QWidget{ + Q_OBJECT +private: + QLabel *textLabel; + QMediaPlayer *mplayer; + LVideoSurface *vwidget; + QString file, text; + QSize fixedsize; + +public: + VideoItemWidget(QString filepath, QWidget *parent = 0) : QWidget(parent){ + file = filepath; + text = filepath.section("/",-1); + textLabel = 0; + mplayer = 0; + vwidget = 0; + this->setMouseTracking(true); + QTimer::singleShot(5, this, SLOT(setupPlayer()) ); //make sure this creation routine is thread-safe + } + ~VideoItemWidget(){ mplayer->stop(); } + + //Optional overloads - it will try to automatically adjust as needed + void setText(QString txt){ + text = txt; + if(textLabel!=0){ + textLabel->setText(txt); + textLabel->setVisible( !txt.isEmpty() ); + } + } + void setIconSize(QSize sz){ + fixedsize = sz; + if(vwidget!=0 && fixedsize.isValid()){ vwidget->setFixedSize(sz); } + } + +private slots: + void setupPlayer(){ + textLabel = new QLabel(this); + vwidget = new LVideoSurface(this); //RolloverVideoWidget(this); + vwidget->setAspectRatioMode(Qt::IgnoreAspectRatio); + if(fixedsize.isValid()){ vwidget->setFixedSize(fixedsize); } + else{ vwidget->setMinimumSize(QSize(16,16)); } + mplayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); + mplayer->setVideoOutput(vwidget); + mplayer->setPlaybackRate(3); // 3x playback speed + mplayer->setMuted(true); + QHBoxLayout *tmpL = new QHBoxLayout(this); + tmpL->setAlignment(Qt::AlignLeft | Qt::AlignCenter); + tmpL->addWidget(vwidget); + tmpL->addWidget(textLabel); + tmpL->setStretchFactor(textLabel, 1); //make sure this always occupies all extra space + //connect(mplayer, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64)) ); + connect(mplayer, SIGNAL(durationChanged(qint64)), this, SLOT(stopVideo()) ); + //connect(vwidget, SIGNAL(OverWidget()), this, SLOT(startVideo()) ); + //connect(vwidget, SIGNAL(NotOverWidget()), this, SLOT(stopVideo()) ); + //Now load the file + textLabel->setText(text); + mplayer->setMedia(QUrl::fromLocalFile(file) ); + mplayer->play(); + } + void durationChanged(qint64 max){ + qDebug() << "Got Duration Changed:" << max; + mplayer->setPosition( qRound(max/2.0)); + } + + void startVideo(){ + if(mplayer==0){ return; } + if(mplayer->state()!=QMediaPlayer::PlayingState){ + qDebug() << "Start Video"; + mplayer->setPosition(0); + mplayer->play(); + } + } + + void stopVideo(){ + if(mplayer==0){ return; } + if(mplayer->state()==QMediaPlayer::PlayingState){ + qDebug() << "Stop Video"; + mplayer->pause(); + mplayer->setPosition( qRound(mplayer->duration()/2.0) ); + } + } + +protected: + void resizeEvent(QResizeEvent *ev){ + if(vwidget!=0 && !fixedsize.isValid()){ vwidget->setFixedSize( QSize(ev->size().height(), ev->size().height()) ); } + } + /*void mouseMoveEvent(QMouseEvent *ev){ + QWidget::mouseMoveEvent(ev); + stopVideo(); //not over the video widget any more + }*/ +}; + +#endif -- cgit From 3a38773ce20620610e87c84c40ebfd6d2f478203 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Sat, 21 Oct 2017 17:48:29 -0400 Subject: Finished video thumbnails and roll over playback for lumina-fm and lumina-fileinfo --- src-qt5/core/libLumina/LVideoLabel.cpp | 25 ++++++++++++------ src-qt5/core/libLumina/LVideoLabel.h | 11 ++++---- src-qt5/core/libLumina/LVideoLabel.pri | 2 ++ src-qt5/core/libLumina/LVideoWidget.cpp | 28 ++++++++++++++++++++ src-qt5/core/libLumina/LVideoWidget.h | 21 +++++++++++++++ src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 2 +- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 7 +++-- src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp | 31 ++++++++++++++++++++--- src-qt5/desktop-utils/lumina-fm/BrowserWidget.h | 1 + 9 files changed, 106 insertions(+), 22 deletions(-) create mode 100644 src-qt5/core/libLumina/LVideoWidget.cpp create mode 100644 src-qt5/core/libLumina/LVideoWidget.h (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp index dcc0ad58..b90cff66 100644 --- a/src-qt5/core/libLumina/LVideoLabel.cpp +++ b/src-qt5/core/libLumina/LVideoLabel.cpp @@ -1,15 +1,17 @@ #include "LVideoLabel.h" -#include + LVideoLabel::LVideoLabel(QString file, QWidget *parent) : QLabel(parent) { - this->setScaledContents(true); - this->setPixmap(thumbnail); //blank pixmap by default + thumbnail = QPixmap(); entered = false; + shrink = true; filepath = file; + QTimer::singleShot(0, this, SLOT(initializeBackend()) ); } LVideoLabel::~LVideoLabel() { - + mediaPlayer->deleteLater(); + surface->deleteLater(); } void LVideoLabel::setShrinkPixmap(bool shrink) { @@ -22,6 +24,7 @@ void LVideoLabel::initializeBackend(){ mediaPlayer->setVideoOutput(surface); mediaPlayer->setPlaybackRate(3); mediaPlayer->setMuted(true); + mediaPlayer->setMedia(QUrl::fromLocalFile(filepath)); mediaPlayer->play(); mediaPlayer->pause(); @@ -36,10 +39,10 @@ void LVideoLabel::stopVideo(QPixmap pix) { emit frameReceived(pix); if(thumbnail.isNull()) thumbnail = pix; - this->setPixmap((shrink) ? thumbnail.scaledToHeight(64) : thumbnail); + this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); mediaPlayer->pause(); }else { - this->setPixmap((shrink) ? pix.scaledToHeight(64) : pix); + this->setPixmap(pix.scaled(this->size(),Qt::IgnoreAspectRatio)); } } @@ -50,17 +53,23 @@ void LVideoLabel::setDuration(QMediaPlayer::MediaStatus status) { } } +void LVideoLabel::resizeEvent(QResizeEvent *event) { + if(!thumbnail.isNull()) + this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); + QLabel::resizeEvent(event); +} + void LVideoLabel::enterEvent(QEvent *event) { entered=true; emit rollOver(); mediaPlayer->setPosition(0); mediaPlayer->play(); - QLabel::enterEvent(event); + QWidget::enterEvent(event); } void LVideoLabel::leaveEvent(QEvent *event) { entered=false; mediaPlayer->setPosition(mediaPlayer->duration() / 2); emit rollOver(); - QLabel::leaveEvent(event); + QWidget::leaveEvent(event); } diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h index 110e3305..8c544b16 100644 --- a/src-qt5/core/libLumina/LVideoLabel.h +++ b/src-qt5/core/libLumina/LVideoLabel.h @@ -3,11 +3,11 @@ #include #include +#include +#include #include "LVideoSurface.h" -//class LVideoSurface; - -class LVideoLabel : public QLabel { +class LVideoLabel : public QLabel{ Q_OBJECT public: LVideoLabel(QString, QWidget* parent=NULL); @@ -17,13 +17,14 @@ class LVideoLabel : public QLabel { protected: void enterEvent(QEvent*); void leaveEvent(QEvent*); + void resizeEvent(QResizeEvent*); signals: void rollOver(); void frameReceived(QPixmap); private slots: - void initializeBackend(); + void initializeBackend(); void stopVideo(QPixmap); void setDuration(QMediaPlayer::MediaStatus); @@ -33,6 +34,6 @@ class LVideoLabel : public QLabel { QPixmap thumbnail; bool entered; bool shrink; - QString filepath; + QString filepath; }; #endif diff --git a/src-qt5/core/libLumina/LVideoLabel.pri b/src-qt5/core/libLumina/LVideoLabel.pri index 384b3aae..06395c8d 100644 --- a/src-qt5/core/libLumina/LVideoLabel.pri +++ b/src-qt5/core/libLumina/LVideoLabel.pri @@ -2,8 +2,10 @@ QT *= multimedia HEADERS *= $${PWD}/LVideoLabel.h HEADERS *= $${PWD}/LVideoSurface.h +HEADERS *= $${PWD}/LVideoWidget.h SOURCES *= $${PWD}/LVideoLabel.cpp SOURCES *= $${PWD}/LVideoSurface.cpp +SOURCES *= $${PWD}/LVideoWidget.cpp INCLUDEPATH *= ${PWD} diff --git a/src-qt5/core/libLumina/LVideoWidget.cpp b/src-qt5/core/libLumina/LVideoWidget.cpp new file mode 100644 index 00000000..14490484 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoWidget.cpp @@ -0,0 +1,28 @@ +#include "LVideoWidget.h" + +LVideoWidget::LVideoWidget(QString file, QSize iconSize, QWidget *parent) : QWidget(parent) { + flag = false; + iconLabel = new LVideoLabel(file, parent); + textLabel = new QLabel(parent); + + layout = new QHBoxLayout(this); + layout->setAlignment(Qt::AlignLeft | Qt::AlignCenter); + layout->addWidget(iconLabel); + layout->addWidget(textLabel); + layout->setStretchFactor(textLabel, 1); //make sure this always occupies all extra space + + textLabel->setText(file.section("/", -1)); + iconLabel->setFixedSize(iconSize); + iconLabel->setVisible(true); + textLabel->setVisible(true); +} + +LVideoWidget::~LVideoWidget() { + delete iconLabel; + delete textLabel; + delete layout; +} + +void LVideoWidget::setIconSize(QSize iconSize) { + iconLabel->setFixedSize(iconSize); +} diff --git a/src-qt5/core/libLumina/LVideoWidget.h b/src-qt5/core/libLumina/LVideoWidget.h new file mode 100644 index 00000000..c239a697 --- /dev/null +++ b/src-qt5/core/libLumina/LVideoWidget.h @@ -0,0 +1,21 @@ +#ifndef LVIDEOWIDGET_H +#define LVIDEOWIDGET_H + +#include "LVideoLabel.h" +#include +#include + +class LVideoWidget : public QWidget { + Q_OBJECT + public: + LVideoWidget(QString, QSize, QWidget* parent=NULL); + ~LVideoWidget(); + void setIconSize(QSize); + + private: + bool flag; + LVideoLabel *iconLabel; + QLabel *textLabel; + QHBoxLayout *layout; +}; +#endif diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index 58ef8cbd..fb55ad99 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -89,7 +89,7 @@ void MainUI::LoadFile(QString path, QString type){ }else if(INFO->isVideo()){ ui->label_file_icon->hide(); LVideoLabel *mediaLabel = new LVideoLabel(INFO->absoluteFilePath(), ui->tab_file); - mediaLabel->setShrinkPixmap(true); + mediaLabel->setFixedSize(64,64); ui->formLayout->replaceWidget(ui->label_file_icon, mediaLabel); }else{ ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index a68b8580..10c2567b 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -20,7 +20,6 @@ Browser::Browser(QObject *parent) : QObject(parent){ showHidden = false; showThumbs = false; imageFormats = LUtils::imageExtensions(false); //lowercase suffixes - videoFormats = LUtils::videoExtensions(); //lowercase suffixes //connect(surface, SIGNAL(frameReceived(QImage)), this, SLOT(captureFrame(QImage))); //connect(player, &QMediaPlayer::mediaStatusChanged, this, [&]{ stopVideo(player, player->mediaStatus()); }); connect(this, SIGNAL(threadDone(QString, QImage)), this, SLOT(futureFinished(QString, QImage))); //will always be between different threads @@ -109,7 +108,7 @@ void Browser::futureFinished(QString name, QImage icon){ if(!icon.isNull() && showThumbs){ QPixmap pix = QPixmap::fromImage(icon); ico->addPixmap(pix); - }else if(info->isVideo() && showThumbs) { + /*}else if(info->isVideo() && showThumbs) { if(videoImages.find(name) == videoImages.end()) { LVideoLabel *mediaLabel = new LVideoLabel(name); while(mediaLabel->pixmap()->isNull()) { QCoreApplication::processEvents(QEventLoop::AllEvents, 50); } @@ -118,7 +117,7 @@ void Browser::futureFinished(QString name, QImage icon){ delete mediaLabel; }else{ ico->addPixmap(videoImages[name]); - } + }*/ }else{ ico = loadIcon(info->iconfile()); } @@ -134,7 +133,7 @@ void Browser::loadDirectory(QString dir, bool force){ //qDebug() << "Load Directory" << dir; bool dirupdate = true; if(currentDir != dir){ //let the main widget know to clear all current items (completely different dir) - videoImages.clear(); + //videoImages.clear(); oldFiles.clear(); lastcheck = QDateTime(); //null time emit clearItems(); diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp index d2c07648..a7b07b47 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp @@ -12,6 +12,7 @@ #include #include +#include BrowserWidget::BrowserWidget(QString objID, QWidget *parent) : QWidget(parent){ //Setup the Widget/UI @@ -38,6 +39,7 @@ BrowserWidget::~BrowserWidget(){ } void BrowserWidget::changeDirectory(QString dir){ + videoMap.clear(); if(BROWSER->currentDirectory()==dir){ return; } //already on this directory //qDebug() << "Change Directory:" << dir << historyList; @@ -125,6 +127,12 @@ void BrowserWidget::setThumbnailSize(int px){ larger = treeWidget->iconSize().height() < px; treeWidget->setIconSize(QSize(px,px)); } + for(QString file : videoMap.uniqueKeys()) { + QTreeWidgetItem *it = videoMap[file]; + LVideoWidget *widget = (LVideoWidget*)treeWidget->itemWidget(it, 0); + widget->setIconSize(treeWidget->iconSize()); + treeWidget->setItemWidget(it, 0, widget); + } //qDebug() << "Changing Icon Size:" << px << larger; if(BROWSER->currentDirectory().isEmpty() || !larger ){ return; } //don't need to reload icons unless the new size is larger emit dirChange("", larger); @@ -326,15 +334,30 @@ void BrowserWidget::itemDataAvailable(QIcon ico, LFileInfo *info){ treeWidget->addTopLevelItem(it); } }else{ - if( ! treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).isEmpty() ){ it = treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).first(); } - else{ + if( ! treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).isEmpty() ) { + it = treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).first(); + }else if(info->isVideo() && videoMap.find(info->absoluteFilePath()) == videoMap.end()){ it = new CQTreeWidgetItem(treeWidget); - it->setText(0, info->fileName() ); //name (0) treeWidget->addTopLevelItem(it); + LVideoWidget *widget = new LVideoWidget(info->absoluteFilePath(), treeWidget->iconSize(), treeWidget); + videoMap.insert(info->absoluteFilePath(), it); + treeWidget->setItemWidget(it, 0, widget); + }else if(info->isVideo()){ + it = videoMap[info->absoluteFilePath()]; + if(treeWidget->itemWidget(it, 0) != 0) { + LVideoWidget *widget = (LVideoWidget*)treeWidget->itemWidget(it, 0); + widget->setIconSize(treeWidget->iconSize()); + treeWidget->setItemWidget(it, 0, widget); + } + }else{ + it = new CQTreeWidgetItem(treeWidget); + treeWidget->addTopLevelItem(it); + it->setText(0, info->fileName() ); //name (0) } } //Now set/update all the data - it->setIcon(0, ico); + if(!info->isVideo()) + it->setIcon(0, ico); it->setText(1, info->isDir() ? "" : LUtils::BytesToDisplaySize(info->size()) ); //size (1) it->setText(2, info->mimetype() ); //type (2) it->setText(3, DTtoString(info->lastModified() )); //modification date (3) diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h index 02fd910d..585aaa82 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h @@ -23,6 +23,7 @@ private: int numItems; //used for checking if all the items have loaded yet QString ID, statustip; QStringList date_format, historyList; + QMap videoMap; bool freshload; //The drag and drop brower widgets -- cgit From b4bb314391b9d363944b8de91ea2c660675fabc6 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Sat, 21 Oct 2017 19:19:28 -0400 Subject: Added some testing code for issues with directories having >10 videos --- src-qt5/core/libLumina/LVideoLabel.cpp | 34 ++++++++++++++++++++++++++++++---- src-qt5/core/libLumina/LVideoLabel.h | 1 + 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp index b90cff66..af23330c 100644 --- a/src-qt5/core/libLumina/LVideoLabel.cpp +++ b/src-qt5/core/libLumina/LVideoLabel.cpp @@ -1,4 +1,5 @@ #include "LVideoLabel.h" +#include LVideoLabel::LVideoLabel(QString file, QWidget *parent) : QLabel(parent) { thumbnail = QPixmap(); @@ -27,13 +28,14 @@ void LVideoLabel::initializeBackend(){ mediaPlayer->setMedia(QUrl::fromLocalFile(filepath)); mediaPlayer->play(); - mediaPlayer->pause(); this->connect(surface, SIGNAL(frameReceived(QPixmap)), this, SLOT(stopVideo(QPixmap))); + this->connect(mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(stateChanged(QMediaPlayer::State))); this->connect(mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(setDuration(QMediaPlayer::MediaStatus))); this->connect(this, SIGNAL(rollOver()), surface, SLOT(switchRollOver())); } + void LVideoLabel::stopVideo(QPixmap pix) { if(!entered) { emit frameReceived(pix); @@ -46,19 +48,42 @@ void LVideoLabel::stopVideo(QPixmap pix) { } } +void LVideoLabel::stateChanged(QMediaPlayer::State state) { + //qDebug() << state; +} + void LVideoLabel::setDuration(QMediaPlayer::MediaStatus status) { - if(status == QMediaPlayer::BufferedMedia) { + //qDebug() << status; + if(status == QMediaPlayer::BufferedMedia && !entered) { //Set duration in the middle to capture the thumbnail mediaPlayer->setPosition(mediaPlayer->duration() / 2); mediaPlayer->play(); - } + }else if(status == QMediaPlayer::EndOfMedia && entered) { //Loop back to the beginning if playback started and at the end of the video + mediaPlayer->setPosition(0); + mediaPlayer->play(); + }else if(status == QMediaPlayer::InvalidMedia){ + mediaPlayer->stop(); + mediaPlayer->play(); + }/*else if(status == QMediaPlayer::LoadingMedia) { + mediaPlayer->pause(); + QTimer timer; + timer.setSingleShot(true); + timer.setInterval(300); + timer.start(); + qDebug() << "Timer Started" << timer.remainingTime(); + while(timer.isActive()) QCoreApplication::processEvents(QEventLoop::AllEvents, 5); + qDebug() << "Timer Finished" << timer.remainingTime(); + mediaPlayer->setPosition(0); + mediaPlayer->play(); + }*/ } void LVideoLabel::resizeEvent(QResizeEvent *event) { - if(!thumbnail.isNull()) + if(!thumbnail.isNull()) //Resize the current pixmap to match the new size this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); QLabel::resizeEvent(event); } +//Start playing the video from the beginning when the mouse enters the label void LVideoLabel::enterEvent(QEvent *event) { entered=true; emit rollOver(); @@ -67,6 +92,7 @@ void LVideoLabel::enterEvent(QEvent *event) { QWidget::enterEvent(event); } +//Stop the video and set the thumbnail back to the middle of the video when the mouse leaves the label void LVideoLabel::leaveEvent(QEvent *event) { entered=false; mediaPlayer->setPosition(mediaPlayer->duration() / 2); diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h index 8c544b16..f368c1a8 100644 --- a/src-qt5/core/libLumina/LVideoLabel.h +++ b/src-qt5/core/libLumina/LVideoLabel.h @@ -27,6 +27,7 @@ class LVideoLabel : public QLabel{ void initializeBackend(); void stopVideo(QPixmap); void setDuration(QMediaPlayer::MediaStatus); + void stateChanged(QMediaPlayer::State); private: QMediaPlayer *mediaPlayer; -- cgit From 02a68b94cd343d1958438dbfccd7258ee76f7eef Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Sat, 21 Oct 2017 19:30:58 -0400 Subject: Added preliminary code to disable video thumbnails with settings --- src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp index a7b07b47..dc00e92f 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp @@ -334,15 +334,22 @@ void BrowserWidget::itemDataAvailable(QIcon ico, LFileInfo *info){ treeWidget->addTopLevelItem(it); } }else{ + if(!BROWSER->showingThumbnails() && videoMap.size() !=0) { + for(QString file : videoMap.keys()) { + QTreeWidgetItem *it = videoMap[file]; + treeWidget->removeItemWidget(it, 0); + } + videoMap.clear(); + } if( ! treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).isEmpty() ) { it = treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).first(); - }else if(info->isVideo() && videoMap.find(info->absoluteFilePath()) == videoMap.end()){ + }else if(info->isVideo() && videoMap.find(info->absoluteFilePath()) == videoMap.end() && BROWSER->showingThumbnails()){ it = new CQTreeWidgetItem(treeWidget); treeWidget->addTopLevelItem(it); LVideoWidget *widget = new LVideoWidget(info->absoluteFilePath(), treeWidget->iconSize(), treeWidget); videoMap.insert(info->absoluteFilePath(), it); treeWidget->setItemWidget(it, 0, widget); - }else if(info->isVideo()){ + }else if(info->isVideo() && BROWSER->showingThumbnails()){ it = videoMap[info->absoluteFilePath()]; if(treeWidget->itemWidget(it, 0) != 0) { LVideoWidget *widget = (LVideoWidget*)treeWidget->itemWidget(it, 0); @@ -356,7 +363,7 @@ void BrowserWidget::itemDataAvailable(QIcon ico, LFileInfo *info){ } } //Now set/update all the data - if(!info->isVideo()) + if(!info->isVideo() || (info->isVideo() && !BROWSER->showingThumbnails())) it->setIcon(0, ico); it->setText(1, info->isDir() ? "" : LUtils::BytesToDisplaySize(info->size()) ); //size (1) it->setText(2, info->mimetype() ); //type (2) -- cgit From 13e92da7516fed2eb08599924c76b06f5bd8af58 Mon Sep 17 00:00:00 2001 From: q5sys Date: Mon, 23 Oct 2017 17:14:24 -0400 Subject: remove unneeded whitespace --- src-qt5/desktop-utils/lumina-xdg-entry/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-xdg-entry/mainwindow.cpp b/src-qt5/desktop-utils/lumina-xdg-entry/mainwindow.cpp index 7b34935e..1ad6edcd 100644 --- a/src-qt5/desktop-utils/lumina-xdg-entry/mainwindow.cpp +++ b/src-qt5/desktop-utils/lumina-xdg-entry/mainwindow.cpp @@ -1,7 +1,7 @@ //=========================================== // Copyright (c) 2017, q5sys (JT) // Available under the MIT license -// See the LICENSE file for full details +// See the LICENSE file for full details //=========================================== #include "mainwindow.h" -- cgit From 8edbaac8f41029364d68ec3d48183fa43921317c Mon Sep 17 00:00:00 2001 From: q5sys Date: Mon, 23 Oct 2017 17:36:14 -0400 Subject: removing whitespace --- src-qt5/desktop-utils/lumina-archiver/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/main.cpp b/src-qt5/desktop-utils/lumina-archiver/main.cpp index 40cd7967..01e7bda1 100644 --- a/src-qt5/desktop-utils/lumina-archiver/main.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/main.cpp @@ -15,7 +15,7 @@ int main(int argc, char *argv[]) { LTHEME::LoadCustomEnvSettings(); QApplication a(argc, argv); - a.setAttribute(Qt::AA_UseHighDpiPixmaps); + a.setAttribute(Qt::AA_UseHighDpiPixmaps); LUtils::LoadTranslation(&a, "l-archiver"); //Now go ahead and setup the app QStringList args; -- cgit From 08d871eeab89f38dcd1717cd6a29dfbbcc6b79b7 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Mon, 23 Oct 2017 17:50:00 -0400 Subject: Fixed issue with setting defaults in lumina-open and cleaned up main.cpp --- src-qt5/core/lumina-open/LFileDialog.cpp | 6 +- src-qt5/core/lumina-open/main.cpp | 277 ++++++++++++++++--------------- 2 files changed, 142 insertions(+), 141 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-open/LFileDialog.cpp b/src-qt5/core/lumina-open/LFileDialog.cpp index ce7c6a6f..dbdb6362 100644 --- a/src-qt5/core/lumina-open/LFileDialog.cpp +++ b/src-qt5/core/lumina-open/LFileDialog.cpp @@ -54,9 +54,9 @@ QString LFileDialog::getDefaultApp(QString extension){ void LFileDialog::setDefaultApp(QString extension, QString appFile){ if(!extension.contains("/")){ extension = LXDG::findAppMimeForFile(appFile); } - //mime type default: set on the system itself - if(appFile.endsWith(".desktop")){ appFile = appFile.section("/",-1); } //only need the relative path - LXDG::setDefaultAppForMime(extension, appFile); + //mime type default: set on the system itself + //if(appFile.endsWith(".desktop")){ appFile = appFile.section("/",-1); } //only need the relative path + LXDG::setDefaultAppForMime(extension, appFile); } // ----------- diff --git a/src-qt5/core/lumina-open/main.cpp b/src-qt5/core/lumina-open/main.cpp index 72d09f42..945f0d1f 100644 --- a/src-qt5/core/lumina-open/main.cpp +++ b/src-qt5/core/lumina-open/main.cpp @@ -29,6 +29,8 @@ #include #include +#define DEBUG 0 + void printUsageInfo(){ qDebug() << "lumina-open: Application launcher for the Lumina Desktop Environment"; qDebug() << "Description: Given a file (with absolute path) or URL, this utility will try to find the appropriate application with which to open the file. If the file is a *.desktop application shortcut, it will just start the application appropriately. It can also perform a few specific system operations if given special flags."; @@ -68,7 +70,7 @@ void showOSD(int argc, char **argv, QString message){ splash.setAlignment(Qt::AlignCenter); - qDebug() << "Display OSD"; + if(DEBUG) qDebug() << "Display OSD"; splash.setText(message); //Make sure it is centered on the current screen QPoint center = App.desktop()->screenGeometry(QCursor::pos()).center(); @@ -89,7 +91,7 @@ void LaunchAutoStart(){ if(cmd.contains("%")){cmd = cmd.remove("%U").remove("%u").remove("%F").remove("%f").remove("%i").remove("%c").remove("%k").simplified(); } //Now run the command if(!cmd.isEmpty()){ - qDebug() << " - Auto-Starting File:" << xdgapps[i]->filePath; + if(DEBUG) qDebug() << " - Auto-Starting File:" << xdgapps[i]->filePath; QProcess::startDetached(cmd); } } @@ -98,130 +100,130 @@ void LaunchAutoStart(){ } QString cmdFromUser(int argc, char **argv, QString inFile, QString extension, QString& path, bool showDLG=false){ - //First check to see if there is a default for this extension - QString defApp; - if(extension=="mimetype"){ + //First check to see if there is a default for this extension + QString defApp; + if(extension=="mimetype"){ //qDebug() << "inFile:" << inFile; QStringList matches = LXDG::findAppMimeForFile(inFile, true).split("::::"); //allow multiple matches - qDebug() << "Mimetype Matches:" << matches; + if(DEBUG) qDebug() << "Mimetype Matches:" << matches; for(int i=0; i 1){ - for(int i=1; i100){ vol=100; } - LOS::setAudioVolume(vol); - showOSD(argc,argv, QString(QObject::tr("Audio Volume %1%")).arg(QString::number(vol)) ); - return; - }else if(QString(argv[i]).simplified() == "-volumedown"){ - int vol = LOS::audioVolume()-5; //decrease 5% - if(vol<0){ vol=0; } - LOS::setAudioVolume(vol); - showOSD(argc,argv, QString(QObject::tr("Audio Volume %1%")).arg(QString::number(vol)) ); - return; - }else if(QString(argv[i]).simplified() == "-brightnessup"){ - int bright = LOS::ScreenBrightness(); - if(bright > 0){ //brightness control available - bright = bright+5; //increase 5% - if(bright>100){ bright = 100; } - LOS::setScreenBrightness(bright); - showOSD(argc,argv, QString(QObject::tr("Screen Brightness %1%")).arg(QString::number(bright)) ); - } - return; - }else if(QString(argv[i]).simplified() == "-brightnessdown"){ - int bright = LOS::ScreenBrightness(); - if(bright > 0){ //brightness control available - bright = bright-5; //decrease 5% - if(bright<0){ bright = 0; } - LOS::setScreenBrightness(bright); - showOSD(argc,argv, QString(QObject::tr("Screen Brightness %1%")).arg(QString::number(bright)) ); - } - return; - }else if( (QString(argv[i]).simplified() =="-action") && (argc>(i+1)) ){ - ActionID = QString(argv[i+1]); - i++; //skip the next input - }else if(QString(argv[i]).simplified()=="-terminal"){ - inFile = LXDG::findDefaultAppForMime("application/terminal"); - break; - }else{ - inFile = QString::fromLocal8Bit(argv[i]); +//Get the input file + //Make sure to load the proper system encoding first + LUtils::LoadTranslation(0,""); //bypass application modification +QString inFile, ActionID; +bool showDLG = false; //flag to bypass any default application setting +if(argc > 1){ + for(int i=1; i100){ vol=100; } +LOS::setAudioVolume(vol); +showOSD(argc,argv, QString(QObject::tr("Audio Volume %1%")).arg(QString::number(vol)) ); +return; + }else if(QString(argv[i]).simplified() == "-volumedown"){ +int vol = LOS::audioVolume()-5; //decrease 5% +if(vol<0){ vol=0; } +LOS::setAudioVolume(vol); +showOSD(argc,argv, QString(QObject::tr("Audio Volume %1%")).arg(QString::number(vol)) ); +return; + }else if(QString(argv[i]).simplified() == "-brightnessup"){ +int bright = LOS::ScreenBrightness(); +if(bright > 0){ //brightness control available + bright = bright+5; //increase 5% + if(bright>100){ bright = 100; } + LOS::setScreenBrightness(bright); + showOSD(argc,argv, QString(QObject::tr("Screen Brightness %1%")).arg(QString::number(bright)) ); +} +return; + }else if(QString(argv[i]).simplified() == "-brightnessdown"){ +int bright = LOS::ScreenBrightness(); +if(bright > 0){ //brightness control available + bright = bright-5; //decrease 5% + if(bright<0){ bright = 0; } + LOS::setScreenBrightness(bright); + showOSD(argc,argv, QString(QObject::tr("Screen Brightness %1%")).arg(QString::number(bright)) ); +} +return; + }else if( (QString(argv[i]).simplified() =="-action") && (argc>(i+1)) ){ + ActionID = QString(argv[i+1]); +i++; //skip the next input + }else if(QString(argv[i]).simplified()=="-terminal"){ + inFile = LXDG::findDefaultAppForMime("application/terminal"); + break; + }else{ + inFile = QString::fromLocal8Bit(argv[i]); break; } } @@ -268,14 +270,14 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat } switch(DF.type){ case XDGDesktop::APP: - qDebug() << "Found .desktop application:" << ActionID; + if(DEBUG) qDebug() << "Found .desktop application:" << ActionID; if(!DF.exec.isEmpty()){ cmd = DF.getDesktopExec(ActionID); - qDebug() << "Got command:" << cmd; + if(DEBUG) qDebug() << "Got command:" << cmd; if(!DF.path.isEmpty()){ path = DF.path; } - watch = DF.startupNotify || !DF.filePath.contains("/xdg/autostart/"); + watch = DF.startupNotify || !DF.filePath.contains("/xdg/autostart/"); }else{ - ShowErrorDialog( argc, argv, QString(QObject::tr("Application shortcut is missing the launching information (malformed shortcut): %1")).arg(inFile) ); + ShowErrorDialog( argc, argv, QString(QObject::tr("Application shortcut is missing the launching information (malformed shortcut): %1")).arg(inFile) ); } break; case XDGDesktop::LINK: @@ -284,11 +286,11 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat inFile = DF.url; cmd.clear(); extension = inFile.section(":",0,0); - if(extension=="file"){ extension = "http"; } //local file URL - Make sure we use the default browser for a LINK type + if(extension=="file"){ extension = "http"; } //local file URL - Make sure we use the default browser for a LINK type extension.prepend("x-scheme-handler/"); - watch = DF.startupNotify || !DF.filePath.contains("/xdg/autostart/"); + watch = DF.startupNotify || !DF.filePath.contains("/xdg/autostart/"); }else{ - ShowErrorDialog( argc, argv, QString(QObject::tr("URL shortcut is missing the URL: %1")).arg(inFile) ); + ShowErrorDialog( argc, argv, QString(QObject::tr("URL shortcut is missing the URL: %1")).arg(inFile) ); } break; case XDGDesktop::DIR: @@ -297,14 +299,14 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat inFile = DF.path; cmd.clear(); extension = "inode/directory"; - watch = DF.startupNotify || !DF.filePath.contains("/xdg/autostart/"); + watch = DF.startupNotify || !DF.filePath.contains("/xdg/autostart/"); }else{ - ShowErrorDialog( argc, argv, QString(QObject::tr("Directory shortcut is missing the path to the directory: %1")).arg(inFile) ); + ShowErrorDialog( argc, argv, QString(QObject::tr("Directory shortcut is missing the path to the directory: %1")).arg(inFile) ); } break; default: - qDebug() << DF.type << DF.name << DF.icon << DF.exec; - ShowErrorDialog( argc, argv, QString(QObject::tr("Unknown type of shortcut : %1")).arg(inFile) ); + if(DEBUG) qDebug() << DF.type << DF.name << DF.icon << DF.exec; + ShowErrorDialog( argc, argv, QString(QObject::tr("Unknown type of shortcut : %1")).arg(inFile) ); } } if(cmd.isEmpty()){ @@ -344,7 +346,7 @@ void getCMD(int argc, char ** argv, QString& binary, QString& args, QString& pat cmd.append(" \""+inFile+"\""); } } - qDebug() << "Found Command:" << cmd << "Extension:" << extension; + if(DEBUG) qDebug() << "Found Command:" << cmd << "Extension:" << extension; //Clean up any leftover "Exec" field codes (should have already been replaced earlier) if(cmd.contains("%")){cmd = cmd.remove("%U").remove("%u").remove("%F").remove("%f").remove("%i").remove("%c").remove("%k").simplified(); } binary = cmd; //pass this string to the calling function @@ -370,7 +372,7 @@ int main(int argc, char **argv){ QMessageBox::warning(0, QObject::tr("Binary Missing"), QString(QObject::tr("Could not find \"%1\". Please ensure it is installed first.")).arg(bin)+"\n\n"+cmd); return 1; } - qDebug() << "[lumina-open] Running Cmd:" << cmd; + if(DEBUG) qDebug() << "[lumina-open] Running Cmd:" << cmd; int retcode = 0; //Provide an override file for never watching running processes. if(watch){ watch = !QFile::exists( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/nowatch" ); } @@ -391,12 +393,12 @@ int main(int argc, char **argv){ }else{ QProcess *p = new QProcess(); p->setProcessEnvironment(QProcessEnvironment::systemEnvironment()); - if(!path.isEmpty() && QFile::exists(path)){ + if(!path.isEmpty() && QFile::exists(path)){ //qDebug() << " - Setting working path:" << path; - p->setWorkingDirectory(path); + p->setWorkingDirectory(path); } p->start(cmd); - + //Now check up on it once every minute until it is finished while(!p->waitForFinished(60000)){ //qDebug() << "[lumina-open] process check:" << p->state(); @@ -410,19 +412,18 @@ int main(int argc, char **argv){ //qDebug() << "[lumina-open] Finished Cmd:" << cmd << retcode << p->exitStatus(); if( QFile::exists("/tmp/.luminastopping") ){ watch = false; } //closing down session - ignore "crashes" (app could have been killed during cleanup) if( (retcode < 0) && watch){ //-1 is used internally for crashed processes - most apps return >=0 - qDebug() << "[lumina-open] Application Error:" << retcode; - //Setup the application - QApplication App(argc, argv); - App.setAttribute(Qt::AA_UseHighDpiPixmaps); - LuminaThemeEngine theme(&App); - LUtils::LoadTranslation(&App,"lumina-open"); + //Setup the application + QApplication App(argc, argv); + App.setAttribute(Qt::AA_UseHighDpiPixmaps); + LuminaThemeEngine theme(&App); + LUtils::LoadTranslation(&App,"lumina-open"); //App.setApplicationName("LuminaOpen"); - QMessageBox dlg(QMessageBox::Critical, QObject::tr("Application Error"), QObject::tr("The following application experienced an error and needed to close:")+"\n\n"+cmd ); - dlg.setWindowFlags(Qt::Window); - if(!log.isEmpty()){ dlg.setDetailedText(log); } - dlg.exec(); - } + QMessageBox dlg(QMessageBox::Critical, QObject::tr("Application Error"), QObject::tr("The following application experienced an error and needed to close:")+"\n\n"+cmd ); + dlg.setWindowFlags(Qt::Window); + if(!log.isEmpty()){ dlg.setDetailedText(log); } + dlg.exec(); + } } return retcode; } -- cgit From 769f269c83a2b9a6bcc6407380fe8c55e30b2476 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Mon, 23 Oct 2017 20:49:43 -0400 Subject: Added some test qml file for the video screensaver --- src-qt5/src-qml/test/File.qml | 21 ++++++++++++++++++ src-qt5/src-qml/test/Video.qml | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src-qt5/src-qml/test/File.qml create mode 100644 src-qt5/src-qml/test/Video.qml (limited to 'src-qt5') diff --git a/src-qt5/src-qml/test/File.qml b/src-qt5/src-qml/test/File.qml new file mode 100644 index 00000000..4713a454 --- /dev/null +++ b/src-qt5/src-qml/test/File.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 +import Qt.labs.folderlistmodel 2.1 + +ListView { + width: 200; height: 400 + + + FolderListModel { + id: folderModel + folder: "/usr/local/videos" + } + + Component { + id: fileDelegate + Text { text: fileName } + } + + model: folderModel + delegate: fileDelegate + Component.onCompleted: { console.log(folderModel.count) } +} diff --git a/src-qt5/src-qml/test/Video.qml b/src-qt5/src-qml/test/Video.qml new file mode 100644 index 00000000..e7d0626d --- /dev/null +++ b/src-qt5/src-qml/test/Video.qml @@ -0,0 +1,50 @@ +import QtQuick 2.0 +import QtMultimedia 5.7 +import QtQuick.Window 2.2 +import Qt.labs.folderlistmodel 2.1 + +Rectangle { + //width: Screen.width + //height: Screen.height + width: 800 + height: 600 + color: "black" + + FolderListModel { + id: folderModel + folder: "/usr/local/videos" + } + + Repeater { + model: folderModel + Component { + Item { + Component.onCompleted: { playlist.addItem(fileURL) } + } + } + } + + Playlist { + id: playlist + playbackMode: Playlist.Random + PlaylistItem { source: "/" } + onError: { console.log("ERROR") } + } + + MediaPlayer { + id: player + autoPlay: true + playlist: playlist + } + + VideoOutput { + id: videoOutput + source: player + anchors.fill: parent + } + + Component.onCompleted: { + playlist.shuffle() + console.log(playlist.itemCount) + } +} -- cgit From d60dc4c97dc690a4e49693de052fdf8789b02eb3 Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 24 Oct 2017 16:51:09 -0400 Subject: change thumbnail generation to faster method tested in lumina-fm-dev --- src-qt5/desktop-utils/lumina-fm/Browser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/Browser.cpp b/src-qt5/desktop-utils/lumina-fm/Browser.cpp index 10c2567b..29cc5a99 100644 --- a/src-qt5/desktop-utils/lumina-fm/Browser.cpp +++ b/src-qt5/desktop-utils/lumina-fm/Browser.cpp @@ -64,7 +64,7 @@ void Browser::loadItem(QString info, Browser *obj){ file.close(); pix.loadFromData(bytes); if(pix.width() > 256 || pix.height() > 256 ){ - pix = pix.scaled(256,256, Qt::KeepAspectRatio); + pix = pix.scaled(256,256, Qt::KeepAspectRatio, Qt::FastTransformation); } } } -- cgit From 2065eaea73177ccb66f24c7ba433abe67f11b31c Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 24 Oct 2017 17:15:58 -0400 Subject: warning banner for running lumina-fm as root_ --- src-qt5/desktop-utils/lumina-fm/MainUI.cpp | 2 ++ src-qt5/desktop-utils/lumina-fm/MainUI.h | 1 + src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp | 4 ++++ src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui | 14 ++++++++++++-- 4 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp index abb99975..50cc110a 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp @@ -25,6 +25,8 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ //qRegisterMetaType< QVector >("QVector"); //qRegisterMetaType< QList >("QList"); waitingToClose = false; + //put if statement here to check if running as root + rootmode = false; ui->setupUi(this); if(DEBUG){ qDebug() << "Initilization:"; } diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.h b/src-qt5/desktop-utils/lumina-fm/MainUI.h index 492ba533..d03ca443 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.h @@ -67,6 +67,7 @@ class MainUI : public QMainWindow{ public: MainUI(); ~MainUI(); + bool rootmode; public slots: void OpenDirs(QStringList); //also called from the main.cpp after initialization diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp index 1b00343d..93a8fec4 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp @@ -30,6 +30,10 @@ DirWidget::DirWidget(QString objID, QSettings *settings, QWidget *parent) : QWidget(parent), ui(new Ui::DirWidget){ ui->setupUi(this); //load the designer file + //if(rootmode = true){ui->label_rootmode->setVisible(true);} + //else{ + ui->label_rootmode->setVisible(false); + //} ID = objID; //Assemble the toolbar for the widget toolbar = new QToolBar(this); diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui index b1ba9d95..b4d8d933 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui @@ -7,7 +7,7 @@ 0 0 400 - 350 + 389 @@ -19,7 +19,17 @@ Form - + + + + + Warning - Running as Root + + + Qt::AlignCenter + + + -- cgit From 11749b3b8eb4665098a0341312104e5b05c6f55c Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 24 Oct 2017 17:30:02 -0400 Subject: add logic for launching lumina-fm as root --- src-qt5/desktop-utils/lumina-fm/MainUI.cpp | 6 ++++++ src-qt5/desktop-utils/lumina-fm/MainUI.h | 2 ++ src-qt5/desktop-utils/lumina-fm/MainUI.ui | 5 +++++ src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui | 10 +++++++++- 4 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp index 50cc110a..2d4cfe84 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp @@ -14,6 +14,7 @@ #include #include +#include #define DEBUG 0 @@ -964,3 +965,8 @@ void MainUI::closeEvent(QCloseEvent *ev){ } QMainWindow::closeEvent(ev); //continue normal close routine } + +void MainUI::on_actionOpen_as_Root_triggered() +{ + ExternalProcess::launch("qsudo lumina-fm"); +} diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.h b/src-qt5/desktop-utils/lumina-fm/MainUI.h index d03ca443..04e8199e 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.h @@ -177,6 +177,8 @@ private slots: void TrayJobsFinished(); + void on_actionOpen_as_Root_triggered(); + signals: void Si_AdaptStatusBar(QFileInfoList fileList, QString path, QString messageFolders, QString messageFiles); diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.ui b/src-qt5/desktop-utils/lumina-fm/MainUI.ui index 744f31a3..56de9b7c 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.ui @@ -434,6 +434,11 @@ Ctrl+P + + + Open as Root + + diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui index b4d8d933..099fd91a 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui @@ -22,8 +22,16 @@ + + + Droid Sans Mono + 75 + false + true + + - Warning - Running as Root + * - FILE MANAGER RUNNING AS ROOT- * Qt::AlignCenter -- cgit From 067a5f38cafc5789af47df06c687f0ddf79219f7 Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 24 Oct 2017 20:40:30 -0400 Subject: add extraction method for custom path --- src-qt5/desktop-utils/lumina-archiver/MainUI.cpp | 51 ++++++++++++++++-------- src-qt5/desktop-utils/lumina-archiver/MainUI.h | 4 +- 2 files changed, 38 insertions(+), 17 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp index 215fc64e..20534569 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp @@ -82,6 +82,7 @@ void MainUI::LoadArguments(QStringList args){ else if(args[i]=="--burn-img"){ action = 0; continue; } else if(args[i]=="--ax"){ action = 1; continue; } else if(args[i]=="--aa"){ action = 2; continue; } + else if(args[i]=="--sx"){ action = 3; continue; } }else{ files << args[i]; } @@ -90,6 +91,7 @@ void MainUI::LoadArguments(QStringList args){ //Now go through and do any actions as needed ui->label_progress->setText(tr("Opening Archive...")); if(action==1){ + qDebug() << "blah"; connect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); connect(BACKEND, SIGNAL(ExtractSuccessful()), delayClose, SLOT(start()) ); }else if(action==2){ @@ -97,6 +99,18 @@ void MainUI::LoadArguments(QStringList args){ for(int j=1; jloadFile(files[0]); ui->actionUSB_Image->setEnabled(files[0].simplified().endsWith(".img")); @@ -260,23 +274,29 @@ void MainUI::extractFiles(){ } void MainUI::autoextractFiles(){ - disconnect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); - QString dir = BACKEND->currentFile().section("/",0,-2); //parent directory of the archive - if(dir.isEmpty()){ return; } - QDir tmp(dir); - QString name = BACKEND->currentFile().section("/",-1).section(".",0,0); - if(QFile::exists(dir+"/"+name)){ - int num = 1; - while( QFile::exists(dir+"/"+name+"_"+QString::number(num))){ num++; } - name = name+"_"+QString::number(num); - } - if(tmp.mkdir(name) ){ - dir.append("/"+name); //created sub directory - } - ui->label_progress->setText(tr("Extracting...")); - BACKEND->startExtract(dir, true); + disconnect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); + QString dir = BACKEND->currentFile().section("/",0,-2); //parent directory of the archive + if(dir.isEmpty()){ return; } + QDir tmp(dir); + QString name = BACKEND->currentFile().section("/",-1).section(".",0,0); + if(QFile::exists(dir+"/"+name)){ + int num = 1; + while( QFile::exists(dir+"/"+name+"_"+QString::number(num))){ num++; } + name = name+"_"+QString::number(num); + } + if(tmp.mkdir(name) ){ + dir.append("/"+name); //created sub directory } + ui->label_progress->setText(tr("Extracting...")); + BACKEND->startExtract(dir, true); +} +void MainUI::simpleExtractFiles(){ + disconnect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); + QString dir = sxPath; + ui->label_progress->setText(tr("Extracting...")); + BACKEND->startExtract(dir, true); +} void MainUI::autoArchiveFiles(){ qDebug() << "Auto Archive Files:" << aaFileList; @@ -284,7 +304,6 @@ void MainUI::autoArchiveFiles(){ BACKEND->startAdd(aaFileList); } - void MainUI::extractSelection(){ if(ui->tree_contents->currentItem()==0){ return; } //nothing selected QList sel = ui->tree_contents->selectedItems(); diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.h b/src-qt5/desktop-utils/lumina-archiver/MainUI.h index a16d5862..1a9d287c 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.h +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.h @@ -30,7 +30,8 @@ public: private: Ui::MainUI *ui; Backend *BACKEND; - QStringList aaFileList; + QStringList aaFileList, sxList; + QString sxPath, sxFile; QTimer *delayClose; QTreeWidgetItem* findItem(QString path, QTreeWidgetItem *start = 0); @@ -49,6 +50,7 @@ private slots: void extractFiles(); void autoextractFiles(); void autoArchiveFiles(); + void simpleExtractFiles(); void extractSelection(); void ViewFile(QTreeWidgetItem *it); void UpdateTree(); -- cgit From e72b4cfb324f8c8bb5aebc9382f2344c6ccb6705 Mon Sep 17 00:00:00 2001 From: q5sys Date: Wed, 25 Oct 2017 09:25:44 -0400 Subject: fixed handling of initial arguments --- src-qt5/desktop-utils/lumina-archiver/MainUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp index 20534569..c4b35474 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp @@ -101,7 +101,7 @@ void MainUI::LoadArguments(QStringList args){ connect(BACKEND, SIGNAL(ArchivalSuccessful()), delayClose, SLOT(start()) ); }else if(action==3){ sxList.clear(); - for(int j=1; j Date: Wed, 25 Oct 2017 12:11:53 -0400 Subject: Re-arrange the 2.0 desktop sources (QML + associated C++ files). Also another checkpoint commit with some of the QML desktop stuff (have a working context menu, wallpapers not working yet though) --- src-qt5/core/lumina-desktop-unified/LSession.cpp | 1 + .../src-desktop/RootWindow.cpp | 2 +- .../lumina-desktop-unified/src-desktop/desktop.pri | 5 +- .../src-desktop/src-cpp/RootDesktopObject.cpp | 77 +++++++++++++++++++++ .../src-desktop/src-cpp/RootDesktopObject.h | 54 +++++++++++++++ .../src-desktop/src-cpp/ScreenObject.cpp | 31 +++++++++ .../src-desktop/src-cpp/ScreenObject.h | 48 +++++++++++++ .../src-desktop/src-cpp/src-cpp.pri | 8 +++ .../src-desktop/src-qml/ContextMenu.qml | 36 ++++++++++ .../src-desktop/src-qml/RootDesktop.qml | 57 ++++++++++++++++ .../src-desktop/src-qml/WallpaperImage.qml | 25 +++++++ .../src-desktop/src-qml/src-qml.pri | 7 ++ .../src-desktop/src-qml/src-qml.qrc | 7 ++ src-qt5/src-cpp/Desktop.pri | 12 ---- src-qt5/src-cpp/RootDesktopObject.cpp | 70 ------------------- src-qt5/src-cpp/RootDesktopObject.h | 52 --------------- src-qt5/src-cpp/ScreenObject.cpp | 30 --------- src-qt5/src-cpp/ScreenObject.h | 48 ------------- src-qt5/src-qml/RootDesktop.qml | 78 ---------------------- src-qt5/src-qml/src-qml.pri | 9 --- src-qt5/src-qml/src-qml.qrc | 5 -- 21 files changed, 356 insertions(+), 306 deletions(-) create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/ContextMenu.qml create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri create mode 100644 src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc delete mode 100644 src-qt5/src-cpp/Desktop.pri delete mode 100644 src-qt5/src-cpp/RootDesktopObject.cpp delete mode 100644 src-qt5/src-cpp/RootDesktopObject.h delete mode 100644 src-qt5/src-cpp/ScreenObject.cpp delete mode 100644 src-qt5/src-cpp/ScreenObject.h delete mode 100644 src-qt5/src-qml/RootDesktop.qml delete mode 100644 src-qt5/src-qml/src-qml.pri delete mode 100644 src-qt5/src-qml/src-qml.qrc (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/LSession.cpp b/src-qt5/core/lumina-desktop-unified/LSession.cpp index 426b91b4..e1251c01 100644 --- a/src-qt5/core/lumina-desktop-unified/LSession.cpp +++ b/src-qt5/core/lumina-desktop-unified/LSession.cpp @@ -230,6 +230,7 @@ void LSession::setupGlobalConnections(){ connect(Lumina::ROOTWIN, SIGNAL(RootResized(QRect)), Lumina::NWS, SLOT(setRoot_desktopGeometry(QRect)) ); connect(RootDesktopObject::instance(), SIGNAL(mouseMoved()), Lumina::SS, SLOT(newInputEvent()) ); connect(RootDesktopObject::instance(), SIGNAL(startLogout()), this, SLOT(StartLogout()) ); + connect(RootDesktopObject::instance(), SIGNAL(lockScreen()), Lumina::SS, SLOT(LockScreenNow()) ); //Native Window Class connections connect(Lumina::NEF, SIGNAL(WindowCreated(WId)), Lumina::NWS, SLOT(NewWindowDetected(WId))); 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 2aac6f3e..0cfa4e6b 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/RootWindow.cpp @@ -25,7 +25,7 @@ RootWindow::~RootWindow(){ } void RootWindow::start(){ - root_view->setSource(QUrl("qrc:///qml/RootDesktop")); + root_view->setSource(QUrl("qrc:///qml/RootDesktop.qml")); root_win->show(); root_view->show(); } 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 25aa02b7..e4c4faeb 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/desktop.pri @@ -1,3 +1,5 @@ +QT *= gui widgets qml quick + SOURCES *= $${PWD}/RootWindow.cpp HEADERS *= $${PWD}/RootWindow.h @@ -5,4 +7,5 @@ HEADERS *= $${PWD}/RootWindow.h #update the includepath so we can just #include as needed without paths INCLUDEPATH *= $${PWD} -include(../../../src-cpp/Desktop.pri) +include($${PWD}/src-cpp/src-cpp.pri) +include($${PWD}/src-qml/src-qml.pri) 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 new file mode 100644 index 00000000..9842712e --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.cpp @@ -0,0 +1,77 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "RootDesktopObject.h" +#include +#include +#include + +#include + +// === PUBLIC === +RootDesktopObject::RootDesktopObject(QObject *parent) : QObject(parent){ + updateScreens(); //make sure the internal list is updated right away +} + +RootDesktopObject::~RootDesktopObject(){ + +} + +void RootDesktopObject::RegisterType(){ + qmlRegisterType("Lumina.Backend.RootDesktopObject", 2, 0, "RootDesktopObject"); + //Also register any types that are needed by this class + ScreenObject::RegisterType(); +} + +RootDesktopObject* RootDesktopObject::instance(){ + static RootDesktopObject* r_obj = new RootDesktopObject(); + return r_obj; +} + +//QML Read Functions +QList RootDesktopObject::screens(){ + return s_objects; +} + +void RootDesktopObject::logout(){ + emit startLogout(); +} + +void RootDesktopObject::lockscreen(){ + emit lockScreen(); +} + +void RootDesktopObject::mousePositionChanged(){ + emit mouseMoved(); +} + +// === PUBLIC SLOTS === +void RootDesktopObject::updateScreens(){ + QList scrns = QApplication::screens(); + QList tmp; //copy of the internal array initially + for(int i=0; iname()==scrns[i]->name()){ found = true; tmp << s_objects.takeAt(j); } + } + if(!found){ tmp << new ScreenObject(scrns[i], this); } + } + //Delete any leftover objects + for(int i=0; ideleteLater(); } + s_objects = tmp; + emit screensChanged(); + for(int i=0; iemit geomChanged(); + } +} + +void RootDesktopObject::ChangeWallpaper(QString screen, QString value){ + for(int i=0; iname()==screen){ s_objects[i]->setBackground(value); break; } + } +} + +// === PRIVATE === 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 new file mode 100644 index 00000000..dd7c7ab3 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/RootDesktopObject.h @@ -0,0 +1,54 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the base C++ object that is used to pass information to the QML "RootDesktop" object +//=========================================== +#ifndef _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H +#define _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H +#include +#include + +#include "ScreenObject.h" + +class RootDesktopObject : public QObject{ + Q_OBJECT + //Define all the QML Properties here (interface between QML and the C++ methods below) + Q_PROPERTY( QList screens READ screens NOTIFY screensChanged) + +public: + //main contructor/destructor + RootDesktopObject(QObject *parent = 0); + ~RootDesktopObject(); + + static void RegisterType(); + + //primary interface to fetch the current instance of the class (so only one is running at any given time) + static RootDesktopObject* instance(); + + //QML Read Functions + QList screens(); + + //QML Access Functions + Q_INVOKABLE void logout(); + Q_INVOKABLE void lockscreen(); + Q_INVOKABLE void mousePositionChanged(); +private: + QList s_objects; + +public slots: + void updateScreens(); //rescan/update screen objects + void ChangeWallpaper(QString screen, QString); + +private slots: + +signals: + void screensChanged(); + void startLogout(); + void mouseMoved(); + void lockScreen(); + +}; +#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 new file mode 100644 index 00000000..4c1d6189 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.cpp @@ -0,0 +1,31 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "ScreenObject.h" +#include +#include + +ScreenObject::ScreenObject(QScreen *scrn, QObject *parent) : QObject(parent){ + bg_screen = scrn; +} + +void ScreenObject::RegisterType(){ + qmlRegisterType("Lumina.Backend.ScreenObject",2,0, "ScreenObject"); +} + +QString ScreenObject::name(){ return bg_screen->name(); } +QString ScreenObject::background(){ qDebug() << "Got Background:" << bg_screen->name() << bg << bg_screen->geometry(); return bg; } +int ScreenObject::x(){ return bg_screen->geometry().x(); } +int ScreenObject::y(){ return bg_screen->geometry().y(); } +int ScreenObject::width(){ return bg_screen->geometry().width(); } +int ScreenObject::height(){ return bg_screen->geometry().height(); } + +void ScreenObject::setBackground(QString fileOrColor){ + if(bg!=fileOrColor){ + bg = fileOrColor; + emit backgroundChanged(); + } +} 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 new file mode 100644 index 00000000..8076f1ae --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/ScreenObject.h @@ -0,0 +1,48 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the base C++ object that is used to pass Screen/Wallpaper info to the QML classes +//=========================================== +#ifndef _LUMINA_DESKTOP_SCREEN_DESKTOP_OBJECT_H +#define _LUMINA_DESKTOP_SCREEN_DESKTOP_OBJECT_H +#include +#include +#include + +class ScreenObject : public QObject { + Q_OBJECT + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) + Q_PROPERTY( int x READ x NOTIFY geomChanged) + Q_PROPERTY( int y READ y NOTIFY geomChanged) + Q_PROPERTY( int width READ width NOTIFY geomChanged) + Q_PROPERTY( int height READ height NOTIFY geomChanged) + +private: + QScreen *bg_screen; + QString bg; + +public: + ScreenObject(QScreen *scrn = 0, QObject *parent = 0); + + static void RegisterType(); + + Q_INVOKABLE QString name(); + Q_INVOKABLE QString background(); + Q_INVOKABLE int x(); + Q_INVOKABLE int y(); + Q_INVOKABLE int width(); + Q_INVOKABLE int height(); + +public slots: + void setBackground(QString fileOrColor); + +signals: + void backgroundChanged(); + void geomChanged(); +}; + +#endif diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri new file mode 100644 index 00000000..33b699da --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-cpp/src-cpp.pri @@ -0,0 +1,8 @@ +SOURCES *= $${PWD}/RootDesktopObject.cpp \ + $${PWD}/ScreenObject.cpp + +HEADERS *= $${PWD}/RootDesktopObject.h \ + $${PWD}/ScreenObject.h + +INCLUDEPATH *= $${PWD} + diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/ContextMenu.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/ContextMenu.qml new file mode 100644 index 00000000..e5bac0b5 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/ContextMenu.qml @@ -0,0 +1,36 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +import QtQuick 2.2 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.0 + +import Lumina.Backend.RootDesktopObject 2.0 + +Menu { + id: contextMenu + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + MenuItem { + text: "Lock Screen" + onTriggered: { + RootObject.lockscreen() + } + } + + MenuItem { + text: "Logout" + //iconName: "system-log-out" + indicator: Image{ + asynchronous: true + //autoTransform: true + //source: "image://theme/system-logout" + source: "file:///usr/local/share/icons/material-design-light/scalable/actions/system-log-out.svg" + } + onTriggered: { + RootObject.logout() + } + } + } 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 new file mode 100644 index 00000000..a1a9164f --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/RootDesktop.qml @@ -0,0 +1,57 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the base QML script the launches/controls the desktop interface itself +//=========================================== +// NOTE: This needs to be paired/used with the corresponding C++ class: RootDesktopObject +// Which should be added as the "RootObject" context property to the QML engine +//------------------ +// Example Code: +// RootDesktopObject *rootobj = new RootDesktopObject(); +// QQuickView *root = new QQuickView(); +// root->setResizeMode(QQuickView::SizeRootObjectToView); +// root->engine()->rootContext()->setContextProperty("RootObject", rootobj); +//=========================================== +import QtQuick 2.2 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.0 + +import "." as QML + +import Lumina.Backend.RootDesktopObject 2.0 +import Lumina.Backend.ScreenObject 2.0 + +Rectangle { + id: rootCanvas + color: "black" + + //Setup the right-click context menu + MouseArea { + anchors.fill: rootCanvas + acceptedButtons: Qt.RightButton + onClicked: { + contextMenu.x = mouseX + contextMenu.y = mouseY + contextMenu.open() + } + onPositionChanged: { + RootObject.mousePositionChanged() + } + } + + //Create the context menu itself + QML.ContextMenu { id: contextMenu } + + //Setup the wallpapers + Repeater{ + model: RootObject.screens + QML.WallpaperImage{ + //console.log( modelData.name() ) + object: modelData + z: 0+index + } + } +} diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml new file mode 100644 index 00000000..4d39b0b8 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/WallpaperImage.qml @@ -0,0 +1,25 @@ +//=========================================== +// Lumina-desktop source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +import QtQuick 2.2 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.0 + +import Lumina.Backend.ScreenObject 2.0 + +AnimatedImage { + //C++ backend object + property ScreenObject object + + //Normal geometries/placements + asynchronous: true + clip: true + source: object.background + x: object.x + y: object.y + width: object.width + height: object.height + } diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri new file mode 100644 index 00000000..99905253 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.pri @@ -0,0 +1,7 @@ +#Show the QML files to lupdate for translation purposes - not for the actual build +lupdate_only{ + SOURCES *= $${PWD}/RootDesktop.qml \ + $${PWD}/ContextMenu.qml +} + +RESOURCES *= $${PWD}/src-qml.qrc diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc new file mode 100644 index 00000000..ebdcc606 --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/src-qml/src-qml.qrc @@ -0,0 +1,7 @@ + + + RootDesktop.qml + ContextMenu.qml + WallpaperImage.qml + + diff --git a/src-qt5/src-cpp/Desktop.pri b/src-qt5/src-cpp/Desktop.pri deleted file mode 100644 index dff6646c..00000000 --- a/src-qt5/src-cpp/Desktop.pri +++ /dev/null @@ -1,12 +0,0 @@ - -QT *= gui qml quick - -SOURCES *= $${PWD}/RootDesktopObject.cpp \ - $${PWD}/ScreenObject.cpp - -HEADERS *= $${PWD}/RootDesktopObject.h \ - $${PWD}/ScreenObject.h - -INCLUDEPATH *= $${PWD} - -include($${PWD}/../src-qml/src-qml.pri) diff --git a/src-qt5/src-cpp/RootDesktopObject.cpp b/src-qt5/src-cpp/RootDesktopObject.cpp deleted file mode 100644 index d151653b..00000000 --- a/src-qt5/src-cpp/RootDesktopObject.cpp +++ /dev/null @@ -1,70 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "RootDesktopObject.h" -#include -#include -#include - -#include - -// === PUBLIC === -RootDesktopObject::RootDesktopObject(QObject *parent) : QObject(parent){ - updateScreens(); //make sure the internal list is updated right away -} - -RootDesktopObject::~RootDesktopObject(){ - -} - -void RootDesktopObject::RegisterType(){ - qmlRegisterType("Lumina.Backend.RootDesktopObject", 2, 0, "RootDesktopObject"); - //Also register any types that are needed by this class - ScreenObject::RegisterType(); -} - -RootDesktopObject* RootDesktopObject::instance(){ - static RootDesktopObject* r_obj = new RootDesktopObject(); - return r_obj; -} - -//QML Read Functions -QList RootDesktopObject::screens(){ - return s_objects; -} - -void RootDesktopObject::logout(){ - emit startLogout(); -} - -void RootDesktopObject::mousePositionChanged(){ - emit mouseMoved(); -} - -// === PUBLIC SLOTS === -void RootDesktopObject::updateScreens(){ - QList scrns = QApplication::screens(); - QList tmp; //copy of the internal array initially - for(int i=0; iname()==scrns[i]->name()){ found = true; tmp << s_objects.takeAt(j); } - } - if(!found){ tmp << new ScreenObject(scrns[i], this); } - } - //Delete any leftover objects - for(int i=0; ideleteLater(); } - s_objects = tmp; - emit screensChanged(); -} - -void RootDesktopObject::ChangeWallpaper(QString screen, QString value){ - for(int i=0; iname()==screen){ s_objects[i]->setBackground(value); break; } - } -} - -// === PRIVATE === diff --git a/src-qt5/src-cpp/RootDesktopObject.h b/src-qt5/src-cpp/RootDesktopObject.h deleted file mode 100644 index 4bc568d3..00000000 --- a/src-qt5/src-cpp/RootDesktopObject.h +++ /dev/null @@ -1,52 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This is the base C++ object that is used to pass information to the QML "RootDesktop" object -//=========================================== -#ifndef _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H -#define _LUMINA_DESKTOP_QML_BACKEND_ROOT_DESKTOP_OBJECT_H -#include -#include - -#include "ScreenObject.h" - -class RootDesktopObject : public QObject{ - Q_OBJECT - //Define all the QML Properties here (interface between QML and the C++ methods below) - Q_PROPERTY( QList screens READ screens NOTIFY screensChanged) - -public: - //main contructor/destructor - RootDesktopObject(QObject *parent = 0); - ~RootDesktopObject(); - - static void RegisterType(); - - //primary interface to fetch the current instance of the class (so only one is running at any given time) - static RootDesktopObject* instance(); - - //QML Read Functions - QList screens(); - - //QML Access Functions - Q_INVOKABLE void logout(); - Q_INVOKABLE void mousePositionChanged(); -private: - QList s_objects; - -public slots: - void updateScreens(); //rescan/update screen objects - void ChangeWallpaper(QString screen, QString); - -private slots: - -signals: - void screensChanged(); - void startLogout(); - void mouseMoved(); - -}; -#endif diff --git a/src-qt5/src-cpp/ScreenObject.cpp b/src-qt5/src-cpp/ScreenObject.cpp deleted file mode 100644 index 354b4cba..00000000 --- a/src-qt5/src-cpp/ScreenObject.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "ScreenObject.h" -#include - -ScreenObject::ScreenObject(QScreen *scrn, QObject *parent) : QObject(parent){ - bg_screen = scrn; -} - -void ScreenObject::RegisterType(){ - qmlRegisterType("Lumina.Backend.ScreenObject",2,0, "ScreenObject"); -} - -QString ScreenObject::name(){ return bg_screen->name(); } -QString ScreenObject::background(){ return bg; } -int ScreenObject::x(){ return bg_screen->geometry().x(); } -int ScreenObject::y(){ return bg_screen->geometry().y(); } -int ScreenObject::width(){ return bg_screen->geometry().width(); } -int ScreenObject::height(){ return bg_screen->geometry().height(); } - -void ScreenObject::setBackground(QString fileOrColor){ - if(bg!=fileOrColor){ - bg = fileOrColor; - emit backgroundChanged(); - } -} diff --git a/src-qt5/src-cpp/ScreenObject.h b/src-qt5/src-cpp/ScreenObject.h deleted file mode 100644 index 5cb16bfc..00000000 --- a/src-qt5/src-cpp/ScreenObject.h +++ /dev/null @@ -1,48 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This is the base C++ object that is used to pass Screen/Wallpaper info to the QML classes -//=========================================== -#ifndef _LUMINA_DESKTOP_SCREEN_DESKTOP_OBJECT_H -#define _LUMINA_DESKTOP_SCREEN_DESKTOP_OBJECT_H -#include -#include -#include - -class ScreenObject : public QObject { - Q_OBJECT - Q_PROPERTY( QString name READ name ) - Q_PROPERTY( QString background READ background NOTIFY backgroundChanged) - Q_PROPERTY( int x READ x NOTIFY geomChanged) - Q_PROPERTY( int y READ y NOTIFY geomChanged) - Q_PROPERTY( int width READ width NOTIFY geomChanged) - Q_PROPERTY( int height READ height NOTIFY geomChanged) - -private: - QScreen *bg_screen; - QString bg; - -public: - ScreenObject(QScreen *scrn = 0, QObject *parent = 0); - - static void RegisterType(); - - QString name(); - QString background(); - int x(); - int y(); - int width(); - int height(); - -public slots: - void setBackground(QString fileOrColor); - -signals: - void backgroundChanged(); - void geomChanged(); -}; - -#endif diff --git a/src-qt5/src-qml/RootDesktop.qml b/src-qt5/src-qml/RootDesktop.qml deleted file mode 100644 index a2576f2e..00000000 --- a/src-qt5/src-qml/RootDesktop.qml +++ /dev/null @@ -1,78 +0,0 @@ -//=========================================== -// Lumina-desktop source code -// Copyright (c) 2017, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -// This is the base QML script the launches/controls the desktop interface itself -//=========================================== -// NOTE: This needs to be paired/used with the corresponding C++ class: RootDesktopObject -// Which should be added as the "RootObject" context property to the QML engine -//------------------ -// Example Code: -// RootDesktopObject *rootobj = new RootDesktopObject(); -// QQuickView *root = new QQuickView(); -// root->setResizeMode(QQuickView::SizeRootObjectToView); -// root->engine()->rootContext()->setContextProperty("RootObject", rootobj); -//=========================================== -import QtQuick 2.2 -import QtQuick.Window 2.2 -import QtQuick.Controls 1.4 - -import "." - -import Lumina.Backend.RootDesktopObject 2.0 -import Lumina.Backend.ScreenObject 2.0 - -Rectangle { - id: rootCanvas - color: "black" - - //Setup the right-click context menu - MouseArea { - anchors.fill: rootCanvas - acceptedButtons: Qt.RightButton - onClicked: { - //contextMenu.x = mouseX - //contextMenu.y = mouseY - contextMenu.popup() - } - onPositionChanged: { - RootObject.mousePositionChanged() - } - } - - //Create the context menu itself - Menu { - id: contextMenu - //closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside - MenuItem { - text: "Logout" - iconName: "system-logout" - /*indicator: Image{ - asynchronous: true - //autoTransform: true - source: "image://theme/system-logout" - }*/ - onTriggered: { - RootObject.logout() - //contextMenu.close() - } - } - } - - //Setup the wallpapers - Repeater{ - model: RootObject.screens - AnimatedImage { - asynchronous: true - clip: true - source: modelData.background - x: modelData.x - y: modelData.y - z: 0+index - width: modelData.width - height: modelData.height - } - } -} diff --git a/src-qt5/src-qml/src-qml.pri b/src-qt5/src-qml/src-qml.pri deleted file mode 100644 index 43af4b5a..00000000 --- a/src-qt5/src-qml/src-qml.pri +++ /dev/null @@ -1,9 +0,0 @@ -#Show the QML files to lupdate for translation purposes - not for the actual build - -QT *= quick qml - -lupdate_only{ - SOURCES *= $${PWD}/RootDesktop.qml -} - -RESOURCES *= $${PWD}/src-qml.qrc diff --git a/src-qt5/src-qml/src-qml.qrc b/src-qt5/src-qml/src-qml.qrc deleted file mode 100644 index 5bedb4a5..00000000 --- a/src-qt5/src-qml/src-qml.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - RootDesktop.qml - - -- cgit From d7044ed7162b0ed37f07867c9e9b3d71ae4801d7 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 25 Oct 2017 15:06:30 -0400 Subject: Fix an unommented testing line in lumina-fm. This broke the build of lumina-fm since the associated UI file has not been added yet. --- src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp index 93a8fec4..6f1624a4 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp @@ -32,7 +32,7 @@ DirWidget::DirWidget(QString objID, QSettings *settings, QWidget *parent) : QWid ui->setupUi(this); //load the designer file //if(rootmode = true){ui->label_rootmode->setVisible(true);} //else{ - ui->label_rootmode->setVisible(false); + //ui->label_rootmode->setVisible(false); //} ID = objID; //Assemble the toolbar for the widget -- cgit From ffa97c5088b2dc88ca38044774813549468969ea Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 25 Oct 2017 15:42:46 -0400 Subject: Speed up some of the desktop init procedures again. Got the "init" time from ~4.2 seconds to ~0.6 seconds on my laptop. --- src-qt5/core/lumina-desktop/LSession.cpp | 27 +++++++++++++++---------- src-qt5/core/lumina-desktop/LXcbEventFilter.cpp | 18 ++++++++--------- src-qt5/core/lumina-desktop/WMProcess.cpp | 6 +++--- 3 files changed, 28 insertions(+), 23 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index fb24117d..6fceff1b 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -98,7 +98,7 @@ void LSession::setupSession(){ qDebug() << "Initializing Session"; if(QFile::exists("/tmp/.luminastopping")){ QFile::remove("/tmp/.luminastopping"); } QTime* timer = 0; - //if(DEBUG){ timer = new QTime(); timer->start(); qDebug() << " - Init srand:" << timer->elapsed();} + if(DEBUG){ timer = new QTime(); timer->start(); qDebug() << " - Init srand:" << timer->elapsed();} //Setup the QSettings default paths splash.showScreen("settings"); @@ -118,8 +118,8 @@ void LSession::setupSession(){ } //use the system settings //Setup the user's lumina settings directory as necessary - splash.showScreen("user"); - if(DEBUG){ qDebug() << " - Init User Files:" << timer->elapsed();} + //splash.showScreen("user"); + //if(DEBUG){ qDebug() << " - Init User Files:" << timer->elapsed();} //checkUserFiles(); //adds these files to the watcher as well //Initialize the internal variables @@ -147,11 +147,12 @@ void LSession::setupSession(){ if(DEBUG){ qDebug() << " - Init Desktops:" << timer->elapsed();} desktopFiles = QDir(QDir::homePath()+"/Desktop").entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs, QDir::Name | QDir::IgnoreCase | QDir::DirsFirst); updateDesktops(); - for(int i=0; i<6; i++){ LSession::processEvents(); } //Run through this a few times so the interface systems get up and running + //if(DEBUG){ qDebug() << " - Process Events (6x):" << timer->elapsed();} + //for(int i=0; i<6; i++){ LSession::processEvents(); } //Run through this a few times so the interface systems get up and running //Now setup the system watcher for changes splash.showScreen("final"); - qDebug() << " - Initialize file system watcher"; + //qDebug() << " - Initialize file system watcher"; if(DEBUG){ qDebug() << " - Init QFileSystemWatcher:" << timer->elapsed();} watcher = new QFileSystemWatcher(this); QString confdir = sessionsettings->fileName().section("/",0,-2); @@ -171,14 +172,18 @@ void LSession::setupSession(){ connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(watcherChange(QString)) ); connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(watcherChange(QString)) ); connect(this, SIGNAL(aboutToQuit()), this, SLOT(SessionEnding()) ); - if(DEBUG){ qDebug() << " - Init Finished:" << timer->elapsed(); delete timer;} - for(int i=0; i<4; i++){ LSession::processEvents(); } //Again, just a few event loops here so thing can settle before we close the splash screen + //if(DEBUG){ qDebug() << " - Process Events (4x):" << timer->elapsed();} + //for(int i=0; i<4; i++){ LSession::processEvents(); } //Again, just a few event loops here so thing can settle before we close the splash screen + if(DEBUG){ qDebug() << " - Launch Startup Apps:" << timer->elapsed();} //launchStartupApps(); QTimer::singleShot(500, this, SLOT(launchStartupApps()) ); - splash.hide(); - LSession::processEvents(); + //if(DEBUG){ qDebug() << " - Hide Splashscreen:" << timer->elapsed();} + //splash.hide(); + //LSession::processEvents(); + if(DEBUG){ qDebug() << " - Close Splashscreen:" << timer->elapsed();} splash.close(); - LSession::processEvents(); + //LSession::processEvents(); + if(DEBUG){ qDebug() << " - Init Finished:" << timer->elapsed(); delete timer;} } void LSession::CleanupSession(){ @@ -303,7 +308,7 @@ void LSession::launchStartupApps(){ QString sfile = sessionsettings->value("audiofiles/login", LOS::LuminaShare()+"Login.ogg").toString(); playAudioFile(sfile); } - qDebug() << "[DESKTOP INIT FINISHED]"; + //qDebug() << "[DESKTOP INIT FINISHED]"; } void LSession::StartLogout(){ diff --git a/src-qt5/core/lumina-desktop/LXcbEventFilter.cpp b/src-qt5/core/lumina-desktop/LXcbEventFilter.cpp index ca7fb38d..038872ff 100644 --- a/src-qt5/core/lumina-desktop/LXcbEventFilter.cpp +++ b/src-qt5/core/lumina-desktop/LXcbEventFilter.cpp @@ -52,8 +52,8 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag session->emit WorkspaceChanged(); }else if( SysNotifyAtoms.contains( ((xcb_property_notify_event_t*)ev)->atom ) ){ //Update the status/list of all running windows - session->WindowPropertyEvent(); - + session->WindowPropertyEvent(); + //window-specific property change }else if( WinNotifyAtoms.contains( ((xcb_property_notify_event_t*)ev)->atom ) ){ //Ping only that window @@ -61,7 +61,7 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag session->WindowPropertyEvent(); } break; -//============================== +//============================== case XCB_CLIENT_MESSAGE: //qDebug() << "Client Message Event"; //qDebug() << " - Root Window:" << QX11Info::appRootWindow(); @@ -72,7 +72,7 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag session->SysTrayDockRequest( ((xcb_client_message_event_t*)ev)->data.data32[2] ); } //Ignore the System Tray messages at the moment (let the WM handle it) - + //window-specific property changes /*}else if( ((xcb_client_message_event_t*)ev)->type == session->XCB->EWMH._NET_WM_STATE ){ if( session->XCB->WindowIsMaximized( ((xcb_client_message_event_t*)ev)->window ) ){ @@ -86,22 +86,22 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag session->WindowPropertyEvent(); } break; -//============================== +//============================== case XCB_DESTROY_NOTIFY: //qDebug() << "Window Closed Event"; session->WindowClosedEvent( ( (xcb_destroy_notify_event_t*)ev )->window ); break; -//============================== +//============================== case XCB_CONFIGURE_NOTIFY: //qDebug() << "Configure Notify Event"; session->WindowConfigureEvent( ((xcb_configure_notify_event_t*)ev)->window ); break; -//============================== +//============================== case XCB_SELECTION_CLEAR: //qDebug() << "Selection Clear Event"; - session->WindowSelectionClearEvent( ((xcb_selection_clear_event_t*)ev)->owner ); + session->WindowSelectionClearEvent( ((xcb_selection_clear_event_t*)ev)->owner ); break; -//============================== +//============================== default: if(TrayDmgFlag!=0){ //if( (ev->response_type & ~0x80)==TrayDmgFlag){ diff --git a/src-qt5/core/lumina-desktop/WMProcess.cpp b/src-qt5/core/lumina-desktop/WMProcess.cpp index aa01b730..0687c1fe 100644 --- a/src-qt5/core/lumina-desktop/WMProcess.cpp +++ b/src-qt5/core/lumina-desktop/WMProcess.cpp @@ -30,7 +30,7 @@ void WMProcess::startWM(){ if(!isRunning()){this->start(cmd); } /*if(ssaver->state() == QProcess::NotRunning \ && LSession::handle()->sessionSettings()->value("WindowManager", "fluxbox").toString() != "lumina-wm"){ - ssaver->start("xscreensaver -no-splash"); + ssaver->start("xscreensaver -no-splash"); }*/ } @@ -52,8 +52,8 @@ void WMProcess::restartWM(){ inShutdown = true; this->kill(); if(!this->waitForFinished(5000) ){ this->terminate(); }; - inShutdown = false; - } + inShutdown = false; + } this->startWM(); } -- cgit From 76eb44f51faee92476ed509b700be9bc30be08a7 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Wed, 25 Oct 2017 17:09:02 -0400 Subject: Fixed image previews with video thumbnails --- src-qt5/core/libLumina/LVideoLabel.cpp | 34 +++++++++++------- src-qt5/core/libLumina/LVideoLabel.h | 5 +-- src-qt5/core/libLumina/LVideoWidget.cpp | 8 +++++ src-qt5/core/libLumina/LVideoWidget.h | 2 ++ src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp | 42 ++++++++++++----------- src-qt5/desktop-utils/lumina-fm/BrowserWidget.h | 4 ++- 6 files changed, 60 insertions(+), 35 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp index af23330c..bc70a292 100644 --- a/src-qt5/core/libLumina/LVideoLabel.cpp +++ b/src-qt5/core/libLumina/LVideoLabel.cpp @@ -1,10 +1,11 @@ #include "LVideoLabel.h" +#include #include LVideoLabel::LVideoLabel(QString file, QWidget *parent) : QLabel(parent) { thumbnail = QPixmap(); entered = false; - shrink = true; + icons = true; filepath = file; QTimer::singleShot(0, this, SLOT(initializeBackend()) ); @@ -15,10 +16,6 @@ LVideoLabel::~LVideoLabel() { surface->deleteLater(); } -void LVideoLabel::setShrinkPixmap(bool shrink) { - this->shrink = shrink; -} - void LVideoLabel::initializeBackend(){ mediaPlayer = new QMediaPlayer(this, QMediaPlayer::VideoSurface); surface = new LVideoSurface(this); @@ -35,6 +32,15 @@ void LVideoLabel::initializeBackend(){ this->connect(this, SIGNAL(rollOver()), surface, SLOT(switchRollOver())); } +void LVideoLabel::enableIcons() { + this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); + icons = true; +} + +void LVideoLabel::disableIcons() { + this->setPixmap(LXDG::findIcon("unknown", "").pixmap(this->size())); + icons = false; +} void LVideoLabel::stopVideo(QPixmap pix) { if(!entered) { @@ -85,17 +91,21 @@ void LVideoLabel::resizeEvent(QResizeEvent *event) { //Start playing the video from the beginning when the mouse enters the label void LVideoLabel::enterEvent(QEvent *event) { - entered=true; - emit rollOver(); - mediaPlayer->setPosition(0); - mediaPlayer->play(); + if(icons) { + entered=true; + emit rollOver(); + mediaPlayer->setPosition(0); + mediaPlayer->play(); + } QWidget::enterEvent(event); } //Stop the video and set the thumbnail back to the middle of the video when the mouse leaves the label void LVideoLabel::leaveEvent(QEvent *event) { - entered=false; - mediaPlayer->setPosition(mediaPlayer->duration() / 2); - emit rollOver(); + if(icons) { + entered=false; + mediaPlayer->setPosition(mediaPlayer->duration() / 2); + emit rollOver(); + } QWidget::leaveEvent(event); } diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h index f368c1a8..3c6b304c 100644 --- a/src-qt5/core/libLumina/LVideoLabel.h +++ b/src-qt5/core/libLumina/LVideoLabel.h @@ -12,7 +12,8 @@ class LVideoLabel : public QLabel{ public: LVideoLabel(QString, QWidget* parent=NULL); ~LVideoLabel(); - void setShrinkPixmap(bool); + void enableIcons(); + void disableIcons(); protected: void enterEvent(QEvent*); @@ -34,7 +35,7 @@ class LVideoLabel : public QLabel{ LVideoSurface *surface; QPixmap thumbnail; bool entered; - bool shrink; + bool icons; QString filepath; }; #endif diff --git a/src-qt5/core/libLumina/LVideoWidget.cpp b/src-qt5/core/libLumina/LVideoWidget.cpp index 14490484..b9660b10 100644 --- a/src-qt5/core/libLumina/LVideoWidget.cpp +++ b/src-qt5/core/libLumina/LVideoWidget.cpp @@ -26,3 +26,11 @@ LVideoWidget::~LVideoWidget() { void LVideoWidget::setIconSize(QSize iconSize) { iconLabel->setFixedSize(iconSize); } + +void LVideoWidget::enableIcons() { + iconLabel->enableIcons(); +} + +void LVideoWidget::disableIcons() { + iconLabel->disableIcons(); +} diff --git a/src-qt5/core/libLumina/LVideoWidget.h b/src-qt5/core/libLumina/LVideoWidget.h index c239a697..6743acb6 100644 --- a/src-qt5/core/libLumina/LVideoWidget.h +++ b/src-qt5/core/libLumina/LVideoWidget.h @@ -11,6 +11,8 @@ class LVideoWidget : public QWidget { LVideoWidget(QString, QSize, QWidget* parent=NULL); ~LVideoWidget(); void setIconSize(QSize); + void disableIcons(); + void enableIcons(); private: bool flag; diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp index dc00e92f..0384d892 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp @@ -12,7 +12,6 @@ #include #include -#include BrowserWidget::BrowserWidget(QString objID, QWidget *parent) : QWidget(parent){ //Setup the Widget/UI @@ -39,6 +38,7 @@ BrowserWidget::~BrowserWidget(){ } void BrowserWidget::changeDirectory(QString dir){ + qDebug() << "changing"; videoMap.clear(); if(BROWSER->currentDirectory()==dir){ return; } //already on this directory //qDebug() << "Change Directory:" << dir << historyList; @@ -111,6 +111,18 @@ bool BrowserWidget::hasHiddenFiles(){ } void BrowserWidget::showThumbnails(bool show){ + qDebug() << show << videoMap.size(); + for(QString file : videoMap.uniqueKeys()) { + QTreeWidgetItem *it = videoMap[file].first; + LVideoWidget *widget = videoMap[file].second; + if(show) { + widget->disableIcons(); + treeWidget->setItemWidget(it, 0, widget); + }else{ + widget->enableIcons(); + treeWidget->setItemWidget(it, 0, widget); + } + } BROWSER->showThumbnails(show); } @@ -128,8 +140,8 @@ void BrowserWidget::setThumbnailSize(int px){ treeWidget->setIconSize(QSize(px,px)); } for(QString file : videoMap.uniqueKeys()) { - QTreeWidgetItem *it = videoMap[file]; - LVideoWidget *widget = (LVideoWidget*)treeWidget->itemWidget(it, 0); + QTreeWidgetItem *it = videoMap[file].first; + LVideoWidget *widget = videoMap[file].second; widget->setIconSize(treeWidget->iconSize()); treeWidget->setItemWidget(it, 0, widget); } @@ -334,28 +346,18 @@ void BrowserWidget::itemDataAvailable(QIcon ico, LFileInfo *info){ treeWidget->addTopLevelItem(it); } }else{ - if(!BROWSER->showingThumbnails() && videoMap.size() !=0) { - for(QString file : videoMap.keys()) { - QTreeWidgetItem *it = videoMap[file]; - treeWidget->removeItemWidget(it, 0); - } - videoMap.clear(); - } if( ! treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).isEmpty() ) { it = treeWidget->findItems(info->fileName(), Qt::MatchExactly, 0).first(); - }else if(info->isVideo() && videoMap.find(info->absoluteFilePath()) == videoMap.end() && BROWSER->showingThumbnails()){ + }else if(info->isVideo() && videoMap.find(info->absoluteFilePath()) == videoMap.end()) { it = new CQTreeWidgetItem(treeWidget); treeWidget->addTopLevelItem(it); LVideoWidget *widget = new LVideoWidget(info->absoluteFilePath(), treeWidget->iconSize(), treeWidget); - videoMap.insert(info->absoluteFilePath(), it); + videoMap.insert(info->absoluteFilePath(), QPair(it, widget)); treeWidget->setItemWidget(it, 0, widget); - }else if(info->isVideo() && BROWSER->showingThumbnails()){ - it = videoMap[info->absoluteFilePath()]; - if(treeWidget->itemWidget(it, 0) != 0) { - LVideoWidget *widget = (LVideoWidget*)treeWidget->itemWidget(it, 0); - widget->setIconSize(treeWidget->iconSize()); - treeWidget->setItemWidget(it, 0, widget); - } + }else if(info->isVideo()) { + it = videoMap[info->absoluteFilePath()].first; + LVideoWidget *widget = videoMap[info->absoluteFilePath()].second; + widget->setIconSize(treeWidget->iconSize()); }else{ it = new CQTreeWidgetItem(treeWidget); treeWidget->addTopLevelItem(it); @@ -363,7 +365,7 @@ void BrowserWidget::itemDataAvailable(QIcon ico, LFileInfo *info){ } } //Now set/update all the data - if(!info->isVideo() || (info->isVideo() && !BROWSER->showingThumbnails())) + if(!info->isVideo()) it->setIcon(0, ico); it->setText(1, info->isDir() ? "" : LUtils::BytesToDisplaySize(info->size()) ); //size (1) it->setText(2, info->mimetype() ); //type (2) diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h index 585aaa82..f041280c 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.h @@ -12,6 +12,8 @@ #include #include +#include + #include "Browser.h" #include "widgets/DDListWidgets.h" @@ -23,7 +25,7 @@ private: int numItems; //used for checking if all the items have loaded yet QString ID, statustip; QStringList date_format, historyList; - QMap videoMap; + QMap> videoMap; bool freshload; //The drag and drop brower widgets -- cgit From 1e4bb99764f6012260adb4192604a392bd62bf0a Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Wed, 25 Oct 2017 18:23:38 -0400 Subject: Fixed issues with previews and LVideoWidget sizing --- src-qt5/core/libLumina/LVideoLabel.cpp | 23 ++++++++++++++++------- src-qt5/core/libLumina/LVideoLabel.h | 3 ++- src-qt5/core/libLumina/LVideoWidget.cpp | 12 +++++++----- src-qt5/core/libLumina/LVideoWidget.h | 3 +-- src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 2 +- src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp | 8 ++++---- 6 files changed, 31 insertions(+), 20 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoLabel.cpp b/src-qt5/core/libLumina/LVideoLabel.cpp index bc70a292..bddb1cba 100644 --- a/src-qt5/core/libLumina/LVideoLabel.cpp +++ b/src-qt5/core/libLumina/LVideoLabel.cpp @@ -2,11 +2,12 @@ #include #include -LVideoLabel::LVideoLabel(QString file, QWidget *parent) : QLabel(parent) { +LVideoLabel::LVideoLabel(QString file, bool icons, QWidget *parent) : QLabel(parent) { thumbnail = QPixmap(); entered = false; - icons = true; + this->icons = icons; filepath = file; + defaultThumbnail = LXDG::findIcon("unknown", "").pixmap(256,256); QTimer::singleShot(0, this, SLOT(initializeBackend()) ); } @@ -23,6 +24,7 @@ void LVideoLabel::initializeBackend(){ mediaPlayer->setPlaybackRate(3); mediaPlayer->setMuted(true); + this->setPixmap(defaultThumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); mediaPlayer->setMedia(QUrl::fromLocalFile(filepath)); mediaPlayer->play(); @@ -38,7 +40,7 @@ void LVideoLabel::enableIcons() { } void LVideoLabel::disableIcons() { - this->setPixmap(LXDG::findIcon("unknown", "").pixmap(this->size())); + this->setPixmap(defaultThumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); icons = false; } @@ -47,10 +49,12 @@ void LVideoLabel::stopVideo(QPixmap pix) { emit frameReceived(pix); if(thumbnail.isNull()) thumbnail = pix; - this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); + if(icons) + this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); mediaPlayer->pause(); }else { - this->setPixmap(pix.scaled(this->size(),Qt::IgnoreAspectRatio)); + if(icons) + this->setPixmap(pix.scaled(this->size(),Qt::IgnoreAspectRatio)); } } @@ -84,8 +88,13 @@ void LVideoLabel::setDuration(QMediaPlayer::MediaStatus status) { } void LVideoLabel::resizeEvent(QResizeEvent *event) { - if(!thumbnail.isNull()) //Resize the current pixmap to match the new size - this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); + //Resize the current pixmap to match the new size + if(!thumbnail.isNull()){ + if(icons) + this->setPixmap(thumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); + else + this->setPixmap(defaultThumbnail.scaled(this->size(),Qt::IgnoreAspectRatio)); + } QLabel::resizeEvent(event); } diff --git a/src-qt5/core/libLumina/LVideoLabel.h b/src-qt5/core/libLumina/LVideoLabel.h index 3c6b304c..56defb6a 100644 --- a/src-qt5/core/libLumina/LVideoLabel.h +++ b/src-qt5/core/libLumina/LVideoLabel.h @@ -10,7 +10,7 @@ class LVideoLabel : public QLabel{ Q_OBJECT public: - LVideoLabel(QString, QWidget* parent=NULL); + LVideoLabel(QString, bool, QWidget* parent=NULL); ~LVideoLabel(); void enableIcons(); void disableIcons(); @@ -34,6 +34,7 @@ class LVideoLabel : public QLabel{ QMediaPlayer *mediaPlayer; LVideoSurface *surface; QPixmap thumbnail; + QPixmap defaultThumbnail; bool entered; bool icons; QString filepath; diff --git a/src-qt5/core/libLumina/LVideoWidget.cpp b/src-qt5/core/libLumina/LVideoWidget.cpp index b9660b10..f1f74414 100644 --- a/src-qt5/core/libLumina/LVideoWidget.cpp +++ b/src-qt5/core/libLumina/LVideoWidget.cpp @@ -1,20 +1,22 @@ #include "LVideoWidget.h" -LVideoWidget::LVideoWidget(QString file, QSize iconSize, QWidget *parent) : QWidget(parent) { - flag = false; - iconLabel = new LVideoLabel(file, parent); +LVideoWidget::LVideoWidget(QString file, QSize iconSize, bool icons, QWidget *parent) : QWidget(parent) { + iconLabel = new LVideoLabel(file, icons, parent); textLabel = new QLabel(parent); layout = new QHBoxLayout(this); layout->setAlignment(Qt::AlignLeft | Qt::AlignCenter); - layout->addWidget(iconLabel); - layout->addWidget(textLabel); + layout->setContentsMargins(5,5,5,5); layout->setStretchFactor(textLabel, 1); //make sure this always occupies all extra space textLabel->setText(file.section("/", -1)); + iconLabel->setGeometry(QRect(QPoint(0,0), iconSize)); iconLabel->setFixedSize(iconSize); iconLabel->setVisible(true); textLabel->setVisible(true); + + layout->addWidget(iconLabel); + layout->addWidget(textLabel); } LVideoWidget::~LVideoWidget() { diff --git a/src-qt5/core/libLumina/LVideoWidget.h b/src-qt5/core/libLumina/LVideoWidget.h index 6743acb6..610fd9e5 100644 --- a/src-qt5/core/libLumina/LVideoWidget.h +++ b/src-qt5/core/libLumina/LVideoWidget.h @@ -8,14 +8,13 @@ class LVideoWidget : public QWidget { Q_OBJECT public: - LVideoWidget(QString, QSize, QWidget* parent=NULL); + LVideoWidget(QString, QSize, bool icons, QWidget* parent=NULL); ~LVideoWidget(); void setIconSize(QSize); void disableIcons(); void enableIcons(); private: - bool flag; LVideoLabel *iconLabel; QLabel *textLabel; QHBoxLayout *layout; diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index fb55ad99..c712afed 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -88,7 +88,7 @@ void MainUI::LoadFile(QString path, QString type){ ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); }else if(INFO->isVideo()){ ui->label_file_icon->hide(); - LVideoLabel *mediaLabel = new LVideoLabel(INFO->absoluteFilePath(), ui->tab_file); + LVideoLabel *mediaLabel = new LVideoLabel(INFO->absoluteFilePath(), true, ui->tab_file); mediaLabel->setFixedSize(64,64); ui->formLayout->replaceWidget(ui->label_file_icon, mediaLabel); }else{ diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp index 0384d892..0983a7b4 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp @@ -38,7 +38,6 @@ BrowserWidget::~BrowserWidget(){ } void BrowserWidget::changeDirectory(QString dir){ - qDebug() << "changing"; videoMap.clear(); if(BROWSER->currentDirectory()==dir){ return; } //already on this directory //qDebug() << "Change Directory:" << dir << historyList; @@ -116,10 +115,10 @@ void BrowserWidget::showThumbnails(bool show){ QTreeWidgetItem *it = videoMap[file].first; LVideoWidget *widget = videoMap[file].second; if(show) { - widget->disableIcons(); + widget->enableIcons(); treeWidget->setItemWidget(it, 0, widget); }else{ - widget->enableIcons(); + widget->disableIcons(); treeWidget->setItemWidget(it, 0, widget); } } @@ -351,13 +350,14 @@ void BrowserWidget::itemDataAvailable(QIcon ico, LFileInfo *info){ }else if(info->isVideo() && videoMap.find(info->absoluteFilePath()) == videoMap.end()) { it = new CQTreeWidgetItem(treeWidget); treeWidget->addTopLevelItem(it); - LVideoWidget *widget = new LVideoWidget(info->absoluteFilePath(), treeWidget->iconSize(), treeWidget); + LVideoWidget *widget = new LVideoWidget(info->absoluteFilePath(), treeWidget->iconSize(), hasThumbnails(), treeWidget); videoMap.insert(info->absoluteFilePath(), QPair(it, widget)); treeWidget->setItemWidget(it, 0, widget); }else if(info->isVideo()) { it = videoMap[info->absoluteFilePath()].first; LVideoWidget *widget = videoMap[info->absoluteFilePath()].second; widget->setIconSize(treeWidget->iconSize()); + treeWidget->setItemWidget(it, 0, widget); }else{ it = new CQTreeWidgetItem(treeWidget); treeWidget->addTopLevelItem(it); -- cgit From 6defe842e03d25827d3638fda8629236593ebc04 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 25 Oct 2017 18:27:11 -0400 Subject: Re-enable the "Root Mode" warning at the top of lumina-fm, and setup the root detection to work properly. --- src-qt5/desktop-utils/lumina-fm/MainUI.cpp | 3 ++- src-qt5/desktop-utils/lumina-fm/MainUI.h | 2 +- src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp index 2d4cfe84..87c3a0f8 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp @@ -17,6 +17,7 @@ #include #define DEBUG 0 +bool rootmode = false; MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ //for Signal/slot we must register the Typedef of QFileInfoList @@ -27,7 +28,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ //qRegisterMetaType< QList >("QList"); waitingToClose = false; //put if statement here to check if running as root - rootmode = false; + rootmode = (getuid()==0); ui->setupUi(this); if(DEBUG){ qDebug() << "Initilization:"; } diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.h b/src-qt5/desktop-utils/lumina-fm/MainUI.h index 04e8199e..04b80f28 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.h @@ -67,7 +67,7 @@ class MainUI : public QMainWindow{ public: MainUI(); ~MainUI(); - bool rootmode; + //bool rootmode; public slots: void OpenDirs(QStringList); //also called from the main.cpp after initialization diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp index 6f1624a4..a8cbea2c 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp @@ -27,13 +27,12 @@ #include "../ScrollDialog.h" #define DEBUG 0 +extern bool rootmode; DirWidget::DirWidget(QString objID, QSettings *settings, QWidget *parent) : QWidget(parent), ui(new Ui::DirWidget){ ui->setupUi(this); //load the designer file - //if(rootmode = true){ui->label_rootmode->setVisible(true);} - //else{ - //ui->label_rootmode->setVisible(false); - //} + ui->label_rootmode->setVisible(rootmode); + ID = objID; //Assemble the toolbar for the widget toolbar = new QToolBar(this); -- cgit From 5b5e79737f38b7eee6ced0cd08d7cdd437c0e708 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Wed, 25 Oct 2017 19:01:17 -0400 Subject: Added the QML Video screensaver --- .../extrafiles/screensavers/Video.json | 25 +++++++++++ .../extrafiles/screensavers/qml_scripts/Video.qml | 50 ++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Video.json create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Video.json b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Video.json new file mode 100644 index 00000000..2fa6e6da --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/Video.json @@ -0,0 +1,25 @@ +{ + "name" : { + "default" : "Video" + }, + "description" : { + "default" : "Play a single video or a list of videos in a loop" + }, + "author" : { + "name" : "Zackary Welch", + "email" : "zwelch@ixsystems.com", + "website" : "https://github.com/ZackaryWelch", + "company" : "iXsystems", + "company_website" : "http://ixsystems.com" + }, + "meta" : { + "license" : "3-clause BSD", + "license_url" : "https://github.com/trueos/lumina/blob/master/LICENSE", + "copyright" : "Copyright (c) 2017, Ken Moore (ken@ixsystems.com)", + "date_created" : "20171025", + "version" : "1.0" + }, + "qml" : { + "exec" : "qml_scripts/Video.qml" + } +} diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml new file mode 100644 index 00000000..e7d0626d --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Video.qml @@ -0,0 +1,50 @@ +import QtQuick 2.0 +import QtMultimedia 5.7 +import QtQuick.Window 2.2 +import Qt.labs.folderlistmodel 2.1 + +Rectangle { + //width: Screen.width + //height: Screen.height + width: 800 + height: 600 + color: "black" + + FolderListModel { + id: folderModel + folder: "/usr/local/videos" + } + + Repeater { + model: folderModel + Component { + Item { + Component.onCompleted: { playlist.addItem(fileURL) } + } + } + } + + Playlist { + id: playlist + playbackMode: Playlist.Random + PlaylistItem { source: "/" } + onError: { console.log("ERROR") } + } + + MediaPlayer { + id: player + autoPlay: true + playlist: playlist + } + + VideoOutput { + id: videoOutput + source: player + anchors.fill: parent + } + + Component.onCompleted: { + playlist.shuffle() + console.log(playlist.itemCount) + } +} -- cgit From 76f587abe521794a71604532224b9cf7103ae50e Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Wed, 25 Oct 2017 19:02:16 -0400 Subject: Removed debug outputs --- src-qt5/core/libLumina/LVideoSurface.cpp | 19 +++++++++++-------- src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LVideoSurface.cpp b/src-qt5/core/libLumina/LVideoSurface.cpp index e3e87667..3aaa81f0 100644 --- a/src-qt5/core/libLumina/LVideoSurface.cpp +++ b/src-qt5/core/libLumina/LVideoSurface.cpp @@ -7,17 +7,17 @@ LVideoSurface::LVideoSurface(QObject *parent) : QAbstractVideoSurface(parent) { } bool LVideoSurface::present(const QVideoFrame &frame) { - //qDebug() << surfaceFormat().pixelFormat() << frame.pixelFormat() << surfaceFormat().frameSize() << frame.size(); + //qDebug() << surfaceFormat().frameSize() << frame.size(); if(!frameImage.isNull() && !entered) { emit frameReceived(frameImage); return true; } if(frame.isValid()) { - //qDebug() << "Recording Frame" << frame.pixelFormat(); + //qDebug() << "Recording Frame"; + //qDebug() << surfaceFormat().frameSize() << frame.size(); QVideoFrame icon(frame); icon.map(QAbstractVideoBuffer::ReadOnly); - //qDebug() << icon.width() << icon.height(); QImage img(icon.bits(), icon.width(), icon.height(), icon.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat())); if((frameImage.isNull() && !entered) or entered) @@ -48,10 +48,13 @@ bool LVideoSurface::start(const QVideoSurfaceFormat &format) { const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); const QSize size = format.frameSize(); - if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) { + //QVideoSurfaceFormat newFormat = format; + //Shrink the frames passed through the format to a smaller, thumbnail appropriate size and increase the frame rate + //newFormat.setFrameSize(258,258); + //newFormat.setFrameRate(90); + + if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) QAbstractVideoSurface::start(format); - return true; - } else { - return false; - } + + return (imageFormat != QImage::Format_Invalid && !size.isEmpty()); } diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp index 0983a7b4..6229749c 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp @@ -110,7 +110,7 @@ bool BrowserWidget::hasHiddenFiles(){ } void BrowserWidget::showThumbnails(bool show){ - qDebug() << show << videoMap.size(); + //qDebug() << show << videoMap.size(); for(QString file : videoMap.uniqueKeys()) { QTreeWidgetItem *it = videoMap[file].first; LVideoWidget *widget = videoMap[file].second; -- cgit From a821ac6d6bd60dbbfffd7661ecbaa2d9e4c26338 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Wed, 25 Oct 2017 20:18:13 -0400 Subject: Started incorporating the Grav screensaver to QML --- .../extrafiles/screensavers/qml_scripts/Grav.qml | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml new file mode 100644 index 00000000..d5245c9b --- /dev/null +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml @@ -0,0 +1,106 @@ +import QtQuick 2.7 +import QtGraphicalEffects 1.0 + +Rectangle { + id : canvas + anchors.fill: parent + width: 800 + height: 600 + color: "black" + + //Between 5 and 15 planets, read from settings + property var planets: Math.round(( Math.random() * 10 ) + 5 ) + + //Create planets + Repeater { + model: planets + + Rectangle { + id : index + parent: canvas + + //Place the planet randomly on the canvas, but not too close to the edge + x: Math.round(Math.random()*canvas.width) + + //Check to make sure the planets are not too close to the sun (outside a 50px radius) + //while( Math.round(Math.random()*canvas.width) < (width/2 + 50) or Math.round(Math.random()*canvas.width) > (width/2 - 50)) + + y: Math.round(Math.random()*canvas.height) + + + //Create the orbit animation + + //Planet size between 14 and 32 pixels + width: Math.round(1.75 * (((Math.random() * 10) + 8 ))) + height: width + + //Make each rectangle look circular + radius: width / 2 + + //Give each planet a random color, semi-transparent + color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.5) + } + } + + //Create the star + Rectangle{ + id: star + parent: canvas + + //Centers in star in the center of the canvas + x: Math.round(canvas.width / 2) + y: Math.round(canvas.height / 2) + + width: 60 + height: width + + //Create the wobble animation + SequentialAnimation on height { + loops: Animation.Infinite + PropertyAnimation { duration: 2000; to: 90 } + PropertyAnimation { duration: 2000; to: 60 } + } + + SequentialAnimation on width { + loops: Animation.Infinite + PropertyAnimation { duration: 2000; to: 90 } + PropertyAnimation { duration: 2000; to: 60 } + } + + //border.width: 4 + //border.color: "blue" + color: "black" + radius: width / 2 + + //Creates a radial gradient to make the star look cool + RadialGradient { + anchors.fill: parent + gradient: Gradient { + GradientStop { position:0 ;color: Qt.rgba(0,0,0,0)} + GradientStop { position:0.18 ;color: Qt.rgba(0,0,0,0)} + GradientStop { position:0.2 ;color: Qt.rgba(0.32,0.47,0.30,0.13)} + GradientStop { position:0.3 ;color: Qt.rgba(0.62,0.92,0.58,0.25)} + GradientStop { position:0.4 ;color: Qt.rgba(1.00,0.93,0.59,0.51)} + GradientStop { position:0.5 ;color: Qt.rgba(0,0,0,0)} + } + } + + } + + /*Motion timer + Timer { + interval: 1 + repeat: true + running: true + property bool starting: true + + onTriggered: { + if(starting) { interval = 3010; starting = false; } + + } + }*/ + + Component.onCompleted: { + //console.log(Math.random()) + } +} -- cgit From 9c5f154c2e8cc1ad388732a0bc3ee9bb42f296c6 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 26 Oct 2017 18:30:51 -0400 Subject: Fix a few places where /net/ files are still checked for existance (pauses/delays the session init) --- src-qt5/core/libLumina/LuminaXDG.cpp | 5 +++-- src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp | 6 +++--- .../desktop-plugins/applauncher/AppLauncherPlugin.cpp | 2 +- .../panel-plugins/systemstart/LStartButton.cpp | 2 +- .../panel-plugins/systemstart/StartMenu.cpp | 18 ++++++++++-------- .../panel-plugins/systemstart/StartMenu.h | 4 ++-- 6 files changed, 20 insertions(+), 17 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index fdf51a11..53b59165 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -631,7 +631,7 @@ void XDGDesktopList::populateMenu(QMenu *topmenu, bool byCategory){ void LFileInfo::loadExtraInfo(){ desk = 0; //Now load the extra information - if(this->isDir()){ + if( this->suffix().isEmpty() && (this->absoluteFilePath().startsWith("/net/") || this->isDir()) ){ mime = "inode/directory"; //Special directory icons QString name = this->fileName().toLower(); @@ -644,6 +644,7 @@ void LFileInfo::loadExtraInfo(){ else if(name=="downloads"){ icon = "folder-downloads"; } else if(name=="documents"){ icon = "folder-documents"; } else if(name=="images" || name=="pictures"){ icon = "folder-image"; } + else if(this->absoluteFilePath().startsWith("/net/")){ icon = "folder-shared"; } else if( !this->isReadable() ){ icon = "folder-locked"; } }else if( this->suffix()=="desktop"){ mime = "application/x-desktop"; @@ -730,7 +731,7 @@ bool LXDG::checkExec(QString exec){ else{ QStringList paths = QString(getenv("PATH")).split(":"); for(int i=0; isetAttribute(Qt::WA_TranslucentBackground); //this->setAttribute(Qt::WA_NoSystemBackground); this->setAutoFillBackground(false); - this->setStyleSheet("QWidget#LuminaDesktopPluginSpace{ border: none; background: transparent; }"); + this->setStyleSheet("QWidget#LuminaDesktopPluginSpace{ border: none; background: transparent; }"); this->setWindowFlags(Qt::WindowStaysOnBottomHint | Qt::CustomizeWindowHint | Qt::FramelessWindowHint); this->setAcceptDrops(true); this->setContextMenuPolicy(Qt::NoContextMenu); @@ -34,7 +34,7 @@ LDesktopPluginSpace::LDesktopPluginSpace() : QWidget(){ } LDesktopPluginSpace::~LDesktopPluginSpace(){ - + } void LDesktopPluginSpace::LoadItems(QStringList plugs, QStringList files){ @@ -76,7 +76,7 @@ void LDesktopPluginSpace::setBackground(QPixmap pix){ void LDesktopPluginSpace::setDesktopArea(QRect area){ //qDebug() << "Setting Desktop Plugin Area:" << area; desktopRect = area; - + } // =================== diff --git a/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp b/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp index 0258d561..533b5997 100644 --- a/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp +++ b/src-qt5/core/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp @@ -44,7 +44,7 @@ void AppLauncherPlugin::loadButton(){ QFileInfo info(path); this->contextMenu()->clear(); //qDebug() << "Default Application Launcher:" << def << path; - bool ok = QFile::exists(path); + bool ok = info.canonicalPath().startsWith("/net/") || QFile::exists(path); if(!ok){ emit RemovePlugin(this->ID()); return;} icosize = this->height()-4 - 2.2*button->fontMetrics().height(); button->setFixedSize( this->width()-4, this->height()-4); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp index f44add77..bbcd096c 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/LStartButton.cpp @@ -28,7 +28,7 @@ LStartButtonPlugin::LStartButtonPlugin(QWidget *parent, QString id, bool horizon menu->setContents(startmenu); QSize saved = LSession::handle()->DesktopPluginSettings()->value("panelPlugs/"+this->type()+"/MenuSize", QSize(0,0)).toSize(); if(!saved.isNull()){ startmenu->setFixedSize(saved); } //re-load the previously saved value - + button->setMenu(menu); connect(menu, SIGNAL(aboutToHide()), this, SLOT(updateButtonVisuals()) ); QTimer::singleShot(0,this, SLOT(OrientationChange())); //Update icons/sizes diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp index e8df8390..c99e2b4b 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.cpp @@ -138,7 +138,7 @@ void StartMenu::UpdateMenu(bool forceall){ } void StartMenu::ReLoadQuickLaunch(){ - emit UpdateQuickLaunch( LSession::handle()->sessionSettings()->value("QuicklaunchApps",QStringList()).toStringList() ); + emit UpdateQuickLaunch( LSession::handle()->sessionSettings()->value("QuicklaunchApps",QStringList()).toStringList() ); } void StartMenu::UpdateQuickLaunch(QString path, bool keep){ @@ -431,7 +431,9 @@ void StartMenu::UpdateFavs(){ tmp.sort(); //Sort alphabetically by name (dirs/files) for(int i=0; i1){ ui->frame_wkspace->setVisible(true); int cur = LSession::handle()->XCB->CurrentWorkspace(); - ui->label_wkspace->setText( QString(tr("Workspace %1/%2")).arg(QString::number(cur+1), QString::number(tot)) ); + ui->label_wkspace->setText( QString(tr("Workspace %1/%2")).arg(QString::number(cur+1), QString::number(tot)) ); }else{ ui->frame_wkspace->setVisible(false); } @@ -635,14 +637,14 @@ void StartMenu::on_tool_mute_audio_clicked(){ ui->slider_volume->setValue(0); } } - + //Screen Brightness void StartMenu::on_slider_bright_valueChanged(int val){ ui->label_bright->setText(QString::number(val)+"%"); LOS::setScreenBrightness(val); } - + //Workspace void StartMenu::on_tool_set_nextwkspace_clicked(){ int cur = LSession::handle()->XCB->CurrentWorkspace(); @@ -663,10 +665,10 @@ void StartMenu::on_tool_set_prevwkspace_clicked(){ if(cur<0){ cur = tot-1; } //back to end //qDebug() << " - New Current:" << cur; LSession::handle()->XCB->SetCurrentWorkspace(cur); - ui->label_wkspace->setText( QString(tr("Workspace %1/%2")).arg(QString::number(cur+1), QString::number(tot)) ); + ui->label_wkspace->setText( QString(tr("Workspace %1/%2")).arg(QString::number(cur+1), QString::number(tot)) ); } - + //Locale void StartMenu::on_combo_locale_currentIndexChanged(int){ //Get the currently selected Locale @@ -677,7 +679,7 @@ void StartMenu::on_combo_locale_currentIndexChanged(int){ LSession::handle()->switchLocale(locale); } - + //Search void StartMenu::on_line_search_textEdited(QString){ if(searchTimer->isActive()){ searchTimer->stop(); } diff --git a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h index 8ab04d94..e2dbb273 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h +++ b/src-qt5/core/lumina-desktop/panel-plugins/systemstart/StartMenu.h @@ -34,13 +34,13 @@ private: Ui::StartMenu *ui; QStringList favs; QString CCat, CSearch, topsearch; //current category/search - QTimer *searchTimer; + QTimer *searchTimer; //Simple utility functions //void deleteChildren(QWidget *obj); //recursive function void ClearScrollArea(QScrollArea *area); void SortScrollArea(QScrollArea *area); - void do_search(QString search, bool force); + void do_search(QString search, bool force); bool promptAboutUpdates(bool &skip); -- cgit From 3fd42c40cfda85fa90c19add4e07ec1ca1c312cb Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 27 Oct 2017 08:08:39 -0400 Subject: Add the ability to use a "directory" as the target for desktop wallpapers. Will automatically open that directory and randomly pick an image from from within it for the wallpaper. --- .../lumina-config/pages/page_wallpaper.cpp | 2 +- src-qt5/core/lumina-desktop/LDesktop.cpp | 65 ++++++++++++++-------- .../core/lumina-desktop/LDesktopPluginSpace.cpp | 12 ++-- .../applauncher/AppLauncherPlugin.cpp | 3 +- 4 files changed, 51 insertions(+), 31 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core-utils/lumina-config/pages/page_wallpaper.cpp b/src-qt5/core-utils/lumina-config/pages/page_wallpaper.cpp index 6842dce4..839269ca 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_wallpaper.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_wallpaper.cpp @@ -221,7 +221,7 @@ void page_wallpaper::deskbgcoloradded(){ ui->combo_desk_bg->addItem( QString(tr("Solid Color: %1")).arg(color), color); //Now move to the last item in the list (the new image(s)); ui->combo_desk_bg->setCurrentIndex( ui->combo_desk_bg->count()-1 ); - + emit HasPendingChanges(true); } diff --git a/src-qt5/core/lumina-desktop/LDesktop.cpp b/src-qt5/core/lumina-desktop/LDesktop.cpp index f9ea1534..1fc6b11b 100644 --- a/src-qt5/core/lumina-desktop/LDesktop.cpp +++ b/src-qt5/core/lumina-desktop/LDesktop.cpp @@ -341,7 +341,7 @@ void LDesktop::UpdateMenu(bool fast){ void LDesktop::UpdateWinMenu(){ winMenu->clear(); //Get the current list of windows - QList wins = LSession::handle()->XCB->WindowList(); + QList wins = LSession::handle()->XCB->WindowList(); //Now add them to the menu for(int i=0; iXCB->ActivateWindow( act->data().toString().toULong() ); + LSession::handle()->XCB->ActivateWindow( act->data().toString().toULong() ); } void LDesktop::UpdateDesktop(){ @@ -393,7 +393,7 @@ void LDesktop::UpdateDesktop(){ if(settings->value(DPREFIX+"generateMediaIcons",true).toBool()){ QDir media("/media"); QStringList mediadirs = media.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name); - for(int i=0; ivalue(DPREFIX+"pluginlist", QStringList()).toStringList(); - if(plugs.contains(ID)){ - plugs.removeAll(ID); + if(plugs.contains(ID)){ + plugs.removeAll(ID); issyncing=true; //don't let the change cause a refresh settings->setValue(DPREFIX+"pluginlist", plugs); settings->sync(); @@ -437,7 +437,7 @@ void LDesktop::DecreaseDesktopPluginIcons(){ settings->setValue(DPREFIX+"GridSize",cur); settings->sync(); QTimer::singleShot(200, this, SLOT(UnlockSettings()) ); - bgDesktop->SetIconSize(cur); + bgDesktop->SetIconSize(cur); } void LDesktop::UpdatePanels(){ @@ -484,18 +484,18 @@ void LDesktop::UpdateDesktopPluginArea(){ QRegion shifted = visReg; QString loc = settings->value(PANELS[i]->prefix()+"location","top").toString().toLower(); int vis = PANELS[i]->visibleWidth(); - if(loc=="top"){ + if(loc=="top"){ if(!shifted.contains(QRect(rawRect.x(), rawRect.y(), rawRect.width(), vis))){ continue; } - shifted.translate(0, (rawRect.top()+vis)-shifted.boundingRect().top() ); + shifted.translate(0, (rawRect.top()+vis)-shifted.boundingRect().top() ); }else if(loc=="bottom"){ - if(!shifted.contains(QRect(rawRect.x(), rawRect.bottom()-vis, rawRect.width(), vis))){ continue; } - shifted.translate(0, (rawRect.bottom()-vis)-shifted.boundingRect().bottom()); - }else if(loc=="left"){ + if(!shifted.contains(QRect(rawRect.x(), rawRect.bottom()-vis, rawRect.width(), vis))){ continue; } + shifted.translate(0, (rawRect.bottom()-vis)-shifted.boundingRect().bottom()); + }else if(loc=="left"){ if( !shifted.contains(QRect(rawRect.x(), rawRect.y(), vis,rawRect.height())) ){ continue; } - shifted.translate((rawRect.left()+vis)-shifted.boundingRect().left() ,0); + shifted.translate((rawRect.left()+vis)-shifted.boundingRect().left() ,0); }else{ //right if(!shifted.contains(QRect(rawRect.right()-vis, rawRect.y(), vis,rawRect.height())) ){ continue; } - shifted.translate((rawRect.right()-vis)-shifted.boundingRect().right(),0); + shifted.translate((rawRect.right()-vis)-shifted.boundingRect().right(),0); } visReg = visReg.intersected( shifted ); } @@ -535,7 +535,7 @@ void LDesktop::UpdateBackground(){ //Get the list of background(s) to show QStringList bgL = settings->value(DPREFIX+"background/filelist-workspace-"+QString::number( LSession::handle()->XCB->CurrentWorkspace()), QStringList()).toStringList(); if(bgL.isEmpty()){ bgL = settings->value(DPREFIX+"background/filelist", QStringList()).toStringList(); } - + //qDebug() << " - List:" << bgL << CBG; //Remove any invalid files for(int i=0; i= bgL.length()-1){ index = 0; } //if invalid or last item in the list - go to first - else{ index++; } //go to next + QString bgFile; + while(bgFile.isEmpty() || QFileInfo(bgFile).isDir()){ + QString prefix; + if(!bgFile.isEmpty()){ + //Got a directory - update the list of files and re-randomize the selection + QStringList imgs = LUtils::imageExtensions(); + for(int i=0; i= bgL.length()-1){ index = 0; } //if invalid or last item in the list - go to first + else{ index++; } //go to next + } + bgFile = prefix+bgL[index]; } - QString bgFile = bgL[index]; //Save this file as the current background CBG = bgFile; //qDebug() << " - Set Background to:" << CBG << index << bgL; @@ -570,7 +589,7 @@ void LDesktop::UpdateBackground(){ bgDesktop->setBackground(backPix); //Now reset the timer for the next change (if appropriate) if(bgtimer->isActive()){ bgtimer->stop(); } - if(bgL.length() > 1){ + if(bgL.length()>1 || oldBGL.length()>1){ //get the length of the timer (in minutes) int min = settings->value(DPREFIX+"background/minutesToChange",5).toInt(); //restart the internal timer @@ -633,9 +652,9 @@ void LDesktop::NewDesktopFile(QString name){ QDir desktop(QDir::homePath()); if(desktop.exists(tr("Desktop"))){ desktop.cd(tr("Desktop")); } //translated folder else{ desktop.cd("Desktop"); } //default/english folder - if(!desktop.exists(name)){ + if(!desktop.exists(name)){ QFile file(desktop.absoluteFilePath(name)); - if(file.open(QIODevice::WriteOnly) ){ file.close(); } + if(file.open(QIODevice::WriteOnly) ){ file.close(); } } } } diff --git a/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp b/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp index 025c067a..9e964f5d 100644 --- a/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp +++ b/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp @@ -222,7 +222,7 @@ QRect LDesktopPluginSpace::findOpenSpot(int gridwidth, int gridheight, int start //else{ row++; } } if(!found){ col++; row=0; } //go to the next column - } + } }else if(reversed && (startRow>0 || startCol>0) ){ //Arrange Left->Right (work backwards) while(row>=0 && !found){ @@ -242,7 +242,7 @@ QRect LDesktopPluginSpace::findOpenSpot(int gridwidth, int gridheight, int start //else{ col++; } } if(!found){ row--; col=colCount-gridwidth;} //go to the previous row - } + } }else{ //Arrange Left->Right while(row<(rowCount-gridheight) && !found){ @@ -296,8 +296,8 @@ void LDesktopPluginSpace::reloadPlugins(bool ForceIconUpdate ){ QStringList plugs = plugins; QStringList items = deskitems; for(int i=0; iwhatsThis().startsWith("applauncher") && ForceIconUpdate){ + + if( ITEMS[i]->whatsThis().startsWith("applauncher") && ForceIconUpdate){ //Change the size of the existing plugin - preserving the location if possible /*QRect geom = ITEMS[i]->loadPluginGeometry(); //pixel coords if(!geom.isNull()){ @@ -306,14 +306,14 @@ void LDesktopPluginSpace::reloadPlugins(bool ForceIconUpdate ){ ITEMS[i]->savePluginGeometry( gridToGeom(geom)); //save it back in pixel coords }*/ //Now remove the plugin for the moment - run it through the re-creation routine below - ITEMS.takeAt(i)->deleteLater(); + ITEMS.takeAt(i)->deleteLater(); i--; } else if(plugs.contains(ITEMS[i]->whatsThis())){ plugs.removeAll(ITEMS[i]->whatsThis()); } else if(items.contains(ITEMS[i]->whatsThis().section("---",0,0).section("::",1,50))){ items.removeAll(ITEMS[i]->whatsThis().section("---",0,0).section("::",1,50)); } else{ ITEMS[i]->removeSettings(true); ITEMS.takeAt(i)->deleteLater(); i--; } //this is considered a permanent removal (cleans settings) } - + //Now create any new items //First load the plugins (almost always have fixed locations) for(int i=0; icontextMenu()->clear(); //qDebug() << "Default Application Launcher:" << def << path; - bool ok = info.canonicalPath().startsWith("/net/") || QFile::exists(path); + bool ok = info.canonicalPath().startsWith("/net/"); + if(!ok){ ok = QFile::exists(path); } //do it this way to ensure the file existance check never runs for /net/ files if(!ok){ emit RemovePlugin(this->ID()); return;} icosize = this->height()-4 - 2.2*button->fontMetrics().height(); button->setFixedSize( this->width()-4, this->height()-4); -- cgit From f8b26186ce5b6a018d2c833188fb1e9ee7f902d5 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 27 Oct 2017 09:24:11 -0400 Subject: Ensure that "Exec" and "TryExec" strings with quotes are handled properly. --- src-qt5/core/libLumina/LUtils.cpp | 3 +++ src-qt5/core/libLumina/LuminaXDG.cpp | 5 ++++- src-qt5/core/lumina-open/main.cpp | 5 ++--- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LUtils.cpp b/src-qt5/core/libLumina/LUtils.cpp index 820b55e8..65c6ac96 100644 --- a/src-qt5/core/libLumina/LUtils.cpp +++ b/src-qt5/core/libLumina/LUtils.cpp @@ -121,6 +121,9 @@ bool LUtils::writeFile(QString filepath, QStringList contents, bool overwrite){ } bool LUtils::isValidBinary(QString& bin){ + //Trim off any quotes + if(bin.startsWith("\"") && bin.endsWith("\"")){ bin.chop(1); bin = bin.remove(0,1); } + //Now look for relative/absolute path if(!bin.startsWith("/")){ //Relative path: search for it on the current "PATH" settings QStringList paths = QString(qgetenv("PATH")).split(":"); diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index 53b59165..aaca7bb1 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -72,6 +72,7 @@ void XDGDesktop::sync(){ QString loc = var.section("[",1,1).section("]",0,0).simplified(); // localization var = var.section("[",0,0).simplified(); //remove the localization QString val = line.section("=",1,50).simplified(); + if( val.count("\"")==2 && val.startsWith("\"") && val.endsWith("\"")){ val.chop(1); val = val.remove(0,1); } //remove the starting/ending quotes //------------------- if(var=="Name"){ if(insection){ @@ -727,6 +728,8 @@ bool LFileInfo::isAVFile(){ //==== LXDG Functions ==== bool LXDG::checkExec(QString exec){ //Return true(good) or false(bad) + //Check for quotes around the exec, and remove them as needed + if(exec.startsWith("\"") && exec.count("\"")>=2){ exec = exec.section("\"",1,1); } if(exec.startsWith("/")){ return QFile::exists(exec); } else{ QStringList paths = QString(getenv("PATH")).split(":"); @@ -748,7 +751,7 @@ QStringList LXDG::systemApplicationDirs(){ for(int i=0; i #include -#define DEBUG 0 +#define DEBUG 1 void printUsageInfo(){ qDebug() << "lumina-open: Application launcher for the Lumina Desktop Environment"; @@ -369,7 +369,7 @@ int main(int argc, char **argv){ QString bin = cmd.section(" ",0,0); if( !LUtils::isValidBinary(bin) ){ //invalid binary for some reason - open a dialog to warn the user instead - QMessageBox::warning(0, QObject::tr("Binary Missing"), QString(QObject::tr("Could not find \"%1\". Please ensure it is installed first.")).arg(bin)+"\n\n"+cmd); + ShowErrorDialog(argc,argv, QString(QObject::tr("Could not find \"%1\". Please ensure it is installed first.")).arg(bin)+"\n\n"+cmd); return 1; } if(DEBUG) qDebug() << "[lumina-open] Running Cmd:" << cmd; @@ -416,7 +416,6 @@ int main(int argc, char **argv){ //Setup the application QApplication App(argc, argv); App.setAttribute(Qt::AA_UseHighDpiPixmaps); - LuminaThemeEngine theme(&App); LUtils::LoadTranslation(&App,"lumina-open"); //App.setApplicationName("LuminaOpen"); QMessageBox dlg(QMessageBox::Critical, QObject::tr("Application Error"), QObject::tr("The following application experienced an error and needed to close:")+"\n\n"+cmd ); -- cgit From 73e0138c0047e8aee30233d1d15d9dfaf8831397 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 27 Oct 2017 09:27:46 -0400 Subject: Fix a couple theme engine holdovers in lumina-open, and turn off debugging again. --- src-qt5/core/lumina-open/main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-open/main.cpp b/src-qt5/core/lumina-open/main.cpp index 7b6cb2ad..2b9e9184 100644 --- a/src-qt5/core/lumina-open/main.cpp +++ b/src-qt5/core/lumina-open/main.cpp @@ -29,7 +29,7 @@ #include #include -#define DEBUG 1 +#define DEBUG 0 void printUsageInfo(){ qDebug() << "lumina-open: Application launcher for the Lumina Desktop Environment"; @@ -50,7 +50,6 @@ void ShowErrorDialog(int argc, char **argv, QString message){ //Setup the application QApplication App(argc, argv); App.setAttribute(Qt::AA_UseHighDpiPixmaps); - LuminaThemeEngine theme(&App); LUtils::LoadTranslation(&App,"lumina-open"); QMessageBox dlg(QMessageBox::Critical, QObject::tr("File Error"), message ); dlg.exec(); @@ -141,7 +140,6 @@ QString cmdFromUser(int argc, char **argv, QString inFile, QString extension, QS LTHEME::LoadCustomEnvSettings(); QApplication App(argc, argv); App.setAttribute(Qt::AA_UseHighDpiPixmaps); - LuminaThemeEngine theme(&App); LUtils::LoadTranslation(&App,"lumina-open"); LFileDialog w; -- cgit From df0a6abc4622e4527fb8ef6f618485bb4fdc4cb1 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 27 Oct 2017 11:09:40 -0400 Subject: Fix the column width resizing for lumina-fm tree widget. --- src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp index 6229749c..ab25d5e7 100644 --- a/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp +++ b/src-qt5/desktop-utils/lumina-fm/BrowserWidget.cpp @@ -82,6 +82,7 @@ void BrowserWidget::showDetails(bool show){ connect(treeWidget, SIGNAL(GotFocus()), this, SLOT(selectionChanged()) ); retranslate(); treeWidget->sortItems(0, Qt::AscendingOrder); + treeWidget->setColumnWidth(0, treeWidget->fontMetrics().width("W")*20); if(!BROWSER->currentDirectory().isEmpty()){ emit dirChange("", true); } }else if(!show && listWidget==0){ listWidget = new DDListWidget(this); @@ -384,7 +385,9 @@ void BrowserWidget::itemDataAvailable(QIcon ico, LFileInfo *info){ }else{ if(freshload && treeWidget!=0){ //qDebug() << "Resize Tree Widget Contents"; - for(int i=0; icolumnCount(); i++){ treeWidget->resizeColumnToContents(i); } + //for(int i=treeWidget->columnCount()-1; i>0; i--){ treeWidget->resizeColumnToContents(i); } + treeWidget->resizeColumnToContents(1); + //treeWidget->resizeColumnToContents(0); } freshload = false; //any further changes are updates - not a fresh load of a dir //Done loading items -- cgit From 7b1a48e82702d2c19c2e1cf30b64da8628783f04 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 31 Oct 2017 09:00:24 -0400 Subject: Add an upgrade path for moving theme settings from the old format to the new theme engine. Also turn on the mouse cursor "loading" image again when launching an external process (for 3 seconds) --- src-qt5/core/libLumina/ExternalProcess.h | 4 ++-- src-qt5/core/libLumina/LDesktopUtils.cpp | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/ExternalProcess.h b/src-qt5/core/libLumina/ExternalProcess.h index b1e56af8..ce8ff6f5 100644 --- a/src-qt5/core/libLumina/ExternalProcess.h +++ b/src-qt5/core/libLumina/ExternalProcess.h @@ -31,7 +31,7 @@ private slots: void processStarting(){ if(!cursorRestored){ QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); - QTimer::singleShot(15000, this, SLOT(resetCursor()) ); + QTimer::singleShot(3000, this, SLOT(resetCursor()) ); } } void processFinished(){ @@ -62,7 +62,7 @@ public: }*/ } - static void launch(QString program, QStringList args = QStringList(), bool manageCursors = false){ + static void launch(QString program, QStringList args = QStringList(), bool manageCursors = true){ //Quick launch of a process with logging disabled and automatic cleanup ExternalProcess *tmp = new ExternalProcess("", manageCursors); if(args.isEmpty()){ tmp->start(program); } diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index c65f6faf..db913e1b 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -505,6 +505,40 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ } LUtils::writeFile(dset, DS, true); } + if(oldversion<1003004){ + //Lumina 1.3.4 - Migrate theme settings from old format to the new theme engine format + QString themefile = QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/lthemeengine.conf"; + if(!QFile::exists(themefile)){ + //Need to migrate theme settings from the old location to the new one + QSettings newtheme(themefile); + QStringList oldtheme = LUtils::readFile( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themesettings.cfg" ); + //Find the system install location for the theme engine for use later + QString enginedir = LOS::LuminaShare()+"/../lthemeengine/"; + //Find/match the icon theme + QString tmp = oldtheme.filter("ICONTHEME=").join("\n").section("=",1,-1).section("\n",0,0).simplified(); + if(tmp.isEmpty()){ tmp = "material-design-light"; } //unknown Icon theme - use the default "light" version + newtheme.setValue("Appearance/icon_theme",tmp); + //Quick detect/adjust of the tone of the color theme based on the icons/colors (no 1-to-1 color theme matching between systems) + bool isdarktheme = tmp.contains("dark"); + isdarktheme = isdarktheme || oldtheme.filter("COLORFILE=").join("\n").section("=",1,-1).section("\n",0,0).contains("DarkGlass"); + //Quick adjust for the material-design icon theme to make it match the current dark/light theme + if(tmp.contains("material-design")){ + newtheme.setValue("Appearance/icon_theme", QString("material-design-")+ (isdarktheme ? "dark" : "light") ); + } + if(isdarktheme){ + newtheme.setValue("Appearance/custom_palette", true); + newtheme.setValue("Appearance/color_scheme_path", enginedir+"colors/darker.conf"); + newtheme.setValue("Interface/desktop_stylesheets", QStringList() << enginedir+"desktop_qss/DarkGlass.qss"); + }else{ + newtheme.setValue("Appearance/custom_palette", true); + newtheme.setValue("Appearance/color_scheme_path", enginedir+"colors/airy.conf"); + newtheme.setValue("Interface/desktop_stylesheets", QStringList() << enginedir+"desktop_qss/Glass.qss"); + } + newtheme.setValue("Appearance/style", "Fusion"); + newtheme.setValue("Interface/stylesheets", QStringList() << enginedir+"qss/tooltip-simple.qss" << enginedir+"qss/scrollbar-simple.qss" << enginedir+"qss/sliders-simple.qss"); + newtheme.sync(); //flush this to file right now + } //end check for theme file existance + } //Check the fluxbox configuration files dset = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/"; -- cgit From 4d27f401cdef77b5f2e162615ade2b92a57ae68f Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 31 Oct 2017 09:28:48 -0400 Subject: Finish up the theme engine migration path (works fine now - after some testing). Also some random whitespace cleanup --- src-qt5/core/libLumina/LDesktopUtils.cpp | 5 ++++- src-qt5/core/libLumina/LuminaOS.h | 14 +++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LDesktopUtils.cpp b/src-qt5/core/libLumina/LDesktopUtils.cpp index db913e1b..f1b3de17 100644 --- a/src-qt5/core/libLumina/LDesktopUtils.cpp +++ b/src-qt5/core/libLumina/LDesktopUtils.cpp @@ -509,8 +509,11 @@ bool LDesktopUtils::checkUserFiles(QString lastversion, QString currentversion){ //Lumina 1.3.4 - Migrate theme settings from old format to the new theme engine format QString themefile = QString(getenv("XDG_CONFIG_HOME"))+"/lthemeengine/lthemeengine.conf"; if(!QFile::exists(themefile)){ + QDir dir; + dir.mkpath(themefile.section("/",0,-2)); //make sure the main directory exists first //Need to migrate theme settings from the old location to the new one - QSettings newtheme(themefile); + QSettings newtheme(themefile, QSettings::NativeFormat); + qDebug() << "Migrating Theme settings:" << newtheme.fileName(); QStringList oldtheme = LUtils::readFile( QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/themesettings.cfg" ); //Find the system install location for the theme engine for use later QString enginedir = LOS::LuminaShare()+"/../lthemeengine/"; diff --git a/src-qt5/core/libLumina/LuminaOS.h b/src-qt5/core/libLumina/LuminaOS.h index e7a72129..98137816 100644 --- a/src-qt5/core/libLumina/LuminaOS.h +++ b/src-qt5/core/libLumina/LuminaOS.h @@ -5,8 +5,8 @@ // See the LICENSE file for full details //=========================================== // This is the main interface for any OS-specific system calls -// To port Lumina to a different operating system, just create a file -// called "LuminaOS-.cpp", and use that file in +// To port Lumina to a different operating system, just create a file +// called "LuminaOS-.cpp", and use that file in // the project (libLumina.pro) instead of LuminaOS-FreeBSD.cpp //=========================================== #ifndef _LUMINA_LIBRARY_OS_H @@ -23,7 +23,7 @@ class LOS{ public: //Return the name of the OS being used - static QString OSName(); + static QString OSName(); //OS-specific prefix(s) static QString LuminaShare(); //Install dir for Lumina share files @@ -34,7 +34,7 @@ public: static QString ControlPanelShortcut(); static QString AppStoreShortcut(); - //OS-specific RSS feeds + //OS-specific RSS feeds static QStringList RSSFeeds(); //Return Format: QStringList[ :::: ]; //Scan for mounted external devices @@ -81,13 +81,13 @@ public: static bool batteryIsCharging(); //Battery Time Remaining static int batterySecondsLeft(); //Returns: estimated number of seconds remaining - + //Get the checksum for a file static QStringList Checksums(QStringList filepaths); //Return: checksum of each input file (same order) - + //Get the filesystem capacity static QString FileSystemCapacity(QString dir) ; //Return: percentage capacity as give by the df command - + //System CPU Information static QStringList CPUTemperatures(); //Returns: List containing the temperature of any CPU's ("50C" for example) static int CPUUsagePercent(); //Returns: Overall percentage of the amount of CPU cycles in use (-1 for errors) -- cgit From 91134ecb1e450464acf6e9b99b17fdec26452d76 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 31 Oct 2017 09:55:21 -0400 Subject: Ensure the mouse cursor "busy" icon is used for 3 seconds when launching an external process. --- src-qt5/core/libLumina/ExternalProcess.h | 7 ++++++- src-qt5/core/lumina-desktop/LSession.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/ExternalProcess.h b/src-qt5/core/libLumina/ExternalProcess.h index ce8ff6f5..2a6f4949 100644 --- a/src-qt5/core/libLumina/ExternalProcess.h +++ b/src-qt5/core/libLumina/ExternalProcess.h @@ -15,6 +15,7 @@ #include #include #include +#include class ExternalProcess : public QProcess{ Q_OBJECT @@ -23,18 +24,21 @@ private: private slots: void resetCursor(){ + //qDebug() << "External Process: Reset Mouse Cursor =" << !cursorRestored; if(!cursorRestored){ QApplication::restoreOverrideCursor(); cursorRestored = true; } } void processStarting(){ + //qDebug() << "Starting External Process: Mouse Notification =" << !cursorRestored; if(!cursorRestored){ - QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); + QApplication::setOverrideCursor( QCursor(Qt::BusyCursor) ); QTimer::singleShot(3000, this, SLOT(resetCursor()) ); } } void processFinished(){ + //qDebug() << "External Process Finished: Reset Mouse Cursor =" << !cursorRestored; if(!cursorRestored){ QApplication::restoreOverrideCursor(); cursorRestored = true; @@ -53,6 +57,7 @@ public: this->setStandardOutputFile(logfile); } //Setup the connection for automatic cleanup + connect(this, SIGNAL(started()), this, SLOT(processStarting()) ); connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished()) ); } diff --git a/src-qt5/core/lumina-desktop/LSession.cpp b/src-qt5/core/lumina-desktop/LSession.cpp index 6fceff1b..dab30f01 100644 --- a/src-qt5/core/lumina-desktop/LSession.cpp +++ b/src-qt5/core/lumina-desktop/LSession.cpp @@ -294,7 +294,7 @@ void LSession::launchStartupApps(){ qDebug() << " - - Screen Brightness:" << QString::number(tmp)+"%"; } //QProcess::startDetached("nice lumina-open -autostart-apps"); - ExternalProcess::launch("nice lumina-open -autostart-apps"); + ExternalProcess::launch("lumina-open", QStringList() << "-autostart-apps", false); //Re-load the screen brightness and volume settings from the previous session // Wait until after the XDG-autostart functions, since the audio system might be started that way @@ -589,7 +589,7 @@ void LSession::SessionEnding(){ //=============== void LSession::LaunchApplication(QString cmd){ //LSession::setOverrideCursor(QCursor(Qt::BusyCursor)); - ExternalProcess::launch(cmd); + ExternalProcess::launch(cmd, QStringList(), true); //QProcess::startDetached(cmd); } @@ -690,7 +690,7 @@ void LSession::WindowPropertyEvent(){ if(RunningApps.length() < newapps.length()){ //New Window found //qDebug() << "New window found"; - LSession::restoreOverrideCursor(); //restore the mouse cursor back to normal (new window opened?) + //LSession::restoreOverrideCursor(); //restore the mouse cursor back to normal (new window opened?) //Perform sanity checks on any new window geometries for(int i=0; i Date: Tue, 31 Oct 2017 10:10:51 -0400 Subject: fix for XDG processing --- src-qt5/core/libLumina/LUtils.cpp | 1 + src-qt5/core/libLumina/LuminaXDG.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LUtils.cpp b/src-qt5/core/libLumina/LUtils.cpp index 65c6ac96..3d3c878a 100644 --- a/src-qt5/core/libLumina/LUtils.cpp +++ b/src-qt5/core/libLumina/LUtils.cpp @@ -123,6 +123,7 @@ bool LUtils::writeFile(QString filepath, QStringList contents, bool overwrite){ bool LUtils::isValidBinary(QString& bin){ //Trim off any quotes if(bin.startsWith("\"") && bin.endsWith("\"")){ bin.chop(1); bin = bin.remove(0,1); } + if(bin.startsWith("\'") && bin.endsWith("\'")){ bin.chop(1); bin = bin.remove(0,1); } //Now look for relative/absolute path if(!bin.startsWith("/")){ //Relative path: search for it on the current "PATH" settings diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index aaca7bb1..492a296c 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -729,7 +729,8 @@ bool LFileInfo::isAVFile(){ bool LXDG::checkExec(QString exec){ //Return true(good) or false(bad) //Check for quotes around the exec, and remove them as needed - if(exec.startsWith("\"") && exec.count("\"")>=2){ exec = exec.section("\"",1,1); } + if(exec.startsWith("\"") && exec.count("\"")>=2){ exec = exec.section("\"",1,1).simplified(); } + if(exec.startsWith("\'") && exec.count("\'")>=2){ exec = exec.section("\'",1,1).simplified(); } if(exec.startsWith("/")){ return QFile::exists(exec); } else{ QStringList paths = QString(getenv("PATH")).split(":"); -- cgit From 60de7e7db69e2afcf5269bcba3a96fc61baeb325 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 31 Oct 2017 10:31:56 -0400 Subject: Add a quick verify/modify of the directory used for the Lumina wallpapers. Try to adjust the old path to the new one automatically. --- src-qt5/core/lumina-desktop/LDesktop.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop/LDesktop.cpp b/src-qt5/core/lumina-desktop/LDesktop.cpp index 1fc6b11b..71b10bd5 100644 --- a/src-qt5/core/lumina-desktop/LDesktop.cpp +++ b/src-qt5/core/lumina-desktop/LDesktop.cpp @@ -539,7 +539,16 @@ void LDesktop::UpdateBackground(){ //qDebug() << " - List:" << bgL << CBG; //Remove any invalid files for(int i=0; i Date: Tue, 31 Oct 2017 10:32:23 -0400 Subject: remove wallpapers from Project --- src-qt5/core/lumina-desktop/lumina-desktop.pro | 11 ----------- .../wallpapers/Lumina_Wispy_blue-grey-zoom.jpg | Bin 6269314 -> 0 bytes .../wallpapers/Lumina_Wispy_blue-grey.jpg | Bin 6508360 -> 0 bytes .../lumina-desktop/wallpapers/Lumina_Wispy_gold.jpg | Bin 2523711 -> 0 bytes .../lumina-desktop/wallpapers/Lumina_Wispy_green.jpg | Bin 1286362 -> 0 bytes .../wallpapers/Lumina_Wispy_grey-blue-zoom.jpg | Bin 563037 -> 0 bytes .../wallpapers/Lumina_Wispy_grey-blue.jpg | Bin 361771 -> 0 bytes .../lumina-desktop/wallpapers/Lumina_Wispy_purple.jpg | Bin 926969 -> 0 bytes .../lumina-desktop/wallpapers/Lumina_Wispy_red.jpg | Bin 1141515 -> 0 bytes 9 files changed, 11 deletions(-) delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey.jpg delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_gold.jpg delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_green.jpg delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue.jpg delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_purple.jpg delete mode 100644 src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_red.jpg (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop/lumina-desktop.pro b/src-qt5/core/lumina-desktop/lumina-desktop.pro index d4e57c5c..2c944a11 100644 --- a/src-qt5/core/lumina-desktop/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop/lumina-desktop.pro @@ -77,17 +77,6 @@ fluxconf.files = fluxboxconf/fluxbox-init-rc \ fluxboxconf/fluxbox-keys fluxconf.path = $${L_SHAREDIR}/lumina-desktop/ -wallpapers.files = wallpapers/Lumina_Wispy_gold.jpg \ - wallpapers/Lumina_Wispy_green.jpg \ - wallpapers/Lumina_Wispy_purple.jpg \ - wallpapers/Lumina_Wispy_red.jpg \ - wallpapers/Lumina_Wispy_blue-grey.jpg \ - wallpapers/Lumina_Wispy_blue-grey-zoom.jpg \ - wallpapers/Lumina_Wispy_grey-blue.jpg \ - wallpapers/Lumina_Wispy_grey-blue-zoom.jpg -wallpapers.path = $${L_SHAREDIR}/wallpapers/Lumina-DE - - defaults.files = defaults/luminaDesktop.conf \ defaults/compton.conf \ audiofiles/Logout.ogg \ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg deleted file mode 100644 index 481ca438..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey-zoom.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey.jpg deleted file mode 100644 index 9da67596..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_blue-grey.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_gold.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_gold.jpg deleted file mode 100644 index cba03cee..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_gold.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_green.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_green.jpg deleted file mode 100644 index 80b0d3e3..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_green.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg deleted file mode 100644 index 4f753ed5..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue-zoom.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue.jpg deleted file mode 100644 index c214cd78..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_grey-blue.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_purple.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_purple.jpg deleted file mode 100644 index e4c3d7a8..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_purple.jpg and /dev/null differ diff --git a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_red.jpg b/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_red.jpg deleted file mode 100644 index a092f636..00000000 Binary files a/src-qt5/core/lumina-desktop/wallpapers/Lumina_Wispy_red.jpg and /dev/null differ -- cgit From 831978b09138ac2aa891311f1382a0d81c1f5010 Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 31 Oct 2017 12:59:26 -0400 Subject: initial commit for sound themeing page --- src-qt5/core-utils/lumina-config/pages/pages.pri | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core-utils/lumina-config/pages/pages.pri b/src-qt5/core-utils/lumina-config/pages/pages.pri index ce167d27..a2022367 100644 --- a/src-qt5/core-utils/lumina-config/pages/pages.pri +++ b/src-qt5/core-utils/lumina-config/pages/pages.pri @@ -13,7 +13,8 @@ HEADERS += $${PWD}/getPage.h \ $${PWD}/page_interface_panels.h \ $${PWD}/page_session_locale.h \ $${PWD}/page_session_options.h \ - $${PWD}/page_compton.h + $${PWD}/page_compton.h \ + $$PWD/page_soundtheme.h # $${PWD}/page_bluetooth_trueos.h # $${PWD}/page_mouse_trueos.h @@ -31,7 +32,8 @@ SOURCES += $${PWD}/getPage.cpp \ $${PWD}/page_interface_panels.cpp \ $${PWD}/page_session_locale.cpp \ $${PWD}/page_session_options.cpp \ - $${PWD}/page_compton.cpp + $${PWD}/page_compton.cpp \ + $$PWD/page_soundtheme.cpp # $${PWD}/page_bluetooth_trueos.cpp # $${PWD}/page_mouse_trueos.cpp @@ -49,6 +51,7 @@ FORMS += $${PWD}/page_main.ui \ $${PWD}/page_interface_panels.ui \ $${PWD}/page_session_locale.ui \ $${PWD}/page_session_options.ui \ - $${PWD}/page_compton.ui + $${PWD}/page_compton.ui \ + $$PWD/page_soundtheme.ui # $${PWD}/page_bluetooth_trueos.ui # $${PWD}/page_mouse_trueos.ui -- cgit From fa667a0c5a942a14fde891a9ef09254f005d1d67 Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 31 Oct 2017 13:41:25 -0400 Subject: add bool to battery sound alert --- src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp | 5 ++++- src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src-qt5') 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 cae73d13..7a6b0e7c 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.cpp @@ -20,6 +20,7 @@ LBattery::LBattery(QWidget *parent, QString id, bool horizontal) : LPPlugin(pare connect(timer,SIGNAL(timeout()), this, SLOT(updateBattery()) ); timer->start(); QTimer::singleShot(0,this,SLOT(OrientationChange()) ); //update the sizing/icon + sessionsettings = new QSettings("lumina-desktop", "sessionsettings"); } LBattery::~LBattery(){ @@ -78,7 +79,8 @@ void LBattery::updateBattery(bool force){ } if(iconsessionSettings()->value("audiofiles/batterylow", LOS::LuminaShare()+"low-battery.ogg").toString(); + 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); } @@ -95,6 +97,7 @@ void LBattery::updateBattery(bool force){ else{ tt = QString( tr("%1 % (%2 Remaining)") ).arg(QString::number(charge), getRemainingTime() ); } label->setToolTip(tt); } +} QString LBattery::getRemainingTime(){ int secs = LOS::batterySecondsLeft(); diff --git a/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.h b/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.h index d14cfc53..3c23be1c 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.h +++ b/src-qt5/core/lumina-desktop/panel-plugins/battery/LBattery.h @@ -30,6 +30,7 @@ private: QTimer *timer; QLabel *label; int iconOld; + QSettings *sessionsettings; private slots: void updateBattery(bool force = false); -- cgit From f16be4917ead3ccceb9debafa91272b6786dd731 Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 31 Oct 2017 15:21:19 -0400 Subject: finish and enable sound theme page for lumina-config --- src-qt5/core-utils/lumina-config/pages/getPage.cpp | 4 +++- src-qt5/core-utils/lumina-config/pages/pages.pri | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core-utils/lumina-config/pages/getPage.cpp b/src-qt5/core-utils/lumina-config/pages/getPage.cpp index 7274ae3f..c3f88e2c 100644 --- a/src-qt5/core-utils/lumina-config/pages/getPage.cpp +++ b/src-qt5/core-utils/lumina-config/pages/getPage.cpp @@ -20,6 +20,7 @@ #include "page_session_locale.h" #include "page_session_options.h" #include "page_compton.h" +#include "page_soundtheme.h" // #include "page_mouse_trueos.h" // #include "page_bluetooth_trueos.h" @@ -51,6 +52,7 @@ QList Pages::KnownPages(){ list << Pages::PageInfo("interface-menu", QObject::tr("Menu"), QObject::tr("Menu Plugins"), "format-list-unordered",QObject::tr("Change what options are shown on the desktop context menu"), "interface", QStringList(), QStringList() << "desktop" << "menu" << "plugins" << "shortcuts"); list << Pages::PageInfo("session-locale", QObject::tr("Localization"), QObject::tr("Locale Settings"), "preferences-desktop-locale",QObject::tr("Change the default locale settings for this user"), "user", QStringList(), QStringList() << "user"<<"locale"<<"language"<<"translations"); list << Pages::PageInfo("session-options", QObject::tr("General Options"), QObject::tr("User Settings"), "configure",QObject::tr("Change basic user settings such as time/date formats"), "user", QStringList(), QStringList() << "user"<<"settings"<<"time"<<"date"<<"icon"<<"reset"<<"numlock"<<"clock"); + list << Pages::PageInfo("soundtheme", QObject::tr("Sound Themeing"), QObject::tr("Theme"), "media-playlist-audio",QObject::tr("Change basic sound settings"), "session", QStringList(), QStringList() << "session"<<"settings"<<"sound"<<"theme"); // list << Pages::PageInfo("mouse-settings", QObject::tr("TrueOS Mouse Settings"), QObject::tr("TrueOS Mouse Settings"), "preferences-desktop-mouse",QObject::tr("Adjust mouse devices"), "user", QStringList(), QStringList() << "user"<<"speed"<<"accel"<<"mouse"); // list << Pages::PageInfo("bluetooth-settings", QObject::tr("TrueOS Bluetooth Settings"), QObject::tr("TrueOS Bluetooth Settings"), "preferences-desktop-bluetooth",QObject::tr("Setup Bluetooth devices"), "user", QStringList(), QStringList() << "user"<<"bluetooth"<<"audio"); @@ -72,7 +74,7 @@ PageWidget* Pages::GetNewPage(QString id, QWidget *parent){ else if(id=="session-locale"){ page = new page_session_locale(parent); } else if(id=="session-options"){ page = new page_session_options(parent); } else if(id=="compton"){ page = new page_compton(parent); } - + else if(id=="soundtheme"){ page = new page_soundtheme(parent); } // else if(id=="mouse-settings"){ page = new page_mouse_trueos(parent); } // else if(id=="bluetooth-settings"){ page = new page_bluetooth_trueos(parent); } //Return the main control_panel page as the fallback/default diff --git a/src-qt5/core-utils/lumina-config/pages/pages.pri b/src-qt5/core-utils/lumina-config/pages/pages.pri index a2022367..585a2922 100644 --- a/src-qt5/core-utils/lumina-config/pages/pages.pri +++ b/src-qt5/core-utils/lumina-config/pages/pages.pri @@ -14,8 +14,8 @@ HEADERS += $${PWD}/getPage.h \ $${PWD}/page_session_locale.h \ $${PWD}/page_session_options.h \ $${PWD}/page_compton.h \ - $$PWD/page_soundtheme.h -# $${PWD}/page_bluetooth_trueos.h + $$PWD/page_soundtheme.h +# $${PWD}/page_bluetooth_trueos.h # $${PWD}/page_mouse_trueos.h @@ -33,7 +33,7 @@ SOURCES += $${PWD}/getPage.cpp \ $${PWD}/page_session_locale.cpp \ $${PWD}/page_session_options.cpp \ $${PWD}/page_compton.cpp \ - $$PWD/page_soundtheme.cpp + $$PWD/page_soundtheme.cpp # $${PWD}/page_bluetooth_trueos.cpp # $${PWD}/page_mouse_trueos.cpp @@ -52,6 +52,6 @@ FORMS += $${PWD}/page_main.ui \ $${PWD}/page_session_locale.ui \ $${PWD}/page_session_options.ui \ $${PWD}/page_compton.ui \ - $$PWD/page_soundtheme.ui + $$PWD/page_soundtheme.ui # $${PWD}/page_bluetooth_trueos.ui # $${PWD}/page_mouse_trueos.ui -- cgit From d1fbff37e4cac77ef8ab46ca9148cd21451a43de Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 31 Oct 2017 16:39:48 -0400 Subject: finish up integration of launch lumina-fm as root --- src-qt5/desktop-utils/lumina-fm/MainUI.cpp | 2 ++ src-qt5/desktop-utils/lumina-fm/MainUI.ui | 2 ++ src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp | 13 +++++++++++-- src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h | 3 ++- src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui | 7 +++++++ 5 files changed, 24 insertions(+), 3 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp index 87c3a0f8..692b7562 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp @@ -116,6 +116,7 @@ QSize orig = settings->value("preferences/MainWindowSize", QSize()).toSize(); TRAY = new TrayUI(this); connect(TRAY, SIGNAL(JobsFinished()), this, SLOT(TrayJobsFinished()) ); if(DEBUG){ qDebug() << " - Done with init"; } + ui->actionOpen_as_Root->setVisible(LUtils::isValidBinary("qsudo")); } MainUI::~MainUI(){ @@ -971,3 +972,4 @@ void MainUI::on_actionOpen_as_Root_triggered() { ExternalProcess::launch("qsudo lumina-fm"); } + diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.ui b/src-qt5/desktop-utils/lumina-fm/MainUI.ui index 56de9b7c..8a635199 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.ui @@ -119,6 +119,8 @@ + + diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp index a8cbea2c..83040108 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.cpp @@ -284,10 +284,11 @@ void DirWidget::createMenus(){ else{ cOpenMenu->clear(); } cOpenMenu->setTitle(tr("Launch...")); cOpenMenu->setIcon( LXDG::findIcon("quickopen","") ); - cOpenMenu->addAction(LXDG::findIcon("utilities-terminal",""), tr("Terminal"), this, SLOT(openTerminal()), kOpTerm->key()); + cOpenMenu->addAction(LXDG::findIcon("utilities-terminal",""), tr("Open Current Dir in a Terminal"), this, SLOT(openTerminal()), kOpTerm->key()); cOpenMenu->addAction(LXDG::findIcon("media-slideshow",""), tr("SlideShow"), this, SLOT(openInSlideshow()), kOpSS->key()); cOpenMenu->addAction(LXDG::findIcon("media-playback-start-circled","media-playback-start"), tr("Multimedia Player"), this, SLOT(openMultimedia()), kOpMM->key()); -/* + if(LUtils::isValidBinary("qsudo")){ cOpenMenu->addAction(LXDG::findIcon("", ""), tr("Open Current Dir as Root"), this, SLOT(openRootFM())); + /* if(cFModMenu==0){ cFModMenu = new QMenu(this); } else{ cFModMenu->clear(); } cFModMenu->setTitle(tr("Modify Files...")); @@ -322,6 +323,8 @@ void DirWidget::createMenus(){ } +} + BrowserWidget* DirWidget::currentBrowser(){ if(cBID.isEmpty() || RCBW==0){ return BW; } else{ return RCBW; } @@ -883,3 +886,9 @@ void DirWidget::mouseReleaseEvent(QMouseEvent *ev){ ev->ignore(); //not handled here } } + +void DirWidget::openRootFM(){ + rootfmdir = "qsudo lumina-fm -new-instance " + currentDir(); + qDebug() << "rootfmdir" << rootfmdir; + ExternalProcess::launch(rootfmdir); +} diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h index 8dd367df..04af46fc 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.h @@ -73,7 +73,7 @@ private: Ui::DirWidget *ui; BrowserWidget *BW, *RCBW; //Main BrowserWidget and right-column browser widget QString ID, cBID; //unique ID assigned by the parent, and currently active browser widget - QString normalbasedir, snapbasedir, snaprelpath; //for maintaining directory context while moving between snapshots + QString normalbasedir, snapbasedir, snaprelpath, rootfmdir; //for maintaining directory context while moving between snapshots QStringList snapshots, needThumbs, tmpSel; QSettings *settings; bool canmodify; @@ -129,6 +129,7 @@ private slots: void fileCheckSums(); void fileProperties(); void openTerminal(); + void openRootFM(); //Browser Functions diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui index 099fd91a..5f980c67 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DirWidget2.ui @@ -25,11 +25,18 @@ Droid Sans Mono + 16 75 false true + + QFrame::Box + + + QFrame::Sunken + * - FILE MANAGER RUNNING AS ROOT- * -- cgit From b38e7a9ff3343c9e2bcaec07f5e495f901e15553 Mon Sep 17 00:00:00 2001 From: q5sys Date: Tue, 31 Oct 2017 16:43:23 -0400 Subject: update LSingleApplication to use getuid instead of getlogin --- src-qt5/core/libLumina/LuminaSingleApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LuminaSingleApplication.cpp b/src-qt5/core/libLumina/LuminaSingleApplication.cpp index 6811d147..5d276805 100644 --- a/src-qt5/core/libLumina/LuminaSingleApplication.cpp +++ b/src-qt5/core/libLumina/LuminaSingleApplication.cpp @@ -19,7 +19,7 @@ LSingleApplication::LSingleApplication(int &argc, char **argv, QString appname) if(appname!="lumina-desktop"){ cTrans = LUtils::LoadTranslation(this, appname); }//save the translator for later //Initialize a couple convenience internal variables cfile = QDir::tempPath()+"/.LSingleApp-%1-%2-%3"; - QString username = QString(getlogin()); + QString username = QString(getuid()); //For locking the process use the official process name - not the user input (no masking) appname = this->applicationName(); cfile = cfile.arg( username, appname, QString::number(QX11Info::appScreen()) ); -- cgit From 7920fb5dc05d9527267bad414cc3b3f0a661067a Mon Sep 17 00:00:00 2001 From: q5sys Date: Wed, 1 Nov 2017 11:44:43 -0400 Subject: add sound theme pages --- .../lumina-config/pages/page_soundtheme.cpp | 113 +++++++++++++++ .../lumina-config/pages/page_soundtheme.h | 42 ++++++ .../lumina-config/pages/page_soundtheme.ui | 156 +++++++++++++++++++++ 3 files changed, 311 insertions(+) create mode 100644 src-qt5/core-utils/lumina-config/pages/page_soundtheme.cpp create mode 100644 src-qt5/core-utils/lumina-config/pages/page_soundtheme.h create mode 100644 src-qt5/core-utils/lumina-config/pages/page_soundtheme.ui (limited to 'src-qt5') diff --git a/src-qt5/core-utils/lumina-config/pages/page_soundtheme.cpp b/src-qt5/core-utils/lumina-config/pages/page_soundtheme.cpp new file mode 100644 index 00000000..fbb0e7e7 --- /dev/null +++ b/src-qt5/core-utils/lumina-config/pages/page_soundtheme.cpp @@ -0,0 +1,113 @@ +//=========================================== +// Lumina Desktop Source Code +// Copyright (c) 2017, JT (q5sys) +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "page_soundtheme.h" +#include "ui_page_soundtheme.h" +#include "../AppDialog.h" + +//========== +// PUBLIC +//========== +page_soundtheme::page_soundtheme(QWidget *parent) : PageWidget(parent), ui(new Ui::page_soundtheme()){ + ui->setupUi(this); +} + +page_soundtheme::~page_soundtheme(){ + +} + +//================ +// PUBLIC SLOTS +//================ +void page_soundtheme::SaveSettings(){ + sessionsettings = new QSettings("lumina-desktop", "sessionsettings"); + + sessionsettings->setValue("PlayStartupAudio", ui->checkBox_startup->isChecked()); + sessionsettings->setValue("audiofiles/login", ui->label_startup->whatsThis()); + + sessionsettings->setValue("PlayLogoutAudio", ui->checkBox_logout->isChecked()); + sessionsettings->setValue("audiofiles/logout", ui->label_logout->whatsThis()); + + sessionsettings->setValue("PlayBatteryLowAudio", ui->checkBox_battery->isChecked()); + sessionsettings->setValue("audiofiles/batterylow", ui->label_battery->whatsThis()); + +} + +void page_soundtheme::LoadSettings(int){ + emit ChangePageTitle( tr("Sound Themes") ); + + sessionsettings = new QSettings("lumina-desktop", "sessionsettings"); + + ui->label_startup->setText(sessionsettings->value("audiofiles/login").toString().section("/",-1)); + ui->label_startup->setToolTip(sessionsettings->value("audiofiles/batterylow").toString()); + ui->label_startup->setWhatsThis(sessionsettings->value("audiofiles/login").toString()); + bool playstartup = sessionsettings->value("PlayStartupAudio").toBool(); + if( playstartup ){ ui->checkBox_startup->setChecked(true); } + + ui->label_logout->setText(sessionsettings->value("audiofiles/logout").toString().section("/",-1)); + ui->label_startup->setToolTip(sessionsettings->value("audiofiles/batterylow").toString()); + ui->label_logout->setWhatsThis(sessionsettings->value("audiofiles/logout").toString()); + bool playlogout = sessionsettings->value("PlayLogoutAudio").toBool(); + if( playlogout ){ ui->checkBox_logout->setChecked(true); } + + ui->label_battery->setText(sessionsettings->value("audiofiles/batterylow").toString().section("/",-1)); + ui->label_startup->setToolTip(sessionsettings->value("audiofiles/batterylow").toString()); + ui->label_battery->setWhatsThis(sessionsettings->value("audiofiles/batterylow").toString()); + bool playbattery = sessionsettings->value("PlayBatteryLowAudio").toBool(); + if( playbattery ){ ui->checkBox_battery->setChecked(true);} + emit HasPendingChanges(false); +} + +//================= +// PRIVATE +//================= + +//================= +// PRIVATE SLOTS +//================= + +void page_soundtheme::on_pushButton_startup_clicked(){ + QString startupsound = QFileDialog::getOpenFileName(this, tr("Select Startup Sound"), QDir::homePath()); + if(startupsound.isEmpty()){ return; } + ui->label_startup->setText(startupsound.section("/",-1)); + ui->label_startup->setToolTip(startupsound); + ui->label_startup->setWhatsThis(startupsound); + settingChanged(); + qDebug() << "startup whats this" << startupsound; +} + +void page_soundtheme::on_pushButton_logout_clicked(){ + QString logoutsound = QFileDialog::getOpenFileName(this, tr("Select Logout Sound"), QDir::homePath()); + if(logoutsound.isEmpty()){ return; } + ui->label_logout->setText(logoutsound.section("/",-1)); + ui->label_logout->setToolTip(logoutsound); + ui->label_logout->setWhatsThis(logoutsound); + qDebug() << "startup whats this" << logoutsound; + settingChanged(); +} + +void page_soundtheme::on_pushButton_battery_clicked(){ + QString batterysound = QFileDialog::getOpenFileName(this, tr("Select Low Battery Sound"), QDir::homePath()); + if(batterysound.isEmpty()){ return; } + ui->label_battery->setText(batterysound.section("/",-1)); + ui->label_battery->setToolTip(batterysound); + ui->label_battery->setWhatsThis(batterysound); + qDebug() << "startup whats this" << batterysound; + settingChanged(); +} + + +void page_soundtheme::on_checkBox_startup_toggled(bool checked){ + settingChanged(); +} + +void page_soundtheme::on_checkBox_logout_toggled(bool checked){ + settingChanged(); +} + +void page_soundtheme::on_checkBox_battery_toggled(bool checked){ + settingChanged(); +} diff --git a/src-qt5/core-utils/lumina-config/pages/page_soundtheme.h b/src-qt5/core-utils/lumina-config/pages/page_soundtheme.h new file mode 100644 index 00000000..5d3bed66 --- /dev/null +++ b/src-qt5/core-utils/lumina-config/pages/page_soundtheme.h @@ -0,0 +1,42 @@ +//=========================================== +// Lumina Desktop Source Code +// Copyright (c) 2017, JT (q5sys) +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#ifndef _LUMINA_CONFIG_PAGE_SOUNDTHEME_H +#define _LUMINA_CONFIG_PAGE_SOUNDTHEME_H +#include "../globals.h" +#include "PageWidget.h" + +namespace Ui{ + class page_soundtheme; +}; + +class page_soundtheme : public PageWidget{ + Q_OBJECT +public: + page_soundtheme(QWidget *parent); + ~page_soundtheme(); + +public slots: + + void SaveSettings(); + void LoadSettings(int screennum); + + +private: + Ui::page_soundtheme *ui; + QString startupsound, logoutsound, batterysound; + QSettings *sessionsettings; + +private slots: + + void on_pushButton_startup_clicked(); + void on_pushButton_logout_clicked(); + void on_pushButton_battery_clicked(); + void on_checkBox_startup_toggled(bool checked); + void on_checkBox_logout_toggled(bool checked); + void on_checkBox_battery_toggled(bool checked); +}; +#endif diff --git a/src-qt5/core-utils/lumina-config/pages/page_soundtheme.ui b/src-qt5/core-utils/lumina-config/pages/page_soundtheme.ui new file mode 100644 index 00000000..329b68a4 --- /dev/null +++ b/src-qt5/core-utils/lumina-config/pages/page_soundtheme.ui @@ -0,0 +1,156 @@ + + + page_soundtheme + + + + 0 + 0 + 455 + 326 + + + + Form + + + + + + + + Enabled + + + + + + + Qt::Vertical + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Set Startup Audio + + + + + + + + + + + Enabled + + + + + + + Qt::Vertical + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Set Logout Audio + + + + + + + + + + + Enabled + + + + + + + Qt::Vertical + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Set Battery Audio + + + + + + + + + + -- cgit From cbfa5b5d7e17b2f20cc415106513847e06292047 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 1 Nov 2017 12:45:10 -0400 Subject: Add the template for a new model-based backend for lumina-fm. --- src-qt5/desktop-utils/lumina-fm/BrowserModel.cpp | 208 +++++++++++++++++++++ src-qt5/desktop-utils/lumina-fm/BrowserModel.h | 85 +++++++++ .../lumina-fm/widgets/DDListWidgets.h | 34 ++-- 3 files changed, 310 insertions(+), 17 deletions(-) create mode 100644 src-qt5/desktop-utils/lumina-fm/BrowserModel.cpp create mode 100644 src-qt5/desktop-utils/lumina-fm/BrowserModel.h (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserModel.cpp b/src-qt5/desktop-utils/lumina-fm/BrowserModel.cpp new file mode 100644 index 00000000..d79da006 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/BrowserModel.cpp @@ -0,0 +1,208 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore & JT Pennington +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "BrowserModel.h" + +BrowserModel::BrowserModel(QObject *parent){ + +} + +BrowserModel::~BrowserModel(){ + +} + +//Virtual overrides +QModelIndex BrowserModel::index(int row, int column, const QModelIndex &parent) const{ + +} + +QModelIndex BrowserModel::parent(const QModelIndex &index) const{ + +} + +// item management +int BrowserModel::rowCount(const QModelIndex &parent) const{ + +} + +bool BrowserModel::insertRows(int row, int count, const QModelIndex &parent){ + +} + +bool BrowserModel::removeRow(int row, const QModelIndex &parent){ + +} + +bool BrowserModel::removeRows(int row, int count, const QModelIndex &parent){ + +} + +int BrowserModel::columnCount(const QModelIndex &parent) const{ + +} + +bool BrowserModel::insertColumns(int column, int count, const QModelIndex &parent){ + +} + +bool BrowserModel::removeColumn(int column, const QModelIndex &parent){ + +} + +bool BrowserModel::removeColumns(int column, int count, const QModelIndex &parent){ + +} + + +//bool BrowserModel::hasChildren(const QModelIndex &parent) const{ + +} + + +// data functions +Qt::ItemFlags BrowserModel::flags(const QModelIndex &index) const{ + +} + +QVariant BrowserModel::data(const QModelIndex &index, int role) const{ + QFileInfo *info = indexToInfo(index); + switch(role){ + case Qt::DisplayRole: + if(index.column()==0){ return QVariant(info->fileName()); } + else if(index.column()==1){ return QVariant(info->fileSize()); } + else if(index.column()==2){ return QVariant(info->mimetype()); } + else if(index.column()==3){ return QVariant(info->lastModified()->toString(Qt::DefaultLocaleShortDate)); } + else if(index.column()==4){ return QVariant(info->created()->toString(Qt::DefaultLocaleShortDate)); } + case Qt::ToolTipRole: + return QVariant(info->absoluteFilePath()); + case Qt::StatusTipRole: + return QVariant(info->absoluteFilePath()); + case Qt::SizeHintRole; + return QVariant(QSize(100,14)); + case Qt::DecorationRole: + return QVariant(LXDG::findIcon(info->iconFile(), "unknown")); + } + return QVariant(); +} + +QVariant BrowserModel::headerData(int section, Qt::Orientation orientation, int role) const{ + if(role == Qt::DisplayRole){ + if(orientation == Qt::Horizontal){ + switch(section){ + case 0: + return QVariant(tr("File Name")); + case 1: + return QVariant("Size"); + case 2: + return QVariant("Type"); + case 3: + return QVariant("Date Modified"); + case 4: + return QVariant("Date Created"); + } + } + } + case Qt::DisplayRole: + return QVariant(tr("File Name"); + /*case Qt::ToolTipRole: + return QVariant("ToolTip"); + case Qt::StatusTipRole: + return QVariant("Status Tip"); + case Qt::SizeHintRole; + return QVariant(QSize(100,14));*/ + case Qt::DecorationRole: + return QVariant("Icon")); + } + return QVariant(); +} + +// data modification functions +bool BrowserModel::setData(const QModelIndex &index, const QVariant &value, int role){ + +} + +bool BrowserModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role){ + +} + + +// drag and drop +//QMimeData* BrowserModel::mimeData(const QModelIndexList &indexes) const{ + +} + +//QStringList BrowserModel::mimeTypes() const{ + +} + +//bool BrowserModel::setItemData(const QModelIndex &index, const QMap &roles){ + +} + +//Qt::DropActions BrowserModel::supportedDropActions() const{ + +} + +//bool BrowserModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent){ + +} + +//Special Functions (non virtual replacements) +LFileInfo* BrowserModel::fileInfo(QString name){ + +} + +QString BrowserModel::currentDirectory(){ + return cDir; +} + + +// ============== +// PUBLIC SLOTS +// ============== +void BrowserModel::loadDirectory(QString dir){ + + +} + +void BrowserModel::loadItem(QString itempath){ + LFileInfo *it = new LFileInfo(itempath); + //Determine the row/column that it needs to be + int row, column; + row = 0; + //Now create the index + for(int i=0; i<5; i++){ + QModelIndex index = createIndex(row, i, it); + } +} + + +// ============= +// PRIVATE +// ============= +/*QString BrowserModel::findInHash(QString path){ + QStringList keys = HASH.keys(); + for(int i=0; ifilePath() == path){ return keys[i]; } + } + return ""; +} + +QString BrowserModel::findInHash(QModelIndex index){ + QString id = QString::number(index.row())+"/"+QString::number(index.column()); + if(HASH.contains(id)){ return id; } + return ""; +} + +LFileInfo* BrowserModel::indexToInfo(QString path){ + QString id = findInHash(path); + if(id.isEmpty()){ return 0;} + return HASH[id]; +}*/ + +LFileInfo* BrowserModel::indexToInfo(QModelIndex index){ + return static_cast(index.internalPointer()); +} diff --git a/src-qt5/desktop-utils/lumina-fm/BrowserModel.h b/src-qt5/desktop-utils/lumina-fm/BrowserModel.h new file mode 100644 index 00000000..0968b4d4 --- /dev/null +++ b/src-qt5/desktop-utils/lumina-fm/BrowserModel.h @@ -0,0 +1,85 @@ +//=========================================== +// Lumina Desktop source code +// Copyright (c) 2017, Ken Moore & JT Pennington +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +// This is the main browsing backend for the file manager +//=========================================== +#ifndef _LUMINA_FM_BROWSER_MODEL_BACKEND_H +#define _LUMINA_FM_BROWSER_MODEL_BACKEND_H + +#include +#include +#include +#include +#include +#include + +#include + +class BrowserModel : public QAbstractItemModel { + Q_OBJECT +public: + BrowserModel(QObject *parent = 0); + ~BrowserModel(); + + //Virtual overrides + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + + // item management + int rowCount(const QModelIndex &parent = QModelIndex()) const; + bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); + bool removeRow(int row, const QModelIndex &parent = QModelIndex()); + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + + int columnCount(const QModelIndex &parent = QModelIndex()) const; + bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()); + bool removeColumn(int column, const QModelIndex &parent = QModelIndex()); + bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()); + + //bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + + // data functions + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + // data modification functions + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); + + // drag and drop + //QMimeData* mimeData(const QModelIndexList &indexes) const; + //QStringList mimeTypes() const; + //bool setItemData(const QModelIndex &index, const QMap &roles); + //Qt::DropActions supportedDropActions() const; + //bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); + + //Special Functions (non virtual replacements) + LFileInfo* fileInfo(QString name); + QString currentDirectory(); + +public slots: + void loadDirectory(QString dir=""); + void loadItem(QString item); + +private: + QHash HASH; //QString: "row/column" + QString cDir; + //simplification functions + /*QString findInHash(QString path); + QString findInHash(QModelIndex index); + LFileInfo* indexToInfo(QString path);*/ + LFileInfo* indexToInfo(QModelIndex index); + +private slots: + +protected: + +signals: + +}; + +#endif + diff --git a/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h b/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h index 254362fd..da4131e0 100644 --- a/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h +++ b/src-qt5/desktop-utils/lumina-fm/widgets/DDListWidgets.h @@ -63,8 +63,8 @@ protected: QList items = this->selectedItems(); if(items.length()<1){ return; } QList urilist; - for(int i=0; iwhatsThis()); + for(int i=0; iwhatsThis()); } //Create the mime data //qDebug() << "Start Drag:" << urilist; @@ -88,7 +88,7 @@ protected: ev->ignore(); } } - + void dragMoveEvent(QDragMoveEvent *ev){ if(ev->mimeData()->hasUrls() && !this->whatsThis().isEmpty() ){ //Change the drop type depending on the data/dir @@ -104,7 +104,7 @@ protected: } this->update(); } - + void dropEvent(QDropEvent *ev){ if(this->whatsThis().isEmpty() || !ev->mimeData()->hasUrls() ){ ev->ignore(); return; } //not supported //qDebug() << "Drop Event:"; @@ -125,7 +125,7 @@ protected: foreach(const QUrl &url, ev->mimeData()->urls()){ const QString filepath = url.toLocalFile(); //If the target file is modifiable, assume a move - otherwise copy - if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home))){ + if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home))){ if(filepath.section("/",0,-2)!=dirpath){ files << "cut::::"+filepath; } //don't "cut" a file into the same dir }else{ files << "copy::::"+filepath; } } @@ -133,18 +133,18 @@ protected: if(!files.isEmpty()){ emit DataDropped( dirpath, files ); } this->setCursor(Qt::ArrowCursor); } - + void mouseReleaseEvent(QMouseEvent *ev){ if(ev->button() != Qt::RightButton && ev->button() != Qt::LeftButton){ ev->ignore(); } else{ QListWidget::mouseReleaseEvent(ev); } //pass it along to the widget } void mousePressEvent(QMouseEvent *ev){ if(ev->button() != Qt::RightButton && ev->button() != Qt::LeftButton){ ev->ignore(); } - else{ QListWidget::mousePressEvent(ev); } //pass it along to the widget + else{ QListWidget::mousePressEvent(ev); } //pass it along to the widget } /*void mouseMoveEvent(QMouseEvent *ev){ if(ev->button() != Qt::RightButton && ev->button() != Qt::LeftButton){ ev->ignore(); } - else{ QListWidget::mouseMoveEvent(ev); } //pass it along to the widget + else{ QListWidget::mouseMoveEvent(ev); } //pass it along to the widget }*/ }; @@ -183,8 +183,8 @@ protected: QList items = this->selectedItems(); if(items.length()<1){ return; } QList urilist; - for(int i=0; iwhatsThis(0)); + for(int i=0; iwhatsThis(0)); } //Create the mime data QMimeData *mime = new QMimeData; @@ -205,9 +205,9 @@ protected: ev->acceptProposedAction(); //allow this to be dropped here }else{ ev->ignore(); - } + } } - + void dragMoveEvent(QDragMoveEvent *ev){ if(ev->mimeData()->hasUrls() && !this->whatsThis().isEmpty() ){ //Change the drop type depending on the data/dir @@ -219,7 +219,7 @@ protected: ev->ignore(); } } - + void dropEvent(QDropEvent *ev){ if(this->whatsThis().isEmpty() || !ev->mimeData()->hasUrls() ){ ev->ignore(); return; } //not supported ev->accept(); //handled here @@ -239,25 +239,25 @@ protected: foreach(const QUrl &url, ev->mimeData()->urls()){ const QString filepath = url.toLocalFile(); //If the target file is modifiable, assume a move - otherwise copy - if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home))){ + if(QFileInfo(filepath).isWritable() && (filepath.startsWith(home) && dirpath.startsWith(home))){ if(filepath.section("/",0,-2)!=dirpath){ files << "cut::::"+filepath; } //don't "cut" a file into the same dir }else{ files << "copy::::"+filepath; } } //qDebug() << "Drop Event:" << dirpath; emit DataDropped( dirpath, files ); } - + void mouseReleaseEvent(QMouseEvent *ev){ if(ev->button() != Qt::RightButton && ev->button() != Qt::LeftButton){ ev->ignore(); } else{ QTreeWidget::mouseReleaseEvent(ev); } //pass it along to the widget } void mousePressEvent(QMouseEvent *ev){ if(ev->button() != Qt::RightButton && ev->button() != Qt::LeftButton){ ev->ignore(); } - else{ QTreeWidget::mousePressEvent(ev); } //pass it along to the widget + else{ QTreeWidget::mousePressEvent(ev); } //pass it along to the widget } /*void mouseMoveEvent(QMouseEvent *ev){ if(ev->button() != Qt::RightButton && ev->button() != Qt::LeftButton){ ev->ignore(); } - else{ QTreeWidget::mouseMoveEvent(ev); } //pass it along to the widget + else{ QTreeWidget::mouseMoveEvent(ev); } //pass it along to the widget }*/ }; -- cgit From a65d083fc98e36d3dd4b58052f73f44ce029b2ae Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 1 Nov 2017 12:46:48 -0400 Subject: Fix up some whitespace in luminaxdg.cpp --- src-qt5/core/libLumina/LuminaXDG.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LuminaXDG.cpp b/src-qt5/core/libLumina/LuminaXDG.cpp index 492a296c..cf9e0af2 100644 --- a/src-qt5/core/libLumina/LuminaXDG.cpp +++ b/src-qt5/core/libLumina/LuminaXDG.cpp @@ -896,7 +896,7 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){ fall << getChildIconDirs(paths[i]+"hicolor"); //XDG fallback (apps add to this) } //Now load all the icon theme dependencies in order (Theme1 -> Theme2 -> Theme3 -> Fallback) - + //fall << LOS::AppPrefix()+"share/pixmaps"; //always use this as well as a final fallback QDir::setSearchPaths("icontheme", theme); QDir::setSearchPaths("default", oxy); @@ -931,7 +931,7 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){ //simple PNG image - load directly into the QIcon structure ico.addFile(srch[i]+":"+iconName+".png"); } - + } //If still no icon found, look for any image format in the "pixmaps" directory if(ico.isNull()){ @@ -951,13 +951,13 @@ QIcon LXDG::findIcon(QString iconName, QString fallback){ break; } } - + } } //Use the fallback icon if necessary if(ico.isNull() ){ if(!fallback.isEmpty()){ ico = LXDG::findIcon(fallback,""); } - else if(iconName.contains("-x-") && !iconName.endsWith("-x-generic")){ + else if(iconName.contains("-x-") && !iconName.endsWith("-x-generic")){ //mimetype - try to use the generic type icon ico = LXDG::findIcon(iconName.section("-x-",0,0)+"-x-generic", ""); } @@ -974,7 +974,7 @@ QStringList LXDG::getChildIconDirs(QString parent){ QDir D(parent); QStringList out; QStringList dirs = D.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); - if(!dirs.isEmpty() && (dirs.contains("32x32") || dirs.contains("scalable")) ){ + if(!dirs.isEmpty() && (dirs.contains("32x32") || dirs.contains("scalable")) ){ //Need to sort these directories by image size //qDebug() << " - Parent:" << parent << "Dirs:" << dirs; for(int i=0; i. will still be caught) @@ -1067,7 +1067,7 @@ while(mimes.isEmpty()){ } } //Look for globs at the start of the filename - if(mimes.isEmpty()){ + if(mimes.isEmpty()){ mimes = mimefull.filter(":"+filename.left(2)); //look for the first 2 characters initially //Note: This initial filter will only work if the wildcard (*) is not within the first 2 characters of the pattern //Now ensure that the filter was accurate -- cgit From ccea2e1130bf1cf54aea58528a493aacadbeda13 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Wed, 1 Nov 2017 12:47:19 -0400 Subject: Start working on fixing up lumina-fileinfo --- src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 28 ++--- src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 11 +- src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui | 132 +++++++++++++++++++---- src-qt5/desktop-utils/lumina-fileinfo/main.cpp | 23 ++-- 4 files changed, 137 insertions(+), 57 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index c712afed..0247e011 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -15,15 +15,13 @@ #include #include -//LFileInfo INFO = LFileInfo(""); - MainUI::MainUI() : QDialog(), ui(new Ui::MainUI){ ui->setupUi(this); //load the designer form canwrite = false; terminate_thread = false; + INFO = new LFileInfo(); UpdateIcons(); //Set all the icons in the dialog SetupConnections(); - INFO = 0; } MainUI::~MainUI(){ @@ -80,7 +78,7 @@ void MainUI::LoadFile(QString path, QString type){ else{ ftype = INFO->suffix().toUpper(); } if(INFO->isHidden()){ ftype = QString(tr("Hidden %1")).arg(type); } ui->label_file_type->setText(ftype); - + //Now load the icon for the file if(INFO->isImage()){ QPixmap pix(INFO->absoluteFilePath()); @@ -159,18 +157,20 @@ void MainUI::LoadFile(QString path, QString type){ } void MainUI::UpdateIcons(){ - this->setWindowIcon(LXDG::findIcon("document-preview","unknown")); - ui->push_close->setIcon( LXDG::findIcon("dialog-close","") ); - ui->push_save->setIcon( LXDG::findIcon("document-save","") ); - ui->tool_xdg_getCommand->setIcon( LXDG::findIcon("edit-find-page","") ); - ui->tool_xdg_getDir->setIcon( LXDG::findIcon("document-open","") ); + } //============== // PRIVATE //============== void MainUI::ReloadAppIcon(){ - ui->push_xdg_getIcon->setIcon( LXDG::findIcon(ui->push_xdg_getIcon->whatsThis(),"") ); + //qDebug() << "Reload App Icon:"; + ui->label_xdg_icon->setPixmap( LXDG::findIcon(ui->line_xdg_icon->text(),"").pixmap(64,64) ); + //qDebug() << "Check Desktop File entry"; + if(INFO->iconfile()!=ui->line_xdg_icon->text()){ + xdgvaluechanged(); + } + //qDebug() << "Done with app icon"; } void MainUI::GetDirSize(const QString dirname) const { @@ -225,6 +225,7 @@ void MainUI::GetDirSize(const QString dirname) const { void MainUI::SetupConnections(){ connect(ui->line_xdg_command, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); connect(ui->line_xdg_comment, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); + connect(ui->line_xdg_icon, SIGNAL(textChanged(QString)), this, SLOT(ReloadAppIcon()) ); connect(ui->tool_xdg_getCommand, SIGNAL(clicked()), this, SLOT(getXdgCommand()) ); connect(ui->line_xdg_name, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); connect(ui->line_xdg_wdir, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); @@ -262,7 +263,7 @@ void MainUI::on_push_save_clicked(){ XDG->name = ui->line_xdg_name->text(); XDG->genericName = ui->line_xdg_name->text().toLower(); XDG->comment = ui->line_xdg_comment->text(); - XDG->icon = ui->push_xdg_getIcon->whatsThis(); + XDG->icon = ui->line_xdg_icon->text(); //Now do the type-specific fields if(XDG->type == XDGDesktop::APP){ XDG->exec = ui->line_xdg_command->text(); @@ -321,14 +322,15 @@ void MainUI::on_push_xdg_getIcon_clicked(){ for(int i=0; ipush_xdg_getIcon->setWhatsThis(file); + ui->line_xdg_icon->setText(file); ReloadAppIcon(); xdgvaluechanged(); } //XDG Value Changed void MainUI::xdgvaluechanged(){ - if(INFO!=0 && (INFO->isDesktopFile() || INFO->filePath().isEmpty() ) ){ + //qDebug() << "xdgvaluechanged"; + if( INFO->isDesktopFile() || INFO->filePath().isEmpty() ){ ui->push_save->setVisible(true); //Compare the current UI values to the file values ui->push_save->setEnabled(canwrite); //assume changed at this point diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index 8cac813c..089dbe6c 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -33,18 +33,17 @@ public: public slots: void UpdateIcons(); - + void ReloadAppIcon(); private: Ui::MainUI *ui; LFileInfo *INFO; - LVideoSurface *surface; - QMediaPlayer *player; - bool flag; - QElapsedTimer timer; + LVideoSurface *surface; + QMediaPlayer *player; + bool flag; + QElapsedTimer timer; bool canwrite; bool terminate_thread; //flag for terminating the GetDirSize task - void ReloadAppIcon(); void GetDirSize(const QString dirname) const; //function to get folder size signals: diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui index 51657ba1..d3b88b28 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui @@ -6,13 +6,22 @@ 0 0 - 349 - 354 + 535 + 580 + + + 0 + 0 + + File Information + + + @@ -307,9 +316,24 @@ + + + 0 + 0 + + + + + 16777215 + 42 + + + + + @@ -317,47 +341,107 @@ true + + + 0 + 0 + + + + + 16777215 + 42 + + + + + - - + + + + 0 + 0 + + + - 275 - 16777215 + 64 + 64 - - No Icon - - + 64 64 + + QFrame::StyledPanel + + + + - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 20000 + 42 + + + + + 2 + 2 + + + + + 0 + 0 + + + + + + + + + + + 24 + 24 + + + + @@ -391,6 +475,9 @@ Save + + + QToolButton::InstantPopup @@ -404,6 +491,9 @@ Close + + + QToolButton::DelayedPopup diff --git a/src-qt5/desktop-utils/lumina-fileinfo/main.cpp b/src-qt5/desktop-utils/lumina-fileinfo/main.cpp index a602f290..463f856a 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/main.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/main.cpp @@ -11,36 +11,25 @@ int main(int argc, char ** argv) { LTHEME::LoadCustomEnvSettings(); QApplication a(argc, argv); - a.setAttribute(Qt::AA_UseHighDpiPixmaps); + a.setAttribute(Qt::AA_UseHighDpiPixmaps); LUtils::LoadTranslation(&a, "l-fileinfo"); - //LuminaThemeEngine theme(&a); //Read the input variables QString path = ""; QString flag = ""; for(int i=1; i Date: Wed, 1 Nov 2017 12:47:54 -0400 Subject: Quick cleanup of input parsing in lumina-archiver. --- src-qt5/desktop-utils/lumina-archiver/MainUI.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp index c4b35474..79c023dc 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp @@ -91,24 +91,18 @@ void MainUI::LoadArguments(QStringList args){ //Now go through and do any actions as needed ui->label_progress->setText(tr("Opening Archive...")); if(action==1){ - qDebug() << "blah"; + //qDebug() << "blah"; connect(BACKEND, SIGNAL(FileLoaded()), this, SLOT(autoextractFiles()) ); connect(BACKEND, SIGNAL(ExtractSuccessful()), delayClose, SLOT(start()) ); }else if(action==2){ aaFileList.clear(); for(int j=1; j Date: Wed, 1 Nov 2017 15:13:52 -0400 Subject: Rework quite a bit of the lumina-fileinfo backend. Still not quite finished yet, but it is already much more stable/reliable. Just need to add new features. --- src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 327 +++---- src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 22 +- src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui | 1053 +++++++++++----------- src-qt5/desktop-utils/lumina-fileinfo/main.cpp | 17 +- 4 files changed, 747 insertions(+), 672 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index 0247e011..a990fc29 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -15,13 +15,18 @@ #include #include -MainUI::MainUI() : QDialog(), ui(new Ui::MainUI){ +MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ ui->setupUi(this); //load the designer form canwrite = false; terminate_thread = false; INFO = new LFileInfo(); UpdateIcons(); //Set all the icons in the dialog SetupConnections(); + + //Disable buttons that are not working yet + ui->actionOpen_File->setVisible(false); + ui->actionOpen_Directory->setVisible(false); + ui->menuSave_As->setEnabled(false); } MainUI::~MainUI(){ @@ -37,123 +42,12 @@ void MainUI::LoadFile(QString path, QString type){ //Do the first file information tab qDebug() << "Load File:" << path << type; INFO = new LFileInfo(path); - if(INFO->exists()){ canwrite = INFO->isWritable(); } - else if(!INFO->filePath().isEmpty()){ - //See if the containing directory can be written - //QFileInfo chk(INFO->absolutePath()); - canwrite = (INFO->isDir() && INFO->isWritable()); - }else{ - canwrite = true; //no associated file yet - } - if(!INFO->exists() && !type.isEmpty()){ - //Set the proper type flag on the shortcut - if(type=="APP"){ INFO->XDG()->type = XDGDesktop::APP; } - else if(type=="LINK"){ INFO->XDG()->type = XDGDesktop::LINK; } - } //First load the general file information if(!INFO->filePath().isEmpty()){ - ui->label_file_name->setText( INFO->fileName() ); - ui->label_file_mimetype->setText( INFO->mimetype() ); - if(!INFO->isDir()){ ui->label_file_size->setText( LUtils::BytesToDisplaySize( INFO->size() ) ); } - else { - ui->label_file_size->setText(tr("---Calculating---")); - QtConcurrent::run(this, &MainUI::GetDirSize, INFO->absoluteFilePath()); - } - ui->label_file_owner->setText(INFO->owner()); - ui->label_file_group->setText(INFO->group()); - ui->label_file_created->setText( INFO->created().toString(Qt::SystemLocaleLongDate) ); - ui->label_file_modified->setText( INFO->lastModified().toString(Qt::SystemLocaleLongDate) ); - //Get the file permissions - QString perms; - if(INFO->isReadable() && INFO->isWritable()){ perms = tr("Read/Write"); } - else if(INFO->isReadable()){ perms = tr("Read Only"); } - else if(INFO->isWritable()){ perms = tr("Write Only"); } - else{ perms = tr("No Access"); } - ui->label_file_perms->setText(perms); - //Now the special "type" for the file - QString ftype; - if(INFO->suffix().toLower()=="desktop"){ ftype = tr("XDG Shortcut"); } - else if(INFO->isDir()){ ftype = tr("Directory"); } - else if(INFO->isExecutable()){ ftype = tr("Binary"); } - else{ ftype = INFO->suffix().toUpper(); } - if(INFO->isHidden()){ ftype = QString(tr("Hidden %1")).arg(type); } - ui->label_file_type->setText(ftype); - - //Now load the icon for the file - if(INFO->isImage()){ - QPixmap pix(INFO->absoluteFilePath()); - ui->label_file_icon->setPixmap(pix.scaledToHeight(64)); - ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); - }else if(INFO->isVideo()){ - ui->label_file_icon->hide(); - LVideoLabel *mediaLabel = new LVideoLabel(INFO->absoluteFilePath(), true, ui->tab_file); - mediaLabel->setFixedSize(64,64); - ui->formLayout->replaceWidget(ui->label_file_icon, mediaLabel); - }else{ - ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); - } - //Now verify the tab is available in the widget - //qDebug() << "Check tab widget"; - if(ui->tabWidget->indexOf(ui->tab_file)<0){ - //qDebug() << "Add File Info Tab"; - ui->tabWidget->addTab(ui->tab_file, tr("File Information")); - } - //qDebug() << "Done with Tab Check"; + SyncFileInfo(); }else{ - if(ui->tabWidget->indexOf(ui->tab_file)>=0){ - ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_file) ); - } + SetupNewFile(); } - - //Now load the special XDG desktop info - qDebug() << "Check XDG Info:" << type; - //qDebug() << INFO->isDesktopFile() << type; - if(INFO->isDesktopFile() || !type.isEmpty()){ - - if(INFO->XDG()->type == XDGDesktop::APP){ - ui->line_xdg_command->setText(INFO->XDG()->exec); - ui->line_xdg_wdir->setText(INFO->XDG()->path); - ui->check_xdg_useTerminal->setChecked( INFO->XDG()->useTerminal ); - ui->check_xdg_startupNotify->setChecked( INFO->XDG()->startupNotify ); - }else if(INFO->XDG()->type==XDGDesktop::LINK){ - //Hide the options that are unavailable for links - //Command line (exec) - ui->line_xdg_command->setVisible(false); - ui->tool_xdg_getCommand->setVisible(false); - ui->lblCommand->setVisible(false); - //Options - ui->lblOptions->setVisible(false); - ui->check_xdg_useTerminal->setVisible(false); - ui->check_xdg_startupNotify->setVisible(false); - //Now load the variables for this type of shortcut - ui->lblWorkingDir->setText(tr("URL:")); - ui->line_xdg_wdir->setText( INFO->XDG()->url ); - ui->tool_xdg_getDir->setVisible(false); //the dir selection button - - } - ui->line_xdg_name->setText(INFO->XDG()->name); - ui->line_xdg_comment->setText(INFO->XDG()->comment); - ui->push_xdg_getIcon->setWhatsThis( INFO->XDG()->icon ); - ReloadAppIcon(); - ui->push_save->setVisible(true); - ui->push_save->setEnabled(false); - //Now ensure the xdg tab exists in the widget - if(ui->tabWidget->indexOf(ui->tab_deskedit)<0){ - qDebug() << "Adding the deskedit tab"; - ui->tabWidget->addTab(ui->tab_deskedit, tr("Edit Shortcut")); - } - }else{ - xdgvaluechanged(); //just do the disables here - //Also remove the xdg tab - if(ui->tabWidget->indexOf(ui->tab_deskedit) >= 0){ - qDebug() << "Removing the deskedit tab"; - ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_deskedit) ); - } - } - //Setup the tab - if(type.isEmpty()){ ui->tabWidget->setCurrentIndex(0); } - else if(ui->tabWidget->count()>1){ ui->tabWidget->setCurrentIndex(1); } - qDebug() << "Done Loading File"; } void MainUI::UpdateIcons(){ @@ -221,8 +115,160 @@ void MainUI::GetDirSize(const QString dirname) const { emit folder_size_changed(filesize, file_number, dir_number, true); } +void MainUI::SyncFileInfo(){ + qDebug() << "Sync File Info"; + if(INFO->filePath().isEmpty()){ return; } + if(INFO->exists()){ canwrite = INFO->isWritable(); } + else{ + //See if the containing directory can be written + QFileInfo chk(INFO->absolutePath()); + canwrite = (chk.isDir() && chk.isWritable()); + } + ui->label_file_name->setText( INFO->fileName() ); + ui->label_file_mimetype->setText( INFO->mimetype() ); + if(!INFO->isDir()){ ui->label_file_size->setText( LUtils::BytesToDisplaySize( INFO->size() ) ); } + else { + ui->label_file_size->setText(tr("---Calculating---")); + QtConcurrent::run(this, &MainUI::GetDirSize, INFO->absoluteFilePath()); + } + ui->label_file_owner->setText(INFO->owner()); + ui->label_file_group->setText(INFO->group()); + ui->label_file_created->setText( INFO->created().toString(Qt::SystemLocaleLongDate) ); + ui->label_file_modified->setText( INFO->lastModified().toString(Qt::SystemLocaleLongDate) ); + //Get the file permissions + QString perms; + if(INFO->isReadable() && INFO->isWritable()){ perms = tr("Read/Write"); } + else if(INFO->isReadable()){ perms = tr("Read Only"); } + else if(INFO->isWritable()){ perms = tr("Write Only"); } + else{ perms = tr("No Access"); } + ui->label_file_perms->setText(perms); + //Now the special "type" for the file + QString ftype; + if(INFO->suffix().toLower()=="desktop"){ ftype = tr("XDG Shortcut"); } + else if(INFO->isDir()){ ftype = tr("Directory"); } + else if(INFO->isExecutable()){ ftype = tr("Binary"); } + else{ ftype = INFO->suffix().toUpper(); } + if(INFO->isHidden()){ ftype = QString(tr("Hidden %1")).arg(ftype); } + ui->label_file_type->setText(ftype); + + //Now load the icon for the file + if(INFO->isImage()){ + QPixmap pix(INFO->absoluteFilePath()); + ui->label_file_icon->setPixmap(pix.scaledToHeight(64)); + ui->label_file_size->setText( ui->label_file_size->text()+" ("+QString::number(pix.width())+" x "+QString::number(pix.height())+" px)" ); + }else if(INFO->isVideo()){ + ui->label_file_icon->hide(); + LVideoLabel *mediaLabel = new LVideoLabel(INFO->absoluteFilePath(), true, ui->tab_file); + mediaLabel->setFixedSize(64,64); + ui->formLayout->replaceWidget(ui->label_file_icon, mediaLabel); + }else{ + ui->label_file_icon->setPixmap( LXDG::findIcon( INFO->iconfile(), "unknown").pixmap(QSize(64,64)) ); + } + + //qDebug() << "Check XDG Info:" + //qDebug() << INFO->isDesktopFile() << type; + syncXdgStruct(INFO->XDG()); + //Make sure the right tabs are available + if(ui->tabWidget->indexOf(ui->tab_file)<0){ + //qDebug() << "Add File Info Tab"; + ui->tabWidget->addTab(ui->tab_file, tr("File Information")); + } + if(!INFO->isDesktopFile()){ + if(ui->tabWidget->indexOf(ui->tab_deskedit)>=0){ + ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_deskedit) ); + } + } + ui->tabWidget->setCurrentIndex(ui->tabWidget->indexOf(ui->tab_file) ); +} + +void MainUI::SetupNewFile(){ + //qDebug() << "Setup New File"; + if(!INFO->filePath().isEmpty()){ + INFO = new LFileInfo(); + } + terminate_thread = true; //just in case + canwrite = true; //can always write a new file + syncXdgStruct(INFO->XDG()); + //Make sure the right tabs are enabled + if(ui->tabWidget->indexOf(ui->tab_file)>=0){ + ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_file) ); + } + if(ui->tabWidget->indexOf(ui->tab_deskedit)<0){ + //qDebug() << "Adding the deskedit tab"; + ui->tabWidget->addTab(ui->tab_deskedit, tr("XDG Shortcut")); + } + ui->tabWidget->setCurrentIndex(ui->tabWidget->indexOf(ui->tab_deskedit) ); +} + +void MainUI::syncXdgStruct(XDGDesktop *XDG){ + bool cleanup = false; + if(XDG==0){ XDG = new XDGDesktop(); cleanup = true;} //make sure nothing crashes + if(XDG->type == XDGDesktop::APP){ + ui->line_xdg_command->setText(XDG->exec); + ui->line_xdg_wdir->setText(XDG->path); + ui->check_xdg_useTerminal->setChecked( XDG->useTerminal ); + ui->check_xdg_startupNotify->setChecked( XDG->startupNotify ); + }else if(XDG->type==XDGDesktop::LINK){ + //Hide the options that are unavailable for links + //Command line (exec) + ui->line_xdg_command->setVisible(false); + ui->tool_xdg_getCommand->setVisible(false); + ui->lblCommand->setVisible(false); + //Options + ui->lblOptions->setVisible(false); + ui->check_xdg_useTerminal->setVisible(false); + ui->check_xdg_startupNotify->setVisible(false); + //Now load the variables for this type of shortcut + ui->lblWorkingDir->setText(tr("URL:")); + ui->line_xdg_wdir->setText( XDG->url ); + ui->tool_xdg_getDir->setVisible(false); //the dir selection button + } + ui->line_xdg_name->setText(XDG->name); + ui->line_xdg_comment->setText(XDG->comment); + ui->line_xdg_icon->setText( XDG->icon ); + ReloadAppIcon(); + ui->actionSave_Shortcut->setVisible(true); + ui->actionSave_Shortcut->setEnabled(false); + if(cleanup){ delete XDG; } +} + +bool MainUI::saveFile(QString path){ + //qDebug() << "Request save file:" << path; + XDGDesktop *XDG = INFO->XDG(); + if(XDG==0){ XDG = new XDGDesktop(); } + if(XDG->type == XDGDesktop::BAD){ XDG->type = XDGDesktop::APP; } + //Update the file path in the data structure + XDG->filePath = path; + //Now change the structure + XDG->name = ui->line_xdg_name->text(); + XDG->genericName = ui->line_xdg_name->text().toLower(); + XDG->comment = ui->line_xdg_comment->text(); + XDG->icon = ui->line_xdg_icon->text(); + //Now do the type-specific fields + if(XDG->type == XDGDesktop::APP){ + XDG->exec = ui->line_xdg_command->text(); + XDG->tryexec = ui->line_xdg_command->text().section(" ",0,0); //use the first word/binary for the existance check + XDG->path = ui->line_xdg_wdir->text(); //working dir/path + XDG->useTerminal = ui->check_xdg_useTerminal->isChecked(); + XDG->startupNotify = ui->check_xdg_startupNotify->isChecked(); + }else if(XDG->type==XDGDesktop::LINK){ + XDG->url = ui->line_xdg_wdir->text(); //we re-used this field + } + //Clear any info which this utility does not support at the moment + XDG->actionList.clear(); + XDG->actions.clear(); + //Now save the structure to file + //qDebug() << "Saving File:" << XDG->filePath; + return XDG->saveDesktopFile(true); //Try to merge the file/structure as necessary +} + // Initialization procedures void MainUI::SetupConnections(){ + connect(ui->actionQuit, SIGNAL(triggered()), this, SLOT(closeApplication()) ); + connect(ui->actionSave_Shortcut, SIGNAL(triggered()), this, SLOT(save_clicked()) ); + connect(ui->actionNew_Shortcut, SIGNAL(triggered()), this, SLOT(SetupNewFile()) ); + connect(ui->actionOpen_File, SIGNAL(triggered()), this, SLOT(open_file()) ); + connect(ui->actionOpen_Directory, SIGNAL(triggered()), this, SLOT(open_dir()) ); connect(ui->line_xdg_command, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); connect(ui->line_xdg_comment, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); connect(ui->line_xdg_icon, SIGNAL(textChanged(QString)), this, SLOT(ReloadAppIcon()) ); @@ -235,55 +281,34 @@ void MainUI::SetupConnections(){ } //UI Buttons -void MainUI::on_push_close_clicked(){ +void MainUI::closeApplication(){ terminate_thread = true; - if(ui->push_save->isEnabled()){ + if(ui->actionSave_Shortcut->isEnabled()){ //Still have unsaved changes //TO-DO - prompt for whether to save the changes } this->close(); } -void MainUI::on_push_save_clicked(){ +void MainUI::save_clicked(){ //Save all the xdg values into the structure - if( (!INFO->isDesktopFile() && !INFO->filePath().isEmpty()) || !canwrite){ return; } - if(INFO->filePath().isEmpty()){ + QString filePath = INFO->filePath(); + if( !filePath.isEmpty() && !INFO->isDesktopFile() ){ return; } + if(filePath.isEmpty() || !canwrite){ //Need to prompt for where to save the file and what to call it QString appdir = QString(getenv("XDG_DATA_HOME"))+"/applications/"; if(!QFile::exists(appdir)){ QDir dir; dir.mkpath(appdir); } - QString filePath = QFileDialog::getSaveFileName(this, tr("Save Application File"), appdir, tr("Application Registrations (*.desktop)") ); + filePath = QFileDialog::getSaveFileName(this, tr("Save Application File"), appdir, tr("XDG Shortcuts (*.desktop)") ); if(filePath.isEmpty()){ return; } if(!filePath.endsWith(".desktop")){ filePath.append(".desktop"); } - //Update the file paths in the data structure - INFO->setFile(filePath); - INFO->XDG()->filePath = filePath; } - XDGDesktop *XDG = INFO->XDG(); - //Now change the structure - XDG->name = ui->line_xdg_name->text(); - XDG->genericName = ui->line_xdg_name->text().toLower(); - XDG->comment = ui->line_xdg_comment->text(); - XDG->icon = ui->line_xdg_icon->text(); - //Now do the type-specific fields - if(XDG->type == XDGDesktop::APP){ - XDG->exec = ui->line_xdg_command->text(); - XDG->tryexec = ui->line_xdg_command->text().section(" ",0,0); //use the first word/binary for the existance check - XDG->path = ui->line_xdg_wdir->text(); //working dir/path - XDG->useTerminal = ui->check_xdg_useTerminal->isChecked(); - XDG->startupNotify = ui->check_xdg_startupNotify->isChecked(); - }else if(XDG->type==XDGDesktop::LINK){ - XDG->url = ui->line_xdg_wdir->text(); //we re-used this field - } - //Clear any info which this utility does not support at the moment - XDG->actionList.clear(); - XDG->actions.clear(); - //Now save the structure to file - bool saved = XDG->saveDesktopFile(true); //Try to merge the file/structure as necessary - qDebug() << "File Saved:" << saved; - ui->push_save->setEnabled( !saved ); + //qDebug() << " -Try Saving File:" << filePath; + bool saved = saveFile(filePath); + //qDebug() << "File Saved:" << saved; + ui->actionSave_Shortcut->setEnabled( !saved ); if(saved){ //Re-load the file info - LoadFile(INFO->absoluteFilePath()); + LoadFile(filePath); } } @@ -331,14 +356,14 @@ void MainUI::on_push_xdg_getIcon_clicked(){ void MainUI::xdgvaluechanged(){ //qDebug() << "xdgvaluechanged"; if( INFO->isDesktopFile() || INFO->filePath().isEmpty() ){ - ui->push_save->setVisible(true); + ui->actionSave_Shortcut->setVisible(true); //Compare the current UI values to the file values - ui->push_save->setEnabled(canwrite); //assume changed at this point + ui->actionSave_Shortcut->setEnabled(canwrite); //assume changed at this point // TO-DO }else{ - ui->push_save->setVisible(false); - ui->push_save->setEnabled(false); + ui->actionSave_Shortcut->setVisible(false); + ui->actionSave_Shortcut->setEnabled(false); } } diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index 089dbe6c..f45e15d7 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -13,17 +13,19 @@ #ifndef _LUMINA_FILE_INFO_MAIN_UI_H #define _LUMINA_FILE_INFO_MAIN_UI_H -#include +#include #include -#include #include #include #include -namespace Ui{ class MainUI; +#include + +namespace Ui{ + class MainUI; }; -class MainUI : public QDialog{ +class MainUI : public QMainWindow{ Q_OBJECT public: MainUI(); @@ -34,6 +36,7 @@ public: public slots: void UpdateIcons(); void ReloadAppIcon(); + private: Ui::MainUI *ui; LFileInfo *INFO; @@ -46,16 +49,23 @@ private: bool terminate_thread; //flag for terminating the GetDirSize task void GetDirSize(const QString dirname) const; //function to get folder size + void SyncFileInfo(); + + void syncXdgStruct(XDGDesktop*); + + bool saveFile(QString path); + signals: void folder_size_changed(quint64 size, quint64 files, quint64 folders, bool finished) const; //Signal for updating the folder size asynchronously private slots: + void SetupNewFile(); //Initialization functions void SetupConnections(); //UI Buttons - void on_push_close_clicked(); - void on_push_save_clicked(); + void closeApplication(); + void save_clicked(); void getXdgCommand(QString prev = ""); //void on_tool_xdg_getCommand_clicked(QString prev = ""); void on_tool_xdg_getDir_clicked(); diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui index d3b88b28..f8414026 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui @@ -1,522 +1,571 @@ MainUI - + 0 0 - 535 - 580 + 800 + 658 - - - 0 - 0 - - File Information - + - - - - - 1 - - - - File Information - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - icon - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - - - - - Owner: - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Group: - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Permissions: - - - - - - - Qt::Horizontal - - - - - - - Created: - - - - - - - Note: The time a file was created might be more recent than the time modified if the file permissions were changed recently. - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Last Modified: - - - - - - - Type: - - - - - - - MimeType: - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - File Size: - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - - Edit Shortcut - - - - 2 - - - 4 - - - 4 - - - 4 - - - 4 - - - - - - - Working Dir: - - - - - - - Use startup notification - - - - - - - true - - - - - - - Icon: - - - - - - - Command: - - - - - - - Comment: - - - - - - - - - - Run in terminal - - - - - - - Name: - - - - - - - Options - - - - - - - - - - - - - - 0 - 0 - - - - - 16777215 - 42 - - - - - - - - - - - - - - true - - - - 0 - 0 - - - - - 16777215 - 42 - - - - - - - - - - - - - - - - - 0 - 0 - - - - - 64 - 64 - - - - - 64 - 64 - - - - QFrame::StyledPanel - - - - - - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 20000 - 42 - - - - - 2 - 2 - - - - - 0 - 0 - - - - - - - - - - - 24 - 24 - - - - - - - - - - Qt::Horizontal - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Save - - - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextBesideIcon - + + + + + + 1 + + + + File Information + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + icon + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + + + + Owner: + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Group: + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Permissions: + + + + + + + Qt::Horizontal + + + + + + + Created: + + + + + + + Note: The time a file was created might be more recent than the time modified if the file permissions were changed recently. + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Last Modified: + + + + + + + Type: + + + + + + + MimeType: + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + File Size: + + + + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + - - - - - Close - - - - - - QToolButton::DelayedPopup - - - Qt::ToolButtonTextBesideIcon - + + + XDG Shortcut + + + + 2 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + + Working Dir: + + + + + + + Use startup notification + + + + + + + true + + + + + + + Icon: + + + + + + + Command: + + + + + + + Comment: + + + + + + + + + + Run in terminal + + + + + + + Name: + + + + + + + Options + + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 42 + + + + + + + + .. + + + + + + + true + + + + 0 + 0 + + + + + 16777215 + 42 + + + + + + + + .. + + + + + + + + + + 0 + 0 + + + + + 64 + 64 + + + + + 64 + 64 + + + + QFrame::StyledPanel + + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 20000 + 42 + + + + + 2 + 2 + + + + + 0 + 0 + + + + + + + + .. + + + + 24 + 24 + + + + + + + + + + Qt::Horizontal + + + + - - - - + + + + + + + + 0 + 0 + 800 + 39 + + + + + File + + + + Save As + + + + + + + + + + + + + + + + + + + + + + + + + + Open File + + + Ctrl+O + + + Qt::ApplicationShortcut + + + + + + + + Quit + + + Ctrl+Q + + + Qt::ApplicationShortcut + + + + + + + + Save Shortcut + + + Ctrl+S + + + Qt::ApplicationShortcut + + + + + + + + Local Shortcut + + + + + + + + Register Shortcut + + + + + + + + Open Directory + + + + + + + + New Shortcut + + - - - line_xdg_name - line_xdg_comment - line_xdg_command - line_xdg_wdir - check_xdg_startupNotify - check_xdg_useTerminal - tool_xdg_getCommand - tool_xdg_getDir - diff --git a/src-qt5/desktop-utils/lumina-fileinfo/main.cpp b/src-qt5/desktop-utils/lumina-fileinfo/main.cpp index 463f856a..ce62399d 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/main.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/main.cpp @@ -20,26 +20,17 @@ int main(int argc, char ** argv) QString flag = ""; for(int i=1; i Date: Thu, 2 Nov 2017 10:21:06 -0400 Subject: Finish up the large cleanup of lumina-fileinfo. --- src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp | 137 +++++++++++++++++++++-- src-qt5/desktop-utils/lumina-fileinfo/MainUI.h | 15 ++- src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui | 99 ++++++++++++++-- 3 files changed, 227 insertions(+), 24 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp index a990fc29..e64346ae 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.cpp @@ -24,9 +24,9 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ SetupConnections(); //Disable buttons that are not working yet - ui->actionOpen_File->setVisible(false); - ui->actionOpen_Directory->setVisible(false); - ui->menuSave_As->setEnabled(false); + //ui->actionOpen_File->setVisible(false); + //ui->actionOpen_Directory->setVisible(false); + //ui->menuSave_As->setEnabled(false); } MainUI::~MainUI(){ @@ -67,6 +67,15 @@ void MainUI::ReloadAppIcon(){ //qDebug() << "Done with app icon"; } +void MainUI::stopDirSize(){ + if(sizeThread.isRunning()){ + terminate_thread = true; + sizeThread.waitForFinished(); + QApplication::processEvents(); //throw away any last signals waiting to be processed + } + terminate_thread = false; +} + void MainUI::GetDirSize(const QString dirname) const { const quint16 update_frequency = 2000; //For reducing the number of folder_size_changed calls quint64 filesize = 0; @@ -117,6 +126,7 @@ void MainUI::GetDirSize(const QString dirname) const { void MainUI::SyncFileInfo(){ qDebug() << "Sync File Info"; + stopDirSize(); if(INFO->filePath().isEmpty()){ return; } if(INFO->exists()){ canwrite = INFO->isWritable(); } else{ @@ -129,7 +139,7 @@ void MainUI::SyncFileInfo(){ if(!INFO->isDir()){ ui->label_file_size->setText( LUtils::BytesToDisplaySize( INFO->size() ) ); } else { ui->label_file_size->setText(tr("---Calculating---")); - QtConcurrent::run(this, &MainUI::GetDirSize, INFO->absoluteFilePath()); + sizeThread = QtConcurrent::run(this, &MainUI::GetDirSize, INFO->absoluteFilePath()); } ui->label_file_owner->setText(INFO->owner()); ui->label_file_group->setText(INFO->group()); @@ -171,12 +181,14 @@ void MainUI::SyncFileInfo(){ //Make sure the right tabs are available if(ui->tabWidget->indexOf(ui->tab_file)<0){ //qDebug() << "Add File Info Tab"; - ui->tabWidget->addTab(ui->tab_file, tr("File Information")); + ui->tabWidget->insertTab(0, ui->tab_file, tr("File Information")); } if(!INFO->isDesktopFile()){ if(ui->tabWidget->indexOf(ui->tab_deskedit)>=0){ ui->tabWidget->removeTab( ui->tabWidget->indexOf(ui->tab_deskedit) ); } + }else if(ui->tabWidget->indexOf(ui->tab_deskedit)<0){ + ui->tabWidget->addTab( ui->tab_deskedit, tr("XDG Shortcut") ); } ui->tabWidget->setCurrentIndex(ui->tabWidget->indexOf(ui->tab_file) ); } @@ -186,7 +198,7 @@ void MainUI::SetupNewFile(){ if(!INFO->filePath().isEmpty()){ INFO = new LFileInfo(); } - terminate_thread = true; //just in case + stopDirSize(); canwrite = true; //can always write a new file syncXdgStruct(INFO->XDG()); //Make sure the right tabs are enabled @@ -230,6 +242,7 @@ void MainUI::syncXdgStruct(XDGDesktop *XDG){ ui->actionSave_Shortcut->setVisible(true); ui->actionSave_Shortcut->setEnabled(false); if(cleanup){ delete XDG; } + checkXDGValidity(); } bool MainUI::saveFile(QString path){ @@ -262,13 +275,47 @@ bool MainUI::saveFile(QString path){ return XDG->saveDesktopFile(true); //Try to merge the file/structure as necessary } +QString MainUI::findOpenDirFile(bool isdir){ + static QList urls; + if(urls.isEmpty()){ + urls << QUrl::fromLocalFile("/"); + QStringList dirs = QString(getenv("XDG_DATA_DIRS")).split(":"); + for(int i=0; iactionQuit, SIGNAL(triggered()), this, SLOT(closeApplication()) ); connect(ui->actionSave_Shortcut, SIGNAL(triggered()), this, SLOT(save_clicked()) ); + connect(ui->actionLocal_Shortcut, SIGNAL(triggered()), this, SLOT(save_as_local_clicked()) ); + connect(ui->actionRegister_Shortcut, SIGNAL(triggered()), this, SLOT(save_as_register_clicked()) ); connect(ui->actionNew_Shortcut, SIGNAL(triggered()), this, SLOT(SetupNewFile()) ); - connect(ui->actionOpen_File, SIGNAL(triggered()), this, SLOT(open_file()) ); - connect(ui->actionOpen_Directory, SIGNAL(triggered()), this, SLOT(open_dir()) ); + connect(ui->actionOpen_File, SIGNAL(triggered()), this, SLOT(open_file_clicked()) ); + connect(ui->actionOpen_Directory, SIGNAL(triggered()), this, SLOT(open_dir_clicked()) ); connect(ui->line_xdg_command, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); connect(ui->line_xdg_comment, SIGNAL(editingFinished()), this, SLOT(xdgvaluechanged()) ); connect(ui->line_xdg_icon, SIGNAL(textChanged(QString)), this, SLOT(ReloadAppIcon()) ); @@ -312,6 +359,50 @@ void MainUI::save_clicked(){ } } +void MainUI::save_as_local_clicked(){ + QString filePath = QFileDialog::getSaveFileName(this, tr("Save Application File"), QDir::homePath(), tr("XDG Shortcuts (*.desktop)") ); + if(filePath.isEmpty()){ return; } + if(!filePath.endsWith(".desktop")){ filePath.append(".desktop"); } + + //qDebug() << " -Try Saving File:" << filePath; + bool saved = saveFile(filePath); + //qDebug() << "File Saved:" << saved; + ui->actionSave_Shortcut->setEnabled( !saved ); + if(saved){ + //Re-load the file info + LoadFile(filePath); + } +} + +void MainUI::save_as_register_clicked(){ + QString appdir = QString(getenv("XDG_DATA_HOME"))+"/applications/"; + if(!QFile::exists(appdir)){ QDir dir; dir.mkpath(appdir); } + QString filePath = QFileDialog::getSaveFileName(this, tr("Save Application File"), appdir, tr("XDG Shortcuts (*.desktop)") ); + if(filePath.isEmpty()){ return; } + if(!filePath.endsWith(".desktop")){ filePath.append(".desktop"); } + + //qDebug() << " -Try Saving File:" << filePath; + bool saved = saveFile(filePath); + //qDebug() << "File Saved:" << saved; + ui->actionSave_Shortcut->setEnabled( !saved ); + if(saved){ + //Re-load the file info + LoadFile(filePath); + } +} + +void MainUI::open_dir_clicked(){ + QString path = findOpenDirFile(true); //directory only + if(path.isEmpty()){ return; } + LoadFile(path, ""); +} + +void MainUI::open_file_clicked(){ + QString path = findOpenDirFile(false); //files only + if(path.isEmpty()){ return; } + LoadFile(path, ""); +} + void MainUI::getXdgCommand(QString prev){ //Find a binary to run QString dir = prev; //start with the previous attempt (if there was one) @@ -353,16 +444,38 @@ void MainUI::on_push_xdg_getIcon_clicked(){ } //XDG Value Changed +bool MainUI::checkXDGValidity(){ + XDGDesktop tmp; + tmp.type = XDGDesktop::APP; //make this adjustable later (GUI radio buttons?) + tmp.name = ui->line_xdg_name->text(); + tmp.genericName = ui->line_xdg_name->text().toLower(); + tmp.comment = ui->line_xdg_comment->text(); + tmp.icon = ui->line_xdg_icon->text(); + //Now do the type-specific fields + if(tmp.type == XDGDesktop::APP){ + tmp.exec = ui->line_xdg_command->text(); + tmp.tryexec = ui->line_xdg_command->text().section(" ",0,0); //use the first word/binary for the existance check + tmp.path = ui->line_xdg_wdir->text(); //working dir/path + tmp.useTerminal = ui->check_xdg_useTerminal->isChecked(); + tmp.startupNotify = ui->check_xdg_startupNotify->isChecked(); + }else if(tmp.type==XDGDesktop::LINK){ + tmp.url = ui->line_xdg_wdir->text(); //we re-used this field + } + bool valid = tmp.isValid(); + ui->label_xdg_statusicon->setPixmap( LXDG::findIcon( valid ? "dialog-ok" : "dialog-cancel", "").pixmap(32,32) ); + ui->label_xdg_status->setText( valid ? tr("Valid Settings") : tr("Invalid Settings") ); + return tmp.isValid(); +} + void MainUI::xdgvaluechanged(){ //qDebug() << "xdgvaluechanged"; if( INFO->isDesktopFile() || INFO->filePath().isEmpty() ){ - ui->actionSave_Shortcut->setVisible(true); + bool valid = checkXDGValidity(); //Compare the current UI values to the file values - ui->actionSave_Shortcut->setEnabled(canwrite); //assume changed at this point - // TO-DO + ui->menuSave_As->setEnabled(valid); + ui->actionSave_Shortcut->setEnabled(canwrite && valid); //assume changed at this point }else{ - ui->actionSave_Shortcut->setVisible(false); ui->actionSave_Shortcut->setEnabled(false); } } diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h index f45e15d7..d7b17207 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.h @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -44,9 +45,12 @@ private: QMediaPlayer *player; bool flag; QElapsedTimer timer; + QFuture sizeThread; bool canwrite; bool terminate_thread; //flag for terminating the GetDirSize task + void stopDirSize(); + void GetDirSize(const QString dirname) const; //function to get folder size void SyncFileInfo(); @@ -54,6 +58,7 @@ private: void syncXdgStruct(XDGDesktop*); bool saveFile(QString path); + QString findOpenDirFile(bool isdir = false); signals: void folder_size_changed(quint64 size, quint64 files, quint64 folders, bool finished) const; //Signal for updating the folder size asynchronously @@ -66,16 +71,20 @@ private slots: //UI Buttons void closeApplication(); void save_clicked(); + void save_as_local_clicked(); + void save_as_register_clicked(); + void open_dir_clicked(); + void open_file_clicked(); void getXdgCommand(QString prev = ""); - //void on_tool_xdg_getCommand_clicked(QString prev = ""); void on_tool_xdg_getDir_clicked(); void on_push_xdg_getIcon_clicked(); //XDG Value Changed + bool checkXDGValidity(); void xdgvaluechanged(); - //Folder size - void refresh_folder_size(quint64 size, quint64 files, quint64 folders, bool finished); //Slot for updating the folder size asynchronously + //Folder size + void refresh_folder_size(quint64 size, quint64 files, quint64 folders, bool finished); //Slot for updating the folder size asynchronously }; #endif diff --git a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui index f8414026..217c1a10 100644 --- a/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-fileinfo/MainUI.ui @@ -14,7 +14,8 @@ File Information - + + .. @@ -442,6 +443,78 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + + + + + + 0 + 0 + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + + true + + + + + + + + + @@ -473,7 +546,8 @@ Save As - + + .. @@ -493,7 +567,8 @@ - + + .. Open File @@ -507,7 +582,8 @@ - + + .. Quit @@ -521,7 +597,8 @@ - + + .. Save Shortcut @@ -535,7 +612,8 @@ - + + .. Local Shortcut @@ -543,7 +621,8 @@ - + + .. Register Shortcut @@ -551,7 +630,8 @@ - + + .. Open Directory @@ -559,7 +639,8 @@ - + + .. New Shortcut -- cgit From e0c84c93d82e19b0aad62e65458fa21b1ae639f2 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Thu, 2 Nov 2017 10:45:01 -0400 Subject: Add parsing of the "/media" directory on FreeBSD to the External Device Paths LOS function. --- src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp index b9346565..a1c82fc9 100644 --- a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp +++ b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp @@ -27,12 +27,12 @@ QString LOS::SysPrefix(){ return "/usr/"; } //Prefix for system QString LOS::ControlPanelShortcut(){ return "/usr/local/share/applications/pccontrol.desktop"; } //system control panel QString LOS::AppStoreShortcut(){ return "/usr/local/share/applications/appcafe.desktop"; } //graphical app/pkg manager //OS-specific RSS feeds (Format: QStringList[ :::: ]; ) -QStringList LOS::RSSFeeds(){ +QStringList LOS::RSSFeeds(){ QStringList feeds; feeds << "FreeBSD News Feed::::https://www.freebsd.org/news/rss.xml"; feeds << "TrueOS News Feed::::http://www.trueos.org/?feed=rss2"; return feeds; - } + } // ==== ExternalDevicePaths() ==== QStringList LOS::ExternalDevicePaths(){ @@ -59,6 +59,23 @@ QStringList LOS::ExternalDevicePaths(){ i--; } } + //Also add info about anything in the "/media" directory + QDir media("/media"); + QFileInfoList list = media.entryInfoList(QDir::NoDotAndDotDot, QDir::Type | QDir::Name); + for(int i=0; i Date: Thu, 2 Nov 2017 11:07:43 -0400 Subject: Finish up the /media parsing for LuminaOS-FreeBSD --- src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp index a1c82fc9..6ff144d5 100644 --- a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp +++ b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp @@ -61,8 +61,10 @@ QStringList LOS::ExternalDevicePaths(){ } //Also add info about anything in the "/media" directory QDir media("/media"); - QFileInfoList list = media.entryInfoList(QDir::NoDotAndDotDot, QDir::Type | QDir::Name); + QFileInfoList list = media.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::Type | QDir::Name); + //qDebug() << "Media files found:" << list.length(); for(int i=0; i Date: Thu, 2 Nov 2017 11:24:14 -0400 Subject: A bit more cleanup on the external device reporting/usage. --- src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp | 4 ++-- src-qt5/desktop-utils/lumina-fm/MainUI.cpp | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp index 6ff144d5..29a58ec9 100644 --- a/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp +++ b/src-qt5/core/libLumina/LuminaOS-FreeBSD.cpp @@ -66,7 +66,7 @@ QStringList LOS::ExternalDevicePaths(){ for(int i=0; i:::::::: (6/24/14 - version 0.4.0 ) // = [USB, HDRIVE, SDCARD, DVD, LVM, UNKNOWN] - qDebug() << "Externally-mounted devices:" << devs; + //qDebug() << "Externally-mounted devices:" << devs; //Now add them to the menu appropriately for(int i=0; i @@ -29,307 +29,307 @@ Archive: - + Archiv: File - + Datei Edit - + Bearbeiten Burn to Disk - + Auf Disc brennen &Open Archive - + Archiv &öffnen Open archive - + Archiv öffnen &New Archive - + &Neues Archiv New archive - + Neues Archiv &Quit - + &Beenden Add File(s) - + Datei(en) hinzufügen Add files to archive - + Dateien zum Archiv hinzufügen Remove File(s) - + Datei(en) entfernen Remove selection from archive - + Auswahl aus Archiv entfernen Extract All - + Alles extrahieren Extract archive into a directory - + Archiv in ein Verzeichnis extrahieren Add Directory - + Verzeichnis hinzufügen Add directory to archive - + Verzeichnis zum Archiv hinzufügen Extract Selection - + Auswahl extrahieren Extract Selected Items - + Ausgewählte Elemente extrahieren USB Image - + USB-Abbild Copy an IMG to a USB device (may require admin permission) - + IMG auf ein USB-Gerät kopieren (eventuell Administratorberechtigung erforderlich) Archive Manager - + Archivverwaltung Admin Mode - + Administratormodus CTRL+N - + STRG+N CTRL+O - + STRG+Ö CTRL+Q - + STRG+B CTRL+E - + STRG+E MimeType - + MimeType Size - + Größe Opening Archive... - + Archiv wird geöffnet... All Types %1 - + Alle Typen %1 Uncompressed Archive (*.tar) - + Unkomprimiertes Archiv (*.tar) GZip Compressed Archive (*.tar.gz *.tgz) - + GZip-komprimiertes Archiv (*.tar.gz *.tgz) BZip Compressed Archive (*.tar.bz *.tbz) - + BZip-komprimiertes Archiv (*.tar.bz *.tbz) BZip2 Compressed Archive (*.tar.bz2 *.tbz2) - + BZip2-komprimiertes Archiv (*.tar.bz2 *.tbz2) LMZA Compressed Archive (*.tar.lzma *.tlz) - + LMZA-komprimiertes Archiv (*.tar.lzma *.tlz) XZ Compressed Archive (*.tar.xz *.txz) - + XZ-komprimiertes Archiv (*.tar.xz *.txz) CPIO Archive (*.cpio) - + CPIO-Archiv (*.cpio) PAX Archive (*.pax) - + PAX-Archiv (*.pax) AR Archive (*.ar) - + AR-Archiv (*.ar) SHAR Archive (*.shar) - + SHAR-Archiv (*.shar) Zip Archive (*.zip) - + Zip-Archiv (*.zip) 7-Zip Archive (*.7z) - + 7-Zip-Archiv (*.7z) All Known Types %1 - + Alle bekannten Typen %1 READ-ONLY: ISO image (*.iso *.img) - + NUR LESEN: ISO-Abbild (*.iso *.img) READ-ONLY: XAR archive (*.xar) - + NUR LESEN: XAR-Archiv (*.xar) READ-ONLY: Java archive (*.jar) - + NUR LESEN: Java-Archiv (*.jar) READ-ONLY: RedHat Package (*.rpm) - + NUR LESEN: RedHat-Paket (*.rpm) Show All Files (*) - + Alle Dateien anzeigen (*) Create Archive - + Archiv erstellen Error - + Fehler Could not overwrite file: - + Datei konnte nicht überschrieben werden: Open Archive - + Archiv öffnen Add to Archive - + Zum Archiv hinzufügen Adding Items... - + Elemente werden hinzugefügt... Removing Items... - + Elemente werden entfernt... Extract Into Directory - + In Verzeichnis extrahieren @@ -337,12 +337,12 @@ Extracting... - + Extrahierungsvorgang... Link To: %1 - + Link auf: %1 @@ -350,67 +350,67 @@ Multimedia - + Multimedia Development - + Entwicklung Education - + Bildung Games - + Spiele Graphics - + Grafik Network - + Netzwerk Office - + Büro Science - + Wissenschaft Settings - + Einstellungen System - + System Utility - + Dienstprogramm Wine - + Wine Unsorted - + Unsortiert @@ -418,127 +418,127 @@ Burn IMG to device - + IMG auf Gerät brennen IMG File - + IMG-Datei Block Size - + Blockgröße USB Device - + USB-Gerät Refresh Device List - + Geräteliste aktualisieren Wipe all extra space on device (conv = sync) - + Sämtlichen zusätzlichen Speicherplatz auf Gerät löschen (conv = sync) Burning to USB: - + Auf USB brennen: Time Elapsed: - + Vergangene Zeit: Cancel - + Abbrechen Start - + Start Burn IMG to Device - + IMG auf Gerät brennen Admin Mode - + Administratormodus Kilobyte(s) - + Kilobyte(s) Megabyte(s) - + Megabyte(s) Gigabyte(s) - + Gigabyte(s) Cancel Image Burn? - + Brennen des Abbildes abbrechen? Do you wish to stop the current IMG burn process? - + Möchten Sie den laufenden IMG-Brennprozess stoppen? Warning: This will leave the USB device in an inconsistent state - + Warnung: Dies wird das USB-Gerät in einem inkonsistenten Zustand zurücklassen Administrator Permissions Needed - + Administratorberechtigungen erforderlich This operation requires administrator priviledges. - + Dieser Vorgang erfordert Administratorrechte. Would you like to enable these priviledges? - + Möchten Sie diese Rechte aktivieren? ERROR - + FEHLER The process could not be completed: - + Der Prozess konnte nicht abgeschlossen werden: SUCCESS - + ERFOLG The image was successfully burned to the USB device - + Das Abbild wurde erfolgreich auf das USB-Gerät gebrannt -- cgit From b4a0884a1377175f089c683c22bbf724d4db6824 Mon Sep 17 00:00:00 2001 From: Pavel Borecki Date: Thu, 21 Sep 2017 05:22:56 +0000 Subject: Translated using Weblate (Czech) Currently translated at 100.0% (101 of 101 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/cs/ --- .../lumina-archiver/i18n/l-archiver_cs.ts | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_cs.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_cs.ts index c2c5a26e..0e3d0da8 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_cs.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_cs.ts @@ -350,67 +350,67 @@ Multimedia - + Multimédia Development - + Vývoj Education - + Výuka Games - + Hry Graphics - + Grafika Network - + Sítě Office - + Kancelář Science - + Věda Settings - + Nastavení System - + Systém Utility - + Nástroje Wine - + Wine Unsorted - + Různé -- cgit From 48d34996f4a54b7fd521a3989cb031f6aa0bb332 Mon Sep 17 00:00:00 2001 From: Tommi Nieminen Date: Wed, 4 Oct 2017 18:29:58 +0000 Subject: Translated using Weblate (Finnish) Currently translated at 94.0% (95 of 101 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/fi/ --- .../desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts index 4525f584..8467eb99 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_fi.ts @@ -350,37 +350,37 @@ Multimedia - + Multimedia Development - + Kehitys Education - + Kasvatus Games - + Pelit Graphics - + Grafiikka Network - + Verkko Office - + Toimisto -- cgit From 35dec768b7fea282872454ce2e5f31cf24bc0339 Mon Sep 17 00:00:00 2001 From: Moo Date: Tue, 26 Sep 2017 09:10:24 +0000 Subject: Translated using Weblate (Lithuanian) Currently translated at 94.0% (95 of 101 strings) Translation: lumina/lumina-archiver Translate-URL: http://weblate.trueos.org/projects/lumina/lumina-archiver/lt/ --- .../lumina-archiver/i18n/l-archiver_lt.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts index 121263bb..d8faaae4 100644 --- a/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts +++ b/src-qt5/desktop-utils/lumina-archiver/i18n/l-archiver_lt.ts @@ -350,7 +350,7 @@ Multimedia - + Multimedija @@ -360,42 +360,42 @@ Education - + Švietimas Games - + Žaidimai Graphics - + Grafika Network - + Tinklas Office - + Raštinė Science - + Mokslas Settings - + Nustatymai System - + Sistema @@ -405,7 +405,7 @@ Wine - + Wine -- cgit From 6051df8adb6044ee53061174feca5ead91a3be13 Mon Sep 17 00:00:00 2001 From: ahto Date: Sat, 4 Nov 2017 23:10:25 +0200 Subject: modified: src-qt5/core/lumina-desktop/i18n/lumina-desktop_et.ts --- .../core/lumina-desktop/i18n/lumina-desktop_et.ts | 419 +++++++++++---------- 1 file changed, 210 insertions(+), 209 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop/i18n/lumina-desktop_et.ts b/src-qt5/core/lumina-desktop/i18n/lumina-desktop_et.ts index ef19e5a0..456d5aff 100644 --- a/src-qt5/core/lumina-desktop/i18n/lumina-desktop_et.ts +++ b/src-qt5/core/lumina-desktop/i18n/lumina-desktop_et.ts @@ -40,47 +40,47 @@ Launch %1 - Käivita %1 + Käivita %1 Open - Ava + Ava Open With - + Ava Kasutades View Properties - + Vaata Omadusi File Operations - + Failioperatsioonid Rename - + Nimeta Ümber Copy - Kopeeri + Kopeeri Cut - Lõika + Lõika Delete - Kustuta + Kustuta @@ -95,7 +95,7 @@ New Filename - + Uus Failinimi @@ -103,12 +103,12 @@ Desktop - Töölaud + Töölaud Manage Applications - + Halda Rakendusi @@ -196,47 +196,47 @@ Starting the Lumina Desktop... - + Lumina Töölaua käivitumine... Version %1 - + Versioon %1 This desktop is powered by coffee, coffee, and more coffee. - + Töölaua valmimist on toetanud kohvi, kohvi ja veel rohkem kohvi. Keep up with desktop news! - + Pea silm peal töölaua uudistel! There is a full handbook of information about the desktop available online. - + Võrgus on Töölaua kohta olemas täiemahuline käsiraamat (ingl.k) Want to change the interface? Everything is customizable in the desktop configuration! - + Soovid muuta kasutajaliidest? Kõik töölaua konfiguratsioonis on muudetav! Lumina can easily reproduce the interface from most other desktop environments. - + Lumina võimaldab kergesti taasluua kasutajaliideseid enamikest muudest töölauakeskkondadest This desktop is generously sponsored by iXsystems - + Selle töölaua valmimist on heldelt toetanud iXsystems I have never been hurt by what I have not said - + Mulle ei ole kunagi haiget teenud ütlemata jäänud asjad @@ -246,22 +246,22 @@ Everything has its beauty but not everyone sees it. - + Kõigel on oma ilu kuid mitte kõik ei oska seda näha Before God we are all equally wise - and equally foolish. - + Jumala ees oleme kõik võrdselt targad - ja võrdselt lollid. We cannot do everything at once, but we can do something at once. - + Me ei saa teha kõike ühekorraga, kuid me saame teha midagi kohe. One with the law is a majority. - + @@ -271,217 +271,218 @@ You can't know too much, but you can say too much. - + Sa ei saa kunagi teada liiga palju, kuid saad öelda. Duty is not collective; it is personal. - + Kohusetunne ei ole kollektiivne, see on isiklik Any society that would give up a little liberty to gain a little security will deserve neither and lose both. - + Ühiskond, mis annab ära veidikene vabadust et lisada veidikene turvalisust, ei vääri kumbagi ning kaotab mõlemad. Never trust a computer you can’t throw out a window. - + Ära kunagi usalda kompuutrit, mida ei ole võimalik aknast välja visata. Study the past if you would define the future. - + Tuleviku ennustamiseks õpi minevikku. The way to get started is to quit talking and begin doing. - + Meetod alustamiseks: lõpeta seletamine ja hakka tegema. Ask and it will be given to you; search, and you will find; knock and the door will be opened for you. - + Küsi, ja sulle antakse; Otsi, ning sa leiad; Koputa, ning uks avatakse sulle. Start where you are. Use what you have. Do what you can. - + Alusta, sealt kus sa oled. Kasuta, mis sul on. Tee, mis saad. A person who never made a mistake never tried anything new. - + Inimene, kes kunagi pole eksinud, ei ole kunagi proovinud teha midagi uut. It does not matter how slowly you go as long as you do not stop. - + Pole oluline kui aeglaselt sa kulged, kuni sa ei peatu. Do what you can, where you are, with what you have. - + Tee mis saad, kus parajasti oled, mis käepärast on. Remember no one can make you feel inferior without your consent. - + Pea meeles et mitte keegi ei saa sind panna tundma alaväärtuslikuna ilma su enda nõusolekuta It’s not the years in your life that count. It’s the life in your years. - + Olulised pole elatud aastad. Oluline on elada igas aastas. Either write something worth reading or do something worth writing. - + Kirjuta midagi väärt lugemist või tee midagi väärt kirjutamist. The only way to do great work is to love what you do. - + Ainus valem heaks tööks on armastada seda. Political correctness is tyranny with manners. - + Poliitkorrektsus on kommetega türannia. Only two things are infinite, the universe and human stupidity, and I'm not sure about the former. - + Ainult kaks asja on lõputud. Universum ja inimese lollus. Ma ei ole kusjuures esimeses kindel. + I find that the harder I work, the more luck I seem to have. - + Olen avastanud et mida rohkem ma tööd raban, seda rohkem õnne näib mul olevat. Do, or do not. There is no 'try'. - + Tee, või ära tee. Lihtsalt proovimine ei ole variant. A mathematician is a device for turning coffee into theorems. - + Matemaatik on seade, mis muudab kohvi teoreemideks. Good people do not need laws to tell them to act responsibly, while bad people will find a way around the laws. - + Head inimesed ei vaja seadusi käitumaks vastutustundlikult, sellal kui halvad inimesed leiavad tee seadustest möödahiilimiseks. Black holes are where God divided by zero. - + Mustad augud Universumis on kohad, kus Jumal jagas nulliga. It's kind of fun to do the impossible. - + On omamoodi lõbus saata korda võimatut. Knowledge speaks, but wisdom listens. - + Teadmised räägivad, tarkus kuulab. A witty saying proves nothing. - + Kaval ütlus ei tõesta midagi. Success usually comes to those who are too busy to be looking for it. - + Edu tuleb tavaliselt nende juurde, kel on liiga kiire, selleks et seda otsida. Well-timed silence hath more eloquence than speech. - + Hästiajastatud vaikus on väljendusrikkam kui kõne I have never let my schooling interfere with my education. - + Ma ei ole kunagi lasknud koolil segada enda harimist. The best way to predict the future is to invent it. - + Parim meetod tuleviku ennustamiseks on see leiutada Well done is better than well said. - + Hästitehtu on parem kui hästiöeldu. Sometimes it is not enough that we do our best; we must do what is required. - + Vahel ei piisa meie parimast; Peame tegema seda, mis on vaja. The truth is more important than the facts. - + Tõde on olulisem kui faktid. Better to remain silent and be thought a fool than to speak out and remove all doubt. - + Parem olla vait ja lasta endast mõelda kui lollist kui teha suu lahti ja eemaldada kõik kahtlused. Initializing Session … - + Seansi käivitumine... Loading System Settings … - + Süsteemi Seadete laadimine... Loading User Preferences … - + Kasutajaeelistuste laadimine... Preparing System Tray … - + Süsteemi tööriba ettevalimistamine... Starting Window Manager … - + Aknahalduri käivitumine... Detecting Applications … - + Olemasolevate programmide tuvastamine... Preparing Menus … - + Kasutajamenüüde ettevalmistamine... Preparing Workspace … - + Töölaua ettevalmistamine... Finalizing … - + Viimased liigutused... Starting App: %1 - + Käivitan rakenduse: %1 @@ -527,7 +528,7 @@ Go Back - Mine tagasi + Mine tagasi @@ -547,12 +548,12 @@ Remove from Quicklaunch - + Eemalda Kiirkäivitusest Add to Quicklaunch - + Lisa Kiirkäivitusse @@ -560,7 +561,7 @@ Error parsing script output: %1 - + Viga skripti väljundi töötlemisel: %1 @@ -573,92 +574,92 @@ Applications - Rakendused + Rakendused Browse Files - + Install Applications - Paigalda rakendusi + Paigalda rakendusi Control Panel - Juhtpaneel + Juhtpaneel Multimedia - Multimeedia + Multimeedia Development - Arendus + Arendustarkvara Education - Haridus + Haridus Games - Mängud + Mängud Graphics - Graafika + Graafika Network - Võrk + Võrk Office - Kontor + Kontor Science - Teadus + Teadus Settings - Sätted + Sätted System - Süsteem + Süsteem Utility - Tööriistad + Tööriistad Wine - Wine + Wine Unsorted - Sortimata + Sortimata Leave - + Lahku @@ -679,12 +680,12 @@ Time Zone (%1) - + Ajavöönd (%1) Use System Time - + Kasuta süsteemiaega @@ -692,32 +693,32 @@ Modify Item - + Muuda Start Moving Item - + Alusta liigutamist Start Resizing Item - + Alusta suuruse muutmist Increase Item Sizes - + Suurenda mõõte Decrease Item Sizes - + Vähenda mõõte Remove Item - + Eemalda @@ -773,24 +774,24 @@ Desktop Actions - + Töölauategevused New Folder - + Uus Kaust New File - + Uus Fail Paste - + Aseta @@ -810,24 +811,24 @@ Lock Session - + Lukusta sessioon Browse Files - + Sirvi Faile Leave - + Lahku Desktop - Töölaud + Töölaud @@ -835,7 +836,7 @@ Workspace 1 - + Tööruum 1 @@ -848,8 +849,8 @@ LQuickLaunchButton - Remove from Quicklaunch - + Remove from QuickLaunch + Eemalda Kiirkäivitusest @@ -858,7 +859,7 @@ Desktop - Töölaud + Töölaud @@ -879,7 +880,7 @@ Volume - + Helitugevus @@ -954,17 +955,17 @@ Show All Windows - + Näita kõiki aknaid Minimize All Windows - + Minimeeri kõik aknad Close All Windows - + Sulge kõik aknad @@ -1005,7 +1006,7 @@ Disk I/O - + Ketta I/O @@ -1028,37 +1029,37 @@ Name: - Nimi: + Nimi: Invalid Note Name: Try Again - + Vigane märkmenimi: Proovi uuesti Select a Note Name - + Vali märkmenimi Open Text File - + Ava tekstifail Create a Note - + Loo märge Rename Note - + Nimeta märge ümber Delete Note - + Kustuta märge @@ -1066,57 +1067,57 @@ Form - Vorm + Vorm Clear Playlist - Tühjenda esitusloend + Tühjenda esitusloend Shuffle Playlist - Sega loendi järjekord + Sega loendi järjekord Add Files - Lisa faile + Lisa faile Add Directory - Lisa kaust + Lisa kaust Add URL - Lisa URL + Lisa URL Multimedia Files - Multimeediafailid + Multimeediafailid Select Multimedia Files - Vali multimeediafailid + Vali multimeediafailid Select Multimedia Directory - Vali multimeedia kaust + Vali multimeedia kaust Enter a valid URL for a multimedia file or stream: - Sisesta multimeediafaili või -voo URL + Sisesta multimeediafaili või -voo URL Multimedia URL - Multimeedia URL + Multimeedia URL @@ -1182,155 +1183,155 @@ Form - Vorm + Vorm View Options - + Vaata valikuid Open Website - + Ava veebileht More - + Rohkem Back to Feeds - + Tagasi voo juurde Feed Information - + Voo informatsioon Remove Feed - + Eemalda voog New Feed Subscription - + Uuele voole registreerumine RSS URL - + RSS URL aadress Load a preset RSS Feed - + Lae eelseadistatud RSS voog Add to Feeds - + Lisa voogudele Feed Reader Settings - + Uudisvoogude lugeja seaded Manual Sync Only - + Ainult käsitsi sünkroniseerimine Some RSS feeds may request custom update intervals instead of using this setting - + Mõned uudisvood võivad nõuda erinevaid uuendusintervalle, selle seade kasutamise asemel. Default Sync Interval - + Vaikimisi sünkroniseerimise intervall Hour(s) - + Tundides Minutes - + Minutites Save Settings - + Salvesta seaded Add RSS Feed - + Lisa uudisvoog View Feed Details - + Vaata uudisvoo detaile Settings - Sätted + Sätted Update Feeds Now - + Uuenda uudisvooge Lumina Desktop RSS - + Lumina Töölaua RSS Feed URL: %1 - + Uudisvoo URL: %1 Title: %1 - + Pealkiri: %1 Description: %1 - + Kirjeldus: %1 Website: %1 - + Veebileht: %1 Last Build Date: %1 - + Viimane koostamise aeg: %1 Last Sync: %1 - + Viimane sünkr.: %1 Next Sync: %1 - + Järgmine sünkr.: %1 @@ -1343,22 +1344,22 @@ Preferences - + Eelistus Wallpaper - + Taustapilt Display - + Ekraan All Desktop Settings - + Kõik ekraaniseaded @@ -1376,42 +1377,42 @@ Form - Vorm + Vorm Type to search - + Trüki millegi otsimiseks Browse Files - + Sirvi faile Browse Applications - + Sirvi programme Control Panel - Juhtpaneel + Juhtpaneel Leave - + Lahku Manage Applications - + Halda programme Show Categories - + Näita kategooriaid @@ -1421,32 +1422,32 @@ Suspend - Arvuti peatamine + Arvuti unerežiim Restart - Taaskäivita + Taaskäivita Power Off - + Lülita välja Log Out - Logi välja + Logi välja Preferences - + Eelistused (System Performing Updates) - + (Süsteem paigaldab uuendusi) @@ -1456,49 +1457,49 @@ Apply Updates? - + Alusta uuenduste paigaldamist? You have system updates waiting to be applied! Do you wish to install them now? - + Sul on ootel süsteemiuuendused. Kas soovid neid nüüd paigaldada? Yes - + Jah No - + Ei Cancel - Loobu + Loobu %1% (Plugged In) - + %1% (ühendatud) %1% (%2 Estimated) - + %1% (%2 hinnanguliselt) %1% Remaining - + %1% jäänud Workspace %1/%2 - Tööruum %1/%2 + Tööruum %1/%2 @@ -1521,7 +1522,7 @@ Power Off - + Lülita välja @@ -1542,22 +1543,22 @@ Apply Updates? - + Paigalda uuendused? You have system updates waiting to be applied! Do you wish to install them now? - + Sul on ootel süsteemiuuendused! Kas soovid neid kohe lasta paigaldada? Yes - + Jah No - + Ei @@ -1588,7 +1589,7 @@ UserWidget - UserWidget + Kasutajavidin @@ -1769,67 +1770,67 @@ Multimedia - Multimeedia + Multimeedia Development - Arendus + Arendus Education - Haridus + Haridus Games - Mängud + Mängud Graphics - Graafika + Graafika Network - Võrk + Võrk Office - Kontor + Kontor Science - Teadus + Teadus Settings - Sätted + Sätted System - Süsteem + Süsteem Utility - Tööriistad + Tööriistad Wine - Wine + Wine Unsorted - Sortimata + Sortimata -- cgit From 7b2df8beebd480dca920534a4560c1f3cce9188c Mon Sep 17 00:00:00 2001 From: ahto Date: Mon, 6 Nov 2017 20:18:55 +0200 Subject: modified: src-qt5/core/lumina-info/i18n/lumina-info_et.ts modified: src-qt5/core/lumina-open/i18n/lumina-open_et.ts modified: src-qt5/experimental/lumina-terminal/i18n/l-terminal_et.ts --- src-qt5/core/lumina-info/i18n/lumina-info_et.ts | 32 +++++++++---------- src-qt5/core/lumina-open/i18n/lumina-open_et.ts | 32 +++++++++---------- .../lumina-terminal/i18n/l-terminal_et.ts | 36 +++++++++++----------- 3 files changed, 50 insertions(+), 50 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-info/i18n/lumina-info_et.ts b/src-qt5/core/lumina-info/i18n/lumina-info_et.ts index 90c031e5..a6280c94 100644 --- a/src-qt5/core/lumina-info/i18n/lumina-info_et.ts +++ b/src-qt5/core/lumina-info/i18n/lumina-info_et.ts @@ -21,12 +21,12 @@ Lumina Website - + Lumina veebileht Bug Reports - + Puukidest teadaandmine @@ -46,7 +46,7 @@ Ask the Community - + Küsi kommuunilt @@ -99,67 +99,67 @@ Multimedia - + Multimeedia Development - + Arendustegevus Education - + Haridus Games - + Mängud Graphics - + Graafika Network - + Võrk Office - + Kontor Science - + Teadus Settings - + Sätted System - + Süsteem Utility - + Tööriistad Wine - + Wine Unsorted - + Sorteerimata diff --git a/src-qt5/core/lumina-open/i18n/lumina-open_et.ts b/src-qt5/core/lumina-open/i18n/lumina-open_et.ts index df9c029b..ee6afe8b 100644 --- a/src-qt5/core/lumina-open/i18n/lumina-open_et.ts +++ b/src-qt5/core/lumina-open/i18n/lumina-open_et.ts @@ -166,7 +166,7 @@ Application entry is invalid: %1 - + Rakenduse %1 kirje on vigane. @@ -191,12 +191,12 @@ Binary Missing - + Binaarfail puudub Could not find "%1". Please ensure it is installed first. - + Ei leidnud "%1" . Palun veendu et see on paigaldatud. @@ -214,67 +214,67 @@ Multimedia - Multimeedia + Multimeedia Development - Arendus + Arendus Education - Haridus + Haridus Games - + Mängud Graphics - Graafika + Graafika Network - Võrk + Võrk Office - Kontor + Kontor Science - Teadus + Teadus Settings - Sätted + Sätted System - Süsteem + Süsteem Utility - + Tööriistad Wine - + Wine Unsorted - + Sorteerimata diff --git a/src-qt5/experimental/lumina-terminal/i18n/l-terminal_et.ts b/src-qt5/experimental/lumina-terminal/i18n/l-terminal_et.ts index f14c723f..e4175b01 100644 --- a/src-qt5/experimental/lumina-terminal/i18n/l-terminal_et.ts +++ b/src-qt5/experimental/lumina-terminal/i18n/l-terminal_et.ts @@ -6,12 +6,12 @@ Copy Selection - + Kopeeri valitu Paste - + Aseta @@ -29,17 +29,17 @@ Close Terminal - + Sulge Terminal Move To Monitor - + Liiguta ekraanile Monitor %1 - + Ekraan %1 @@ -47,67 +47,67 @@ Multimedia - + Multimeedia Development - + Arendus Education - + Haridus Games - + Mängud Graphics - + Graafika Network - + Võrk Office - + Kontor Science - + Teadus Settings - + Sätted System - + Süsteem Utility - + Tööriistad Wine - + Wine Unsorted - + Sorteerimata -- cgit From 5d7b8a4c02051fb20a464bdca0536fb6f2bd509d Mon Sep 17 00:00:00 2001 From: ahto Date: Mon, 6 Nov 2017 20:22:33 +0200 Subject: modified: src-qt5/core/lumina-info/i18n/lumina-info_et.ts --- src-qt5/core/lumina-info/i18n/lumina-info_et.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-info/i18n/lumina-info_et.ts b/src-qt5/core/lumina-info/i18n/lumina-info_et.ts index a6280c94..09142c95 100644 --- a/src-qt5/core/lumina-info/i18n/lumina-info_et.ts +++ b/src-qt5/core/lumina-info/i18n/lumina-info_et.ts @@ -16,7 +16,7 @@ Source Repository - + Lähtekoodi repositoorium @@ -26,7 +26,7 @@ Bug Reports - Puukidest teadaandmine + Puukide raporteerimine -- cgit From aae93096bccb55ab9e60621f559e5116b9403a5f Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Wed, 8 Nov 2017 19:27:45 -0500 Subject: Finished Grav screensaver in QML --- .../extrafiles/screensavers/qml_scripts/Grav.qml | 117 ++++++++++++--------- 1 file changed, 67 insertions(+), 50 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml index d5245c9b..7a3c33cd 100644 --- a/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml +++ b/src-qt5/core/lumina-desktop-unified/extrafiles/screensavers/qml_scripts/Grav.qml @@ -8,38 +8,74 @@ Rectangle { height: 600 color: "black" + //TODO Add orbital trails option + //Between 5 and 15 planets, read from settings - property var planets: Math.round(( Math.random() * 10 ) + 5 ) + property int planets: Math.round(( Math.random() * 10 ) + 5 ) + property int cx: Math.round(width/2) + property int cy: Math.round(height/2) //Create planets Repeater { - model: planets - - Rectangle { - id : index - parent: canvas - - //Place the planet randomly on the canvas, but not too close to the edge - x: Math.round(Math.random()*canvas.width) - - //Check to make sure the planets are not too close to the sun (outside a 50px radius) - //while( Math.round(Math.random()*canvas.width) < (width/2 + 50) or Math.round(Math.random()*canvas.width) > (width/2 - 50)) - - y: Math.round(Math.random()*canvas.height) - - - //Create the orbit animation - - //Planet size between 14 and 32 pixels - width: Math.round(1.75 * (((Math.random() * 10) + 8 ))) - height: width - - //Make each rectangle look circular - radius: width / 2 - - //Give each planet a random color, semi-transparent - color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.5) - } + id: planetRepeater + model: planets + + Rectangle { + id : index + parent: canvas + + //Creates random distance for elipse + property double c: Math.random() * 250 + property double b: Math.random() * 150 + c + property double a: Math.sqrt(b*b+c*c) + //Random angle of rotation + property double th: Math.random() * Math.PI + + //Calculates starting position + x: Math.round(cx + a * Math.cos(th)) + y: Math.round(cy + b * Math.sin(th)) + + //Planet size between 14 and 32 pixels + width: Math.round(1.75 * (((Math.random() * 10) + 8 ))) + height: width + + //Make each rectangle look circular + radius: width / 2 + + //Give each planet a random color, semi-transparent + color: Qt.rgba(Math.random(), Math.random(), Math.random(), 0.5) + + Timer { + //Each planet updates between 1ms and 51ms (smaller times=faster) + interval: Math.round(Math.random() * 50 ) + 1 + repeat: true + running: true + property bool starting: true + property int time: 0 + + onTriggered: { + //Move a planet 80 pixels away from the sun if the planet is too close + if(starting) { + if(x > cx && Math.abs(cx-x) < 80) { + x+=80 + }else if(x < cx && Math.abs(cx-x) < 80) { + x-=80 + } + + if(y > cy && Math.abs(cy-y) < 80) { + y+=80 + }else if(y < cy && Math.abs(cy-y) < 80) { + y-=80 + } + starting = false; + } + //Parametric equation that calculates the position of the general ellipse. Completes a loop ever 314 cycles. Credit to + x = cx+a*Math.cos(2*Math.PI*(time/314.0))*Math.cos(th) - b*Math.sin(2*Math.PI*(time/314.0))*Math.sin(th) + y = cy+a*Math.cos(2*Math.PI*(time/314.0))*Math.sin(th) + b*Math.sin(2*Math.PI*(time/314.0))*Math.cos(th) + time++; + } + } + } } //Create the star @@ -47,9 +83,9 @@ Rectangle { id: star parent: canvas - //Centers in star in the center of the canvas - x: Math.round(canvas.width / 2) - y: Math.round(canvas.height / 2) + //Centers in star in the center of the canvas, with an offset to center the animation + x: cx - 30 + y: cy - 30 width: 60 height: width @@ -67,8 +103,6 @@ Rectangle { PropertyAnimation { duration: 2000; to: 60 } } - //border.width: 4 - //border.color: "blue" color: "black" radius: width / 2 @@ -86,21 +120,4 @@ Rectangle { } } - - /*Motion timer - Timer { - interval: 1 - repeat: true - running: true - property bool starting: true - - onTriggered: { - if(starting) { interval = 3010; starting = false; } - - } - }*/ - - Component.onCompleted: { - //console.log(Math.random()) - } } -- cgit From 556ff459148d03ebd85fa3db770e8819ad770b2d Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Mon, 13 Nov 2017 15:33:07 -0500 Subject: Add a special rule for Ubuntu Linux: IncludePath for the poppler files is different - add it automatically. --- src-qt5/OS-detect.pri | 7 +++++-- src-qt5/core/README.md | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src-qt5') diff --git a/src-qt5/OS-detect.pri b/src-qt5/OS-detect.pri index 8511bd81..3d01ea5f 100644 --- a/src-qt5/OS-detect.pri +++ b/src-qt5/OS-detect.pri @@ -75,12 +75,15 @@ isEmpty(OS){ #Apply any special rules for particular distros equals(LINUX_DISTRO,"Fedora"){ isEmpty(L_ETCDIR){ L_ETCDIR=/etc } - } + } equals(LINUX_DISTRO,"Gentoo"){ isEmpty(L_BINDIR){ L_BINDIR = $${PREFIX}/bin } isEmpty(L_ETCDIR){ L_ETCDIR = $${PREFIX}/../etc } isEmpty(L_MANDIR){ L_MANDIR = $${PREFIX}/share/man } - } + } + equals(LINUX_DISTRO,"Ubuntu"){ + INCLUDEPATH *= /usr/include/poppler/qt5 + } }else{ OS="Unknown"; } diff --git a/src-qt5/core/README.md b/src-qt5/core/README.md index 6a17d900..6ed23f78 100644 --- a/src-qt5/core/README.md +++ b/src-qt5/core/README.md @@ -27,6 +27,7 @@ Other Files that get installed if "core" is built directly: * svg * widgets * x11extras + * NOTE: Qt5 platform theme and developer libraries are also required to build the Lumina theme engine plugin ("qtbase5-*" on Ubuntu 17.10) 2. X11 Libraries * libXdamage 3. XCB Libraries -- cgit