diff options
Diffstat (limited to 'src-qt5')
63 files changed, 1618 insertions, 757 deletions
diff --git a/src-qt5/core-utils/lumina-config/AppDialog.h b/src-qt5/core-utils/lumina-config/AppDialog.h index ea7615e2..2b03fc76 100644 --- a/src-qt5/core-utils/lumina-config/AppDialog.h +++ b/src-qt5/core-utils/lumina-config/AppDialog.h @@ -23,13 +23,22 @@ private: Ui::AppDialog *ui; public: - AppDialog(QWidget *parent = 0) : QDialog(parent), ui(new Ui::AppDialog){ + AppDialog(QWidget *parent = 0, QString defaultPath = "") : QDialog(parent), ui(new Ui::AppDialog){ ui->setupUi(this); //load the designer file appreset = false; - ui->comboBox->clear(); + ui->listApps->clear(); + QListWidgetItem *defaultItem = nullptr; QList<XDGDesktop*> APPS = LXDG::sortDesktopNames(APPSLIST->apps(false,false)); //Don't show all/hidden for(int i=0; i<APPS.length(); i++){ - ui->comboBox->addItem( LXDG::findIcon(APPS[i]->icon,"application-x-executable"), APPS[i]->name, APPS[i]->filePath); + QListWidgetItem *app = new QListWidgetItem(LXDG::findIcon(APPS[i]->icon,"application-x-executable"), APPS[i]->name); + app->setData(Qt::UserRole, APPS[i]->filePath); + ui->listApps->addItem(app); + if(APPS[i]->filePath == defaultPath){ + defaultItem = app; + } + } + if(ui->listApps->count()){ + ui->listApps->setCurrentItem(defaultItem != nullptr ? defaultItem : ui->listApps->item(0)); } this->setWindowIcon( LXDG::findIcon("system-search","") ); if(parent!=0){ @@ -56,7 +65,10 @@ public: private slots: void on_buttonBox_accepted(){ - appselected = ui->comboBox->currentData().toString(); + QListWidgetItem *item = ui->listApps->currentItem(); + if(item != nullptr){ + appselected = item->data(Qt::UserRole).toString(); + } this->close(); } void on_buttonBox_rejected(){ @@ -68,6 +80,26 @@ private slots: this->close(); } } + void on_listApps_itemDoubleClicked(QListWidgetItem *item){ + appselected = item->data(Qt::UserRole).toString(); + this->close(); + } + void on_lineSearch_textChanged(const QString &term){ + QListWidgetItem *first_visible = nullptr; + for(int i = 0; i < ui->listApps->count(); i++){ + QListWidgetItem *item = ui->listApps->item(i); + bool visible = item->text().contains(term, Qt::CaseInsensitive); + item->setHidden(!visible); + if(visible && first_visible == nullptr){ + first_visible = item; + } + } + //Select the first app + ui->listApps->setCurrentItem(first_visible); + if(first_visible != nullptr){ + ui->listApps->scrollToItem(first_visible); + } + } }; #endif diff --git a/src-qt5/core-utils/lumina-config/AppDialog.ui b/src-qt5/core-utils/lumina-config/AppDialog.ui index 63323f7d..ec7de974 100644 --- a/src-qt5/core-utils/lumina-config/AppDialog.ui +++ b/src-qt5/core-utils/lumina-config/AppDialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>348</width> - <height>91</height> + <height>300</height> </rect> </property> <property name="windowTitle"> @@ -15,46 +15,14 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QComboBox" name="comboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> + <widget class="QLineEdit" name="lineSearch"> + <property name="placeholderText"> + <string>Search for....</string> </property> </widget> </item> <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> + <widget class="QListWidget" name="listApps"/> </item> <item> <widget class="QDialogButtonBox" name="buttonBox"> diff --git a/src-qt5/core-utils/lumina-config/i18n/lumina-config_de.ts b/src-qt5/core-utils/lumina-config/i18n/lumina-config_de.ts index 7109453a..9d145f55 100644 --- a/src-qt5/core-utils/lumina-config/i18n/lumina-config_de.ts +++ b/src-qt5/core-utils/lumina-config/i18n/lumina-config_de.ts @@ -340,7 +340,7 @@ </message> <message> <location filename="../LPlugins.cpp" line="67"/> - <source>Start menu alternative focusing on the user's files, directories, and favorites.</source> + <source>Start menu alternative focusing on the user's files, directories, and favorites.</source> <translation>Startmenüalternative, die Benutzerdateien, Verzeichnisse und Lesezeichen fokussiert.</translation> </message> <message> @@ -531,12 +531,12 @@ <message> <location filename="../LPlugins.cpp" line="312"/> <source>Lock Session</source> - <translation type="unfinished"></translation> + <translation>Sitzung sperren</translation> </message> <message> <location filename="../LPlugins.cpp" line="313"/> <source>Lock the current desktop session</source> - <translation type="unfinished"></translation> + <translation>Aktuelle Arbeitsflächen-Sitzung sperren</translation> </message> <message> <location filename="../LPlugins.cpp" line="323"/> @@ -711,17 +711,17 @@ <message> <location filename="../pages/getPage.h" line="29"/> <source>Wallpaper</source> - <translation type="unfinished"></translation> + <translation>Hintergrundbild</translation> </message> <message> <location filename="../pages/getPage.h" line="30"/> <source>Theme</source> - <translation type="unfinished"></translation> + <translation>Thema</translation> </message> <message> <location filename="../pages/getPage.h" line="32"/> <source>Autostart</source> - <translation type="unfinished"></translation> + <translation>Autostart</translation> </message> <message> <location filename="../pages/getPage.h" line="33"/> @@ -761,27 +761,27 @@ <message> <location filename="../pages/getPage.h" line="36"/> <source>Desktop</source> - <translation type="unfinished"></translation> + <translation>Arbeitsfläche</translation> </message> <message> <location filename="../pages/getPage.h" line="37"/> <source>Panels</source> - <translation type="unfinished"></translation> + <translation>Leisten</translation> </message> <message> <location filename="../pages/getPage.h" line="38"/> <source>Menu</source> - <translation type="unfinished"></translation> + <translation>Menü</translation> </message> <message> <location filename="../pages/getPage.h" line="42"/> <source>Input Device Settings</source> - <translation type="unfinished"></translation> + <translation>Eingabegeräteeinstellungen</translation> </message> <message> <location filename="../pages/getPage.h" line="42"/> <source>Adjust keyboard and mouse devices</source> - <translation type="unfinished"></translation> + <translation>Tastatur und Mausgeräte anpassen</translation> </message> <message> <location filename="../pages/getPage.h" line="36"/> @@ -826,7 +826,7 @@ <message> <location filename="../pages/getPage.h" line="39"/> <source>Localization</source> - <translation type="unfinished"></translation> + <translation>Lokalisierung</translation> </message> <message> <location filename="../pages/getPage.h" line="40"/> @@ -1073,7 +1073,7 @@ <message> <location filename="../pages/page_compton.ui" line="39"/> <source>Only use compositing with GPU acceleration </source> - <translation type="unfinished"></translation> + <translation>Compositing nur mit GPU-Beschleunigung verwenden </translation> </message> <message> <location filename="../pages/page_compton.cpp" line="38"/> @@ -1253,12 +1253,12 @@ </message> <message> <location filename="../pages/page_fluxbox_keys.ui" line="244"/> - <source>"Mod1": Alt key -"Mod4": Windows/Mac key -"Control": Ctrl key</source> - <translation>"Mod1": Alt-Taste -"Mod4": Windows/Mac-Taste -"Steuerung": Strg-Taste</translation> + <source>"Mod1": Alt key +"Mod4": Windows/Mac key +"Control": Ctrl key</source> + <translation>"Mod1": Alt-Taste +"Mod4": Windows/Mac-Taste +"Steuerung": Strg-Taste</translation> </message> <message> <location filename="../pages/page_fluxbox_keys.cpp" line="71"/> @@ -1436,12 +1436,12 @@ <message> <location filename="../pages/page_interface_panels.ui" line="69"/> <source>Profile</source> - <translation type="unfinished"></translation> + <translation>Profil</translation> </message> <message> <location filename="../pages/page_interface_panels.ui" line="82"/> <source>Import</source> - <translation type="unfinished"></translation> + <translation>Import</translation> </message> <message> <location filename="../pages/page_interface_panels.cpp" line="52"/> @@ -1474,7 +1474,7 @@ <message> <location filename="../pages/page_main.cpp" line="61"/> <source>Desktop Defaults</source> - <translation type="unfinished"></translation> + <translation>Arbeitsflächen-Standardeinstellungen</translation> </message> <message> <location filename="../pages/page_main.cpp" line="65"/> @@ -1497,27 +1497,27 @@ <message> <location filename="../pages/page_mouse.cpp" line="53"/> <source>Input Device Settings</source> - <translation type="unfinished"></translation> + <translation>Eingabegeräteeinstellungen</translation> </message> <message> <location filename="../pages/page_mouse.cpp" line="81"/> <source>Mouse #%1</source> - <translation type="unfinished"></translation> + <translation>Maus #%1</translation> </message> <message> <location filename="../pages/page_mouse.cpp" line="85"/> <source>Keyboard #%1</source> - <translation type="unfinished"></translation> + <translation>Tastatur #%1</translation> </message> <message> <location filename="../pages/page_mouse.cpp" line="106"/> <source>Extension Device #%1</source> - <translation type="unfinished"></translation> + <translation>Erweiterungsgerät #%1</translation> </message> <message> <location filename="../pages/page_mouse.cpp" line="107"/> <source>Master Device</source> - <translation type="unfinished"></translation> + <translation>Hauptgerät</translation> </message> </context> <context> @@ -1613,7 +1613,7 @@ <message> <location filename="../pages/page_session_options.ui" line="65"/> <source>Show application crash data</source> - <translation type="unfinished"></translation> + <translation>Anwendungsabsturzdaten anzeigen</translation> </message> <message> <location filename="../pages/page_session_options.ui" line="74"/> @@ -1833,7 +1833,7 @@ <message> <location filename="../pages/page_theme.ui" line="36"/> <source>Desktop Theme</source> - <translation type="unfinished"></translation> + <translation>Arbeitsflächenthema</translation> </message> <message> <location filename="../pages/page_theme.ui" line="42"/> @@ -1889,7 +1889,7 @@ <message> <location filename="../pages/page_theme.ui" line="192"/> <source>Application Themes</source> - <translation type="unfinished"></translation> + <translation>Anwendungsthemen</translation> </message> <message> <location filename="../pages/page_theme.ui" line="198"/> @@ -1920,12 +1920,12 @@ <message> <location filename="../pages/page_theme.cpp" line="137"/> <source>None</source> - <translation type="unfinished"></translation> + <translation>Keine</translation> </message> <message> <location filename="../pages/page_theme.cpp" line="138"/> <source>Manual Setting</source> - <translation type="unfinished"></translation> + <translation>Manuelle Einstellung</translation> </message> </context> <context> diff --git a/src-qt5/core-utils/lumina-config/i18n/lumina-config_pl.ts b/src-qt5/core-utils/lumina-config/i18n/lumina-config_pl.ts index c52873a3..eade831a 100644 --- a/src-qt5/core-utils/lumina-config/i18n/lumina-config_pl.ts +++ b/src-qt5/core-utils/lumina-config/i18n/lumina-config_pl.ts @@ -340,8 +340,8 @@ </message> <message> <location filename="../LPlugins.cpp" line="67"/> - <source>Start menu alternative focusing on the user's files, directories, and favorites.</source> - <translation type="unfinished"></translation> + <source>Start menu alternative focusing on the user's files, directories, and favorites.</source> + <translation>Alternatywny wygląd menu start, pokazujący pliki użytkownika, jego katalogi i ulubione elementy.</translation> </message> <message> <location filename="../LPlugins.cpp" line="73"/> @@ -351,7 +351,7 @@ <message> <location filename="../LPlugins.cpp" line="74"/> <source>Start menu alternative which focuses on launching applications.</source> - <translation type="unfinished"></translation> + <translation>Alternatywny wygląd menu start, ułatwiający szybkie uruchamianie aplikacji.</translation> </message> <message> <location filename="../LPlugins.cpp" line="94"/> @@ -371,12 +371,12 @@ <message> <location filename="../LPlugins.cpp" line="130"/> <source>View and control any running application windows (group similar windows under a single button).</source> - <translation type="unfinished"></translation> + <translation>Pogląd i kontrola każdego okna uruchomionej aplikacji (grupowanie tych samych aplikacji).</translation> </message> <message> <location filename="../LPlugins.cpp" line="137"/> <source>View and control any running application windows (every individual window has a button)</source> - <translation type="unfinished"></translation> + <translation>Pogląd i kontrola każdego okna uruchomionej aplikacji (nie grupuj aplikacji).</translation> </message> <message> <location filename="../LPlugins.cpp" line="150"/> @@ -500,12 +500,12 @@ <location filename="../LPlugins.cpp" line="178"/> <location filename="../LPlugins.cpp" line="305"/> <source>Menu Script</source> - <translation type="unfinished"></translation> + <translation>Menu Skrypt</translation> </message> <message> <location filename="../LPlugins.cpp" line="205"/> <source>Configurable area for automatically showing desktop icons</source> - <translation type="unfinished"></translation> + <translation>Konfigurowalny obszar do automatycznego pokazywania ikon pulpitu</translation> </message> <message> <location filename="../LPlugins.cpp" line="263"/> @@ -520,23 +520,23 @@ <message> <location filename="../LPlugins.cpp" line="292"/> <source>List the open, minimized, active, and urgent application windows</source> - <translation type="unfinished"></translation> + <translation>Lista otwartych, zminimalizowanych i aktywnych okien aplikacji</translation> </message> <message> <location filename="../LPlugins.cpp" line="179"/> <location filename="../LPlugins.cpp" line="306"/> <source>Run an external script to generate a user defined menu</source> - <translation type="unfinished"></translation> + <translation>Uruchom skrypt do generowania menu</translation> </message> <message> <location filename="../LPlugins.cpp" line="312"/> <source>Lock Session</source> - <translation type="unfinished"></translation> + <translation>Zablokuj sesję</translation> </message> <message> <location filename="../LPlugins.cpp" line="313"/> <source>Lock the current desktop session</source> - <translation type="unfinished"></translation> + <translation>Zablokuj sesję pulpitu</translation> </message> <message> <location filename="../LPlugins.cpp" line="323"/> @@ -711,17 +711,17 @@ <message> <location filename="../pages/getPage.h" line="29"/> <source>Wallpaper</source> - <translation type="unfinished"></translation> + <translation>Tapeta</translation> </message> <message> <location filename="../pages/getPage.h" line="30"/> <source>Theme</source> - <translation type="unfinished"></translation> + <translation>Motyw</translation> </message> <message> <location filename="../pages/getPage.h" line="32"/> <source>Autostart</source> - <translation type="unfinished"></translation> + <translation>Uruchamianie automatyczne</translation> </message> <message> <location filename="../pages/getPage.h" line="33"/> @@ -761,27 +761,27 @@ <message> <location filename="../pages/getPage.h" line="36"/> <source>Desktop</source> - <translation type="unfinished"></translation> + <translation>Pulpit</translation> </message> <message> <location filename="../pages/getPage.h" line="37"/> <source>Panels</source> - <translation type="unfinished"></translation> + <translation>Panele</translation> </message> <message> <location filename="../pages/getPage.h" line="38"/> <source>Menu</source> - <translation type="unfinished"></translation> + <translation>Menu</translation> </message> <message> <location filename="../pages/getPage.h" line="42"/> <source>Input Device Settings</source> - <translation type="unfinished"></translation> + <translation>Ustawienia urządzeń wejściowych</translation> </message> <message> <location filename="../pages/getPage.h" line="42"/> <source>Adjust keyboard and mouse devices</source> - <translation type="unfinished"></translation> + <translation>Skonfiguruj klawiaturę oraz mysz</translation> </message> <message> <location filename="../pages/getPage.h" line="36"/> @@ -791,7 +791,7 @@ <message> <location filename="../pages/getPage.h" line="36"/> <source>Change what icons or tools are embedded on the desktop</source> - <translation type="unfinished"></translation> + <translation>Ikony lub narzędzia wyświetlane na pulpicie</translation> </message> <message> <location filename="../pages/getPage.h" line="37"/> @@ -801,12 +801,12 @@ <message> <location filename="../pages/getPage.h" line="37"/> <source>Change any floating panels and what they show</source> - <translation type="unfinished"></translation> + <translation>Panele i ich zawartość</translation> </message> <message> <location filename="../pages/getPage.h" line="38"/> <source>Menu Plugins</source> - <translation type="unfinished"></translation> + <translation>Wtyczki menu</translation> </message> <message> <location filename="../pages/getPage.h" line="38"/> @@ -821,12 +821,12 @@ <message> <location filename="../pages/getPage.h" line="39"/> <source>Change the default locale settings for this user</source> - <translation type="unfinished"></translation> + <translation>Zmień ustawienia językowe tego użytkownika</translation> </message> <message> <location filename="../pages/getPage.h" line="39"/> <source>Localization</source> - <translation type="unfinished"></translation> + <translation>Ustawienia językowe</translation> </message> <message> <location filename="../pages/getPage.h" line="40"/> @@ -849,7 +849,7 @@ <message> <location filename="../ScriptDialog.ui" line="14"/> <source>Setup a JSON Menu Script</source> - <translation type="unfinished"></translation> + <translation>Ustaw skrypt menu używając JSON</translation> </message> <message> <location filename="../ScriptDialog.ui" line="25"/> @@ -885,7 +885,7 @@ <message> <location filename="../ScriptDialog.cpp" line="57"/> <source>Select a menu script</source> - <translation type="unfinished"></translation> + <translation>Wybierz skrypt menu</translation> </message> <message> <location filename="../ScriptDialog.cpp" line="64"/> @@ -945,7 +945,7 @@ <message> <location filename="../mainWindow.ui" line="14"/> <source>MainWindow</source> - <translation type="unfinished"></translation> + <translation type="unfinished">MainWindow</translation> </message> <message> <location filename="../mainWindow.ui" line="23"/> @@ -1068,17 +1068,17 @@ <message> <location filename="../pages/page_compton.ui" line="32"/> <source>Disable Compositing Manager (session restart required)</source> - <translation type="unfinished"></translation> + <translation>Wyłącz menedżera kompozycji (wymagany restart sesji)</translation> </message> <message> <location filename="../pages/page_compton.ui" line="39"/> <source>Only use compositing with GPU acceleration </source> - <translation type="unfinished"></translation> + <translation>Menedżer kompozycji tylko z akceleracją GPU. </translation> </message> <message> <location filename="../pages/page_compton.cpp" line="38"/> <source>Compositor Settings</source> - <translation type="unfinished"></translation> + <translation>Ustawienia menedżera kompozycji</translation> </message> </context> <context> @@ -1199,7 +1199,7 @@ <message> <location filename="../pages/page_fluxbox_keys.ui" line="14"/> <source>page_fluxbox_keys</source> - <translation type="unfinished"></translation> + <translation type="unfinished">page_fluxbox_keys</translation> </message> <message> <location filename="../pages/page_fluxbox_keys.ui" line="34"/> @@ -1249,16 +1249,16 @@ <message> <location filename="../pages/page_fluxbox_keys.ui" line="220"/> <source>View Syntax Codes</source> - <translation type="unfinished"></translation> + <translation>Pokaż składnię kodu</translation> </message> <message> <location filename="../pages/page_fluxbox_keys.ui" line="244"/> - <source>"Mod1": Alt key -"Mod4": Windows/Mac key -"Control": Ctrl key</source> - <translation>"Mod1": Alt key -"Mod4": Windows/Mac key -"Control": Ctrl key</translation> + <source>"Mod1": Alt key +"Mod4": Windows/Mac key +"Control": Ctrl key</source> + <translation>"Mod1": Alt key +"Mod4": Windows/Mac key +"Control": Ctrl key</translation> </message> <message> <location filename="../pages/page_fluxbox_keys.cpp" line="71"/> @@ -1436,12 +1436,12 @@ <message> <location filename="../pages/page_interface_panels.ui" line="69"/> <source>Profile</source> - <translation type="unfinished"></translation> + <translation>Profil</translation> </message> <message> <location filename="../pages/page_interface_panels.ui" line="82"/> <source>Import</source> - <translation type="unfinished"></translation> + <translation>Import</translation> </message> <message> <location filename="../pages/page_interface_panels.cpp" line="52"/> diff --git a/src-qt5/core-utils/lumina-config/lumina-config.pro b/src-qt5/core-utils/lumina-config/lumina-config.pro index d690bcb3..5494393e 100644 --- a/src-qt5/core-utils/lumina-config/lumina-config.pro +++ b/src-qt5/core-utils/lumina-config/lumina-config.pro @@ -16,11 +16,11 @@ include(../../core/libLumina/LuminaXDG.pri) include(../../core/libLumina/LuminaSingleApplication.pri) include(../../core/libLumina/LuminaThemes.pri) -NO_XINPUT{ +#NO_XINPUT{ DEFINES+=NO_XINPUT -}else{ - include(../../core/libLumina/LInputDevice.pri) -} +#}else{ +# include(../../core/libLumina/LInputDevice.pri) +#} SOURCES += main.cpp \ mainWindow.cpp \ diff --git a/src-qt5/core-utils/lumina-config/pages/getPage.h b/src-qt5/core-utils/lumina-config/pages/getPage.h index c820283e..59dbcd2b 100644 --- a/src-qt5/core-utils/lumina-config/pages/getPage.h +++ b/src-qt5/core-utils/lumina-config/pages/getPage.h @@ -38,11 +38,6 @@ static QList<PAGEINFO> KnownPages(){ list << 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 << 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 << 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"); - #ifndef NO_XINPUT - if(LUtils::isValidBinary("xinput")){ - list << PageInfo("input-devices", QObject::tr("Input Device Settings"), QObject::tr("Input Device Settings"), "preferences-desktop-peripherals",QObject::tr("Adjust keyboard and mouse devices"), "user", QStringList(), QStringList() << "user"<<"speed"<<"accel"<<"mouse" << "keyboard"); - } - #endif // list << 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 << 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"); @@ -64,10 +59,6 @@ static QList<PAGEINFO> KnownPages(){ #include "page_session_options.h" #include "page_compton.h" -#ifndef NO_XINPUT -#include "page_mouse.h" -#endif - // #include "page_mouse_trueos.h" // #include "page_bluetooth_trueos.h" @@ -86,9 +77,6 @@ static PageWidget* 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); } - #ifndef NO_XINPUT - else if(id=="input-devices"){ page = new page_mouse(parent); } - #endif // else if(id=="mouse-settings"){ page = new page_mouse_trueos(parent); } // else if(id=="bluetooth-settings"){ page = new page_bluetooth_trueos(parent); } 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 b2a0896c..a21653c9 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.cpp @@ -42,92 +42,23 @@ void page_defaultapps::LoadSettings(int){ emit HasPendingChanges(false); emit ChangePageTitle( tr("Default Applications") ); -//First load the lumina-open specific defaults - // - Default File Manager - QString tmp = LXDG::findDefaultAppForMime("inode/directory"); - if(tmp.isEmpty()){ tmp = "lumina-fm"; } - if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings - if(tmp.endsWith(".desktop")){ - XDGDesktop file(tmp); - if(file.type == XDGDesktop::BAD){ - //Might be a binary - just print out the raw "path" - ui->tool_default_filemanager->setText(tmp.section("/",-1)); - ui->tool_default_filemanager->setIcon( LXDG::findIcon("application-x-executable","") ); - }else{ - ui->tool_default_filemanager->setText(file.name); - ui->tool_default_filemanager->setIcon(LXDG::findIcon(file.icon,"") ); - } - }else if(tmp.isEmpty()){ - ui->tool_default_filemanager->setText(tr("Click to Set")); - ui->tool_default_filemanager->setIcon( LXDG::findIcon("system-help","") ); - }else{ - //Might be a binary - just print out the raw "path" - ui->tool_default_filemanager->setText(tmp.section("/",-1)); - ui->tool_default_filemanager->setIcon( LXDG::findIcon("application-x-executable","") ); - } + //First load the lumina-open specific defaults + // - Default File Manager + defaultFileManager = LXDG::findDefaultAppForMime("inode/directory"); + if(defaultFileManager.isEmpty()){ defaultFileManager = "lumina-fm"; } + updateDefaultButton(ui->tool_default_filemanager, defaultFileManager); + // - Default Terminal - tmp =LXDG::findDefaultAppForMime("application/terminal"); //sessionsettings->value("default-terminal", "xterm").toString(); - if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings - if(tmp.endsWith(".desktop")){ - XDGDesktop file(tmp); - if(file.type == XDGDesktop::BAD){ - //Might be a binary - just print out the raw "path" - ui->tool_default_terminal->setText(tmp.section("/",-1)); - ui->tool_default_terminal->setIcon( LXDG::findIcon("application-x-executable","") ); - }else{ - ui->tool_default_terminal->setText(file.name); - ui->tool_default_terminal->setIcon(LXDG::findIcon(file.icon,"") ); - } - }else if(tmp.isEmpty()){ - ui->tool_default_terminal->setText(tr("Click to Set")); - ui->tool_default_terminal->setIcon( LXDG::findIcon("system-help","") ); - }else{ - //Might be a binary - just print out the raw "path" - ui->tool_default_terminal->setText(tmp.section("/",-1)); - ui->tool_default_terminal->setIcon( LXDG::findIcon("application-x-executable","") ); - } + defaultTerminal = LXDG::findDefaultAppForMime("application/terminal"); //sessionsettings->value("default-terminal", "xterm").toString(); + updateDefaultButton(ui->tool_default_terminal, defaultTerminal); + // - Default Web Browser - tmp = LXDG::findDefaultAppForMime("x-scheme-handler/http"); //appsettings->value("default/webbrowser", "").toString(); - if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings - if(tmp.endsWith(".desktop")){ - XDGDesktop file(tmp); - if(file.type == XDGDesktop::BAD){ - //Might be a binary - just print out the raw "path" - ui->tool_default_webbrowser->setText(tmp.section("/",-1)); - ui->tool_default_webbrowser->setIcon( LXDG::findIcon("application-x-executable","") ); - }else{ - ui->tool_default_webbrowser->setText(file.name); - ui->tool_default_webbrowser->setIcon(LXDG::findIcon(file.icon,"") ); - } - }else if(tmp.isEmpty()){ - ui->tool_default_webbrowser->setText(tr("Click to Set")); - ui->tool_default_webbrowser->setIcon( LXDG::findIcon("system-help","") ); - }else{ - //Might be a binary - just print out the raw "path" - ui->tool_default_webbrowser->setText(tmp.section("/",-1)); - ui->tool_default_webbrowser->setIcon( LXDG::findIcon("application-x-executable","") ); - } + defaultBrowser = LXDG::findDefaultAppForMime("x-scheme-handler/http"); //appsettings->value("default/webbrowser", "").toString(); + updateDefaultButton(ui->tool_default_webbrowser, defaultBrowser); + // - Default Email Client - tmp = LXDG::findDefaultAppForMime("application/email"); //appsettings->value("default/email", "").toString(); - if( !QFile::exists(tmp) && !LUtils::isValidBinary(tmp) ){ qDebug() << "Invalid Settings:" << tmp; tmp.clear(); } //invalid settings - if(tmp.endsWith(".desktop")){ - XDGDesktop file(tmp); - if(file.type == XDGDesktop::BAD){ - //Might be a binary - just print out the raw "path" - ui->tool_default_email->setText(tmp.section("/",-1)); - ui->tool_default_email->setIcon( LXDG::findIcon("application-x-executable","") ); - }else{ - ui->tool_default_email->setText(file.name); - ui->tool_default_email->setIcon(LXDG::findIcon(file.icon,"") ); - } - }else if(tmp.isEmpty()){ - ui->tool_default_email->setText(tr("Click to Set")); - ui->tool_default_email->setIcon( LXDG::findIcon("system-help","") ); - }else{ - //Might be a binary - just print out the raw "path" - ui->tool_default_email->setText(tmp.section("/",-1)); - ui->tool_default_email->setIcon( LXDG::findIcon("application-x-executable","") ); - } + defaultEmail = LXDG::findDefaultAppForMime("application/email"); //appsettings->value("default/email", "").toString(); + updateDefaultButton(ui->tool_default_email, defaultEmail); //Now load the XDG mime defaults ui->tree_defaults->clear(); @@ -135,7 +66,7 @@ void page_defaultapps::LoadSettings(int){ //qDebug() << "Mime List:\n" << defMimeList.join("\n"); defMimeList.sort(); //sort by group/mime //Now fill the tree by group/mime - QTreeWidgetItem *group = new QTreeWidgetItem(0); //nothing at the moment + QTreeWidgetItem *group = nullptr; QString ccat; for(int i=0; i<defMimeList.length(); i++){ //Get the info from this entry @@ -145,37 +76,38 @@ void page_defaultapps::LoadSettings(int){ QString def = defMimeList[i].section("::::",2,2); QString comment = defMimeList[i].section("::::",3,50); //Now check if this is a new category - if(ccat!=cat){ - //New group - group = new QTreeWidgetItem(0); + if(group == nullptr || ccat!=cat){ + //New group + group = new QTreeWidgetItem(0); group->setText(0, cat); //add translations for known/common groups later - ui->tree_defaults->addTopLevelItem(group); - ccat = cat; + ui->tree_defaults->addTopLevelItem(group); + ccat = cat; } //Now create the entry QTreeWidgetItem *it = new QTreeWidgetItem(); - it->setWhatsThis(0,mime); // full mimetype - it->setText(0, QString(tr("%1 (%2)")).arg(mime.section("/",-1), extlist) ); - it->setText(2,comment); - it->setToolTip(0, comment); it->setToolTip(1,comment); - //Now load the default (if there is one) - it->setWhatsThis(1,def); //save for later - if(def.endsWith(".desktop")){ - XDGDesktop file(def); - if(file.type == XDGDesktop::BAD){ - //Might be a binary - just print out the raw "path" - it->setText(1,def.section("/",-1)); - it->setIcon(1, LXDG::findIcon("application-x-executable","") ); - }else{ - it->setText(1, file.name); - it->setIcon(1, LXDG::findIcon(file.icon,"") ); - } - }else if(!def.isEmpty()){ - //Binary/Other default - it->setText(1, def.section("/",-1)); - it->setIcon(1, LXDG::findIcon("application-x-executable","") ); + it->setWhatsThis(0,mime); // full mimetype + it->setText(0, QString(tr("%1 (%2)")).arg(mime.section("/",-1), extlist) ); + it->setText(2,comment); + it->setToolTip(0, comment); it->setToolTip(1,comment); + //Now load the default (if there is one) + it->setWhatsThis(1,def); //save for later + it->setData(1, Qt::UserRole, def); + if(def.endsWith(".desktop")){ + XDGDesktop file(def); + if(file.type == XDGDesktop::BAD){ + //Might be a binary - just print out the raw "path" + it->setText(1, def.section("/",-1)); + it->setIcon(1, LXDG::findIcon("application-x-executable","") ); + }else{ + it->setText(1, file.name); + it->setIcon(1, LXDG::findIcon(file.icon,"") ); } - group->addChild(it); + }else if(!def.isEmpty()){ + //Binary/Other default + it->setText(1, def.section("/",-1)); + it->setIcon(1, LXDG::findIcon("application-x-executable","") ); + } + group->addChild(it); } ui->tree_defaults->sortItems(0,Qt::AscendingOrder); @@ -194,8 +126,8 @@ void page_defaultapps::updateIcons(){ //================= // PRIVATE //================= -QString page_defaultapps::getSysApp(bool allowreset){ - AppDialog dlg(this); +QString page_defaultapps::getSysApp(bool allowreset, QString defaultPath){ + AppDialog dlg(this, defaultPath); dlg.allowReset(allowreset); dlg.exec(); if(dlg.appreset && allowreset){ @@ -206,6 +138,7 @@ QString page_defaultapps::getSysApp(bool allowreset){ } void page_defaultapps::updateDefaultButton(QToolButton *button, QString app){ + if( !QFile::exists(app) && !LUtils::isValidBinary(app) ){ qDebug() << "Invalid Settings:" << app; app.clear(); } //invalid settings if(app.endsWith(".desktop")){ XDGDesktop file(app); if(file.type == XDGDesktop::BAD){ @@ -231,10 +164,11 @@ void page_defaultapps::updateDefaultButton(QToolButton *button, QString app){ //================= void page_defaultapps::changeDefaultBrowser(){ //Prompt for the new app - QString app = getSysApp(true); - if(app.isEmpty()){ return; }//nothing selected - if(app=="reset"){ app.clear(); } + QString app = getSysApp(true, defaultBrowser); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app.clear(); } //save the new app setting and adjust the button appearance + defaultBrowser = app; LXDG::setDefaultAppForMime("x-scheme-handler/http", app.section("/",-1)); LXDG::setDefaultAppForMime("x-scheme-handler/https", app.section("/",-1)); updateDefaultButton(ui->tool_default_webbrowser, app); @@ -242,30 +176,33 @@ void page_defaultapps::changeDefaultBrowser(){ void page_defaultapps::changeDefaultEmail(){ //Prompt for the new app - QString app = getSysApp(true); - if(app.isEmpty()){ return; }//nothing selected - if(app=="reset"){ app.clear(); } + QString app = getSysApp(true, defaultEmail); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app.clear(); } //save the new app setting and adjust the button appearance + defaultEmail = app; LXDG::setDefaultAppForMime("application/email",app.section("/",-1)); updateDefaultButton(ui->tool_default_email, app); } void page_defaultapps::changeDefaultFileManager(){ //Prompt for the new app - QString app = getSysApp(true); - if(app.isEmpty()){ return; }//nothing selected - if(app=="reset"){ app = "lumina-fm"; } + QString app = getSysApp(true, defaultFileManager); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app = "lumina-fm"; } //save the new app setting and adjust the button appearance + defaultFileManager = app; LXDG::setDefaultAppForMime("inode/directory", app.section("/",-1)); updateDefaultButton(ui->tool_default_filemanager, app); } void page_defaultapps::changeDefaultTerminal(){ //Prompt for the new app - QString app = getSysApp(true); - if(app.isEmpty()){ return; }//nothing selected - if(app=="reset"){ app = "xterm"; } + QString app = getSysApp(true, defaultTerminal); + if(app.isEmpty()){ return; }//nothing selected + if(app=="reset"){ app = "xterm"; } //save the new app setting and adjust the button appearance + defaultTerminal = app; LXDG::setDefaultAppForMime("application/terminal", app.section("/",-1) ); updateDefaultButton(ui->tool_default_terminal, app); } @@ -292,14 +229,19 @@ void page_defaultapps::cleardefaultitem(){ void page_defaultapps::setdefaultitem(){ QTreeWidgetItem *it = ui->tree_defaults->currentItem(); + QString path; if(it==0){ return; } //no item selected QList<QTreeWidgetItem*> list; for(int i=0; i<it->childCount(); i++){ list << it->child(i); } - if(list.isEmpty()){ list << it; } //just do the current item + if(list.isEmpty()){ + //just do the current item + list << it; + path = it->data(1, Qt::UserRole).toString(); + } //Prompt for which application to use - QString app = getSysApp(false); //no "reset" option + QString app = getSysApp(false, path); //no "reset" option if(app.isEmpty()){ return; }//nothing selected //Now set the items for(int i=0; i<list.length(); i++){ @@ -310,6 +252,7 @@ void page_defaultapps::setdefaultitem(){ list[i]->setWhatsThis(1,app); //app path list[i]->setIcon(1,LXDG::findIcon(desk.icon,"")); //reset the icon list[i]->setText(1,desk.name); //reset the name + list[i]->setData(1, Qt::UserRole, app); } } diff --git a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h index f80ea1ab..d8e2bcde 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h +++ b/src-qt5/core-utils/lumina-config/pages/page_defaultapps.h @@ -26,8 +26,12 @@ public slots: private: Ui::page_defaultapps *ui; + QString defaultBrowser; + QString defaultEmail; + QString defaultFileManager; + QString defaultTerminal; - QString getSysApp(bool allowreset); + QString getSysApp(bool allowreset, QString defaultPath = ""); void updateDefaultButton(QToolButton *button, QString app); diff --git a/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp b/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp index 827061af..3c355aa7 100644 --- a/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp +++ b/src-qt5/core-utils/lumina-config/pages/page_interface_panels.cpp @@ -21,6 +21,13 @@ page_interface_panels::page_interface_panels(QWidget *parent) : PageWidget(paren connect(ui->tool_panels_add, SIGNAL(clicked()), this, SLOT(newPanel()) ); updateIcons(); setupProfiles(); + + //Create panels container + QHBoxLayout *panels_layout = new QHBoxLayout(); + panels_layout->setContentsMargins(0,0,0,0); + panels_layout->setAlignment(Qt::AlignLeft); + panels_layout->addStretch(); + ui->scroll_panels->widget()->setLayout(panels_layout); } page_interface_panels::~page_interface_panels(){ @@ -53,28 +60,30 @@ void page_interface_panels::LoadSettings(int screennum){ QString screenID = QApplication::screens().at(cscreen)->name(); QString DPrefix = "desktop-"+screenID+"/"; int panelnumber = settings->value(DPrefix+"panels",-1).toInt(); + QBoxLayout *panels_layout = static_cast<QHBoxLayout*>(ui->scroll_panels->widget()->layout()); -//First clean any current panels - for(int i=0; i<PANELS.length(); i++){ delete PANELS.takeAt(i); i--; } - //Now create new panels - if(ui->scroll_panels->widget()->layout()==0){ - ui->scroll_panels->widget()->setLayout( new QHBoxLayout() ); - ui->scroll_panels->widget()->layout()->setContentsMargins(0,0,0,0); + //Remove extra panels (if any) + for(int i=panelnumber; i<PANELS.length(); i++){ + PanelWidget *tmp = PANELS.takeAt(i); + delete tmp; + i--; } - ui->scroll_panels->widget()->layout()->setAlignment(Qt::AlignLeft); - //Clear anything left over in the layout - for(int i=0; i<ui->scroll_panels->widget()->layout()->count(); i++){ - delete ui->scroll_panels->widget()->layout()->takeAt(i); + + int current_count = panels_layout->count()-1; + + //Update current panels + for(int i=0; i<current_count; i++) { + PANELS[i]->LoadSettings(settings, cscreen, i); } - for(int i=0; i<panelnumber; i++){ + //Create new panels + for(int i=current_count; i<panelnumber; i++){ PanelWidget *tmp = new PanelWidget(ui->scroll_panels->widget(), this, PINFO); tmp->LoadSettings(settings, cscreen, i); PANELS << tmp; connect(tmp, SIGNAL(PanelChanged()), this, SLOT(panelValChanged()) ); connect(tmp, SIGNAL(PanelRemoved(int)), this, SLOT(removePanel(int)) ); - ui->scroll_panels->widget()->layout()->addWidget(tmp); + panels_layout->insertWidget(panels_layout->count()-1, tmp); } - static_cast<QHBoxLayout*>(ui->scroll_panels->widget()->layout())->addStretch(); QApplication::processEvents(); loading = false; diff --git a/src-qt5/core-utils/lumina-config/pages/page_mouse.cpp b/src-qt5/core-utils/lumina-config/pages/page_mouse.cpp deleted file mode 100644 index f4eebd0e..00000000 --- a/src-qt5/core-utils/lumina-config/pages/page_mouse.cpp +++ /dev/null @@ -1,217 +0,0 @@ -//=========================================== -// Lumina Desktop Source Code -// Copyright (c) 2016, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#include "page_mouse.h" -#include "ui_page_mouse.h" -#include "getPage.h" - -#include <QSpinBox> -#include <QDoubleSpinBox> - -//========== -// PUBLIC -//========== -page_mouse::page_mouse(QWidget *parent) : PageWidget(parent), ui(new Ui::page_mouse()){ - ui->setupUi(this); - devices = LInput::listDevices(); - //DEBUG Code - /*qDebug() << "List Devices:"; - for(int i=0; i<devices.length(); i++){ - if(!devices[i]->isPointer()){ - ::free( devices.takeAt(i)); - i--; - }else{ - qDebug() << "Found Pointer:" << devices[i]->devNumber(); - qDebug() << " - isExtension:" << devices[i]->isExtension(); - QList<int> props = devices[i]->listProperties(); - qDebug() << " - Properties:"; - for(int j=0; j<props.length(); j++){ - qDebug() << " --" <<devices[i]->propertyName(props[j])+" ("+QString::number(props[j])+")" <<" = " << devices[i]->getPropertyValue(props[j]); - } - } - }*/ - generateUI(); -} - -page_mouse::~page_mouse(){ - for(int i=0; i<devices.length(); i++){ ::free(devices[i]); } -} - -//================ -// PUBLIC SLOTS -//================ -void page_mouse::SaveSettings(){ - - emit HasPendingChanges(false); -} - -void page_mouse::LoadSettings(int){ - emit HasPendingChanges(false); - emit ChangePageTitle( tr("Input Device Settings") ); - -} - -void page_mouse::updateIcons(){ - for(int i=0; i<ui->tabWidget->count(); i++){ - ui->tabWidget->setTabIcon( i, LXDG::findIcon( "input-"+ui->tabWidget->tabWhatsThis(i).section(":",0,0), "" ) ); - } -} - -//================= -// PRIVATE -//================= -void page_mouse::generateUI(){ - ui->tabWidget->clear(); //remove all tabs (just in case) - int mouse = 1; - int keyboard = 1; - qDebug() << "Devices Found:" << devices.length(); - for(int i=0; i<devices.length(); i++){ - QTreeWidget *tree = 0; - if(!devices[i]->isExtension() || devices[i]->isPointer()){ - if(devices[i]->isPointer() && devices[i]->listProperties().count() <4){ continue; } //filter out all the trivial/static mouse devices - //Make a new tab for this device - tree = new QTreeWidget(this); - tree->setHeaderHidden(true); - tree->setColumnCount(2); - connect(tree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(itemClicked(QTreeWidgetItem*,int)) ); - if(devices[i]->isPointer()){ - int tab = ui->tabWidget->addTab(tree, LXDG::findIcon("input-mouse",""), QString(tr("Mouse #%1")).arg(QString::number(mouse)) ); - ui->tabWidget->setTabWhatsThis(tab, "mouse:"+QString::number(devices[i]->devNumber())); - mouse++; - }else{ - int tab = ui->tabWidget->addTab(tree, LXDG::findIcon("input-keyboard",""), QString(tr("Keyboard #%1")).arg(QString::number(keyboard)) ); - ui->tabWidget->setTabWhatsThis(tab, "keyboard:"+QString::number(devices[i]->devNumber()) ); - keyboard++; - } - }else{ - //Find the associated tab for this extension device - int tab = 0; - QString type = devices[i]->isPointer() ? "mouse" : "keyboard"; - int num = devices[i]->devNumber(); - for(int t=ui->tabWidget->count()-1; t>0; t--){ - if(ui->tabWidget->tabWhatsThis(t).startsWith(type) && ui->tabWidget->tabWhatsThis(t).section(":",-1).toInt() < num ){ tab = t; break; } - } - tree = static_cast<QTreeWidget*>( ui->tabWidget->widget(tab) ); - } - if(tree!=0){ populateDeviceTree(tree, devices[i]); } - } -} - -void page_mouse::populateDeviceTree(QTreeWidget *tree, LInputDevice *device){ - QTreeWidgetItem *top = new QTreeWidgetItem(tree); - if(device->isExtension()){ - top->setText( 0, QString(tr("Extension Device #%1")).arg(QString::number(tree->topLevelItemCount())) ); - }else{ top->setText(0, tr("Master Device")); } - top->setWhatsThis(0, QString(device->isPointer() ? "mouse" : "keyboard")+":"+QString::number(device->devNumber()) ); //save this for later - top->setFirstColumnSpanned(true); - top->setExpanded(true); - tree->addTopLevelItem(top); - //Now add all the child properties to this item - QList<int> props = device->listProperties(); - for(int i=0; i<props.length(); i++){ - if(device->propertyName(props[i]).toLower().contains("matrix")){ continue; } //skip this one - can not change from UI and most people will never want to anyway - QTreeWidgetItem *tmp = new QTreeWidgetItem(top); - tmp->setWhatsThis(0, QString::number(props[i]) ); - tmp->setText(0, device->propertyName(props[i])); - top->addChild(tmp); - populateDeviceItemValue(tree, tmp, device->getPropertyValue(props[i]), QString::number(device->devNumber())+":"+QString::number(props[i]) ); - } - //Clean up the tree widget as needed - top->sortChildren(0, Qt::AscendingOrder); - tree->resizeColumnToContents(0); -} - -void page_mouse::populateDeviceItemValue(QTreeWidget *tree, QTreeWidgetItem *it, QVariant value, QString id){ - if(value.type()==QVariant::Int){ - //Could be a boolian - check the name for known "enable" states - if(value.toInt() < 2 && (it->text(0).toLower().contains("enable") || it->text(0).toLower().contains("emulation") || it->text(0)==("XTEST Device") ) ){ - //Just use a checkable column within the item - bool enabled = (value.toInt()==1); - it->setText(1,""); - it->setWhatsThis(1, "bool:"+id); - it->setCheckState(1, enabled ? Qt::Checked : Qt::Unchecked); - }else{ - //Use a QSpinBox - QSpinBox *box = new QSpinBox(); - box->setRange(0,100); - box->setValue( value.toInt() ); - box->setWhatsThis("int:"+id); - tree->setItemWidget(it, 1, box); - connect(box, SIGNAL(valueChanged(int)), this, SLOT(valueChanged()) ); - } - }else if(value.type()==QVariant::Double){ - //Use a QDoubleSpinBox - QDoubleSpinBox *box = new QDoubleSpinBox(); - box->setRange(0,1000); - box->setValue( value.toInt() ); - box->setWhatsThis("double:"+id); - tree->setItemWidget(it, 1, box); - connect(box, SIGNAL(valueChanged(double)), this, SLOT(valueChanged()) ); - - }else if(value.canConvert< QList<QVariant> >()){ - //Not Modifiable - just use the label in the item - QList<QVariant> list = value.toList(); - QStringList txtList; - for(int i=0; i<list.length(); i++){ txtList << list[i].toString(); } - it->setText(1, txtList.join(", ") ); - it->setToolTip(1, txtList.join(", ")); - }else if( value.canConvert<QString>() ){ - //Not Modifiable - just use the label in the item - it->setText(1, value.toString()); - } -} -//================= -// PRIVATE SLOTS -//================= -void page_mouse::valueChanged(){ - //Now get the currently focused widget - QWidget *foc = this->focusWidget(); - if(foc==0){ return; } - //qDebug() << "Focus Widget:" << foc->whatsThis(); - //Now pull out the value and device/property numbers - unsigned int dev = foc->whatsThis().section(":",1,1).toInt(); - int prop = foc->whatsThis().section(":",2,2).toInt(); - QVariant value; - if(foc->whatsThis().startsWith("int:")){ value.setValue( static_cast<QSpinBox*>(foc)->value() ); } - else if(foc->whatsThis().startsWith("double:")){ value.setValue( static_cast<QDoubleSpinBox*>(foc)->value() ); } - //Now change the property for the device - qDebug() << " - Device:" <<dev << "prop:" << prop << "value:" << value; - for(int i=0; i<devices.length(); i++){ - if(devices[i]->devNumber() == dev){ - bool ok = devices[i]->setPropertyValue(prop, value); - if(ok){ foc->setStyleSheet(""); } - else{ foc->setStyleSheet("background: red"); } - //qDebug() << " - Changed property:" << (ok ? "success" : "failure"); - break; - } - } -} - -void page_mouse::itemClicked(QTreeWidgetItem *it, int col){ - if(col!=1){ return; } //only care about value changes - if(it->whatsThis(1).isEmpty()){ return; }//not a checkable item - qDebug() << "item Clicked:" << it->whatsThis(1) << it->text(0); - //Now pull out the value and device/property numbers - unsigned int dev = it->whatsThis(1).section(":",1,1).toInt(); - int prop = it->whatsThis(1).section(":",2,2).toInt(); - QVariant value( (it->checkState(1)==Qt::Checked) ? 1 : 0 ); - //Now change the property for the device - qDebug() << " - Device:" <<dev << "prop:" << prop << "value:" << value; - for(int i=0; i<devices.length(); i++){ - if(devices[i]->devNumber() == dev){ - //Since this "clicked" signal can get sent out even if the value has not changed, go ahead and make sure we have a different value first - QVariant current = devices[i]->getPropertyValue(prop); - //qDebug() << " - Current Value:" << current; - if(value.toInt()!=current.toInt()){ - bool ok = devices[i]->setPropertyValue(prop, value); - //if(ok){ foc->setStyleSheet(""); } - //else{ foc->setStyleSheet("background: red"); } - qDebug() << " - Changed property:" << (ok ? "success" : "failure"); - } - break; - } - } -} diff --git a/src-qt5/core-utils/lumina-config/pages/page_mouse.h b/src-qt5/core-utils/lumina-config/pages/page_mouse.h deleted file mode 100644 index 5409a9c2..00000000 --- a/src-qt5/core-utils/lumina-config/pages/page_mouse.h +++ /dev/null @@ -1,43 +0,0 @@ -//=========================================== -// Lumina Desktop Source Code -// Copyright (c) 2016, Ken Moore -// Available under the 3-clause BSD license -// See the LICENSE file for full details -//=========================================== -#ifndef _LUMINA_CONFIG_PAGE_MOUSE_H -#define _LUMINA_CONFIG_PAGE_MOUSE_H -#include "../globals.h" -#include "PageWidget.h" - -#include <LInputDevice.h> -#include <QTreeWidgetItem> - -namespace Ui{ - class page_mouse; -}; - -class page_mouse : public PageWidget{ - Q_OBJECT -public: - page_mouse(QWidget *parent); - ~page_mouse(); - -public slots: - void SaveSettings(); - void LoadSettings(int screennum); - void updateIcons(); - -private: - Ui::page_mouse *ui; - QList<LInputDevice*> devices; - - void generateUI(); - void populateDeviceTree(QTreeWidget *tree, LInputDevice *device); - void populateDeviceItemValue(QTreeWidget *tree, QTreeWidgetItem *it, QVariant value, QString id); - -private slots: - void valueChanged(); - void itemClicked(QTreeWidgetItem*, int); - -}; -#endif diff --git a/src-qt5/core-utils/lumina-config/pages/page_mouse.ui b/src-qt5/core-utils/lumina-config/pages/page_mouse.ui deleted file mode 100644 index a6c2e53f..00000000 --- a/src-qt5/core-utils/lumina-config/pages/page_mouse.ui +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>page_mouse</class> - <widget class="QWidget" name="page_mouse"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>300</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTabWidget" name="tabWidget"> - <property name="iconSize"> - <size> - <width>32</width> - <height>32</height> - </size> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src-qt5/core-utils/lumina-config/pages/pages.pri b/src-qt5/core-utils/lumina-config/pages/pages.pri index 0ee5d561..89b9b010 100644 --- a/src-qt5/core-utils/lumina-config/pages/pages.pri +++ b/src-qt5/core-utils/lumina-config/pages/pages.pri @@ -51,9 +51,3 @@ FORMS += $${PWD}/page_main.ui \ $${PWD}/page_compton.ui # $${PWD}/page_bluetooth_trueos.ui # $${PWD}/page_mouse_trueos.ui - -!NO_XINPUT{ - HEADERS += $${PWD}/page_mouse.h - SOURCES += $${PWD}/page_mouse.cpp - FORMS += $${PWD}/page_mouse.ui -} diff --git a/src-qt5/core/libLumina/ExternalProcess.h b/src-qt5/core/libLumina/ExternalProcess.h index 1325247f..8329c361 100644 --- a/src-qt5/core/libLumina/ExternalProcess.h +++ b/src-qt5/core/libLumina/ExternalProcess.h @@ -13,17 +13,40 @@ #include <QProcess> #include <QString> +#include <QTimer> +#include <QApplication> class ExternalProcess : public QProcess{ Q_OBJECT +private: + bool cursorRestored; + private slots: + void resetCursor(){ + if(!cursorRestored){ + QApplication::restoreOverrideCursor(); + cursorRestored = true; + } + } + void processStarting(){ + if(!cursorRestored){ + QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); + QTimer::singleShot(15000, this, SLOT(resetCursor()) ); + } + } void processFinished(){ + if(!cursorRestored){ + QApplication::restoreOverrideCursor(); + cursorRestored = true; + } //Clean up this object this->deleteLater(); } + public: - ExternalProcess(QString logfile = "") : QProcess(){ + ExternalProcess(QString logfile = "", bool manageCursors = true) : QProcess(){ this->setProcessChannelMode(QProcess::MergedChannels); + cursorRestored = !manageCursors; if(logfile.isEmpty()){ this->setStandardOutputFile(QProcess::nullDevice()); }else{ @@ -32,6 +55,7 @@ public: //Setup the connection for automatic cleanup connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished()) ); } + ~ExternalProcess(){ /*if(this->state() == QProcess::Running){ this->detach(); //about to close down the QProcess - detach the other program so it can continue functioning normally. diff --git a/src-qt5/core/libLumina/LuminaRandR-X11.cpp b/src-qt5/core/libLumina/LuminaRandR-X11.cpp new file mode 100644 index 00000000..85251b64 --- /dev/null +++ b/src-qt5/core/libLumina/LuminaRandR-X11.cpp @@ -0,0 +1,206 @@ +//=========================================== +// Lumina-DE source code +// Copyright (c) 2017, Ken Moore +// Available under the 3-clause BSD license +// See the LICENSE file for full details +//=========================================== +#include "LuminaRandR.h" + +#include "xcb/randr.h" +#include "xcb/xcb_atom.h" + +#include <QDebug> +#include <QX11Info> + +static QString atomToName(xcb_atom_t atom){ + xcb_get_atom_name_reply_t *nreply = xcb_get_atom_name_reply(QX11Info::connection(), xcb_get_atom_name_unchecked(QX11Info::connection(), atom), NULL); + QString name = QString::fromLocal8Bit(xcb_get_atom_name_name(nreply), xcb_get_atom_name_name_length(nreply)); + free(nreply); + return name; +}; + +//More efficient method for converting lots of atoms to strings +static QStringList atomsToNames(xcb_atom_t *atoms, unsigned int num){ + //qDebug() << "atomsToNames:" << num; + QList< xcb_get_atom_name_cookie_t > cookies; + //qDebug() << " - Get cookies"; + for(unsigned int i=0; i<num; i++){ cookies << xcb_get_atom_name_unchecked(QX11Info::connection(), atoms[i]); } + QStringList names; + //qDebug() << " - Get names"; + for(int i=0; i<cookies.length(); i++){ + xcb_get_atom_name_reply_t *nreply = xcb_get_atom_name_reply(QX11Info::connection(), cookies[i], NULL); + if(nreply==0){ continue; } + names << QString::fromLocal8Bit(xcb_get_atom_name_name(nreply), xcb_get_atom_name_name_length(nreply)); + free(nreply); + } + return names; +}; + +class OutputDevice::p_objects{ +public: + xcb_atom_t monitor_atom; + QList<xcb_randr_output_t> outputs; //the actual output devices used by the monitor + +}; + +//Global Listing of Devices +QList<OutputDevice> OutputDevice::availableMonitors(){ + QList<OutputDevice> list; + //Get the list of monitors + xcb_randr_get_monitors_cookie_t cookie = xcb_randr_get_monitors_unchecked(QX11Info::connection(), QX11Info::appRootWindow(), 1); + xcb_randr_get_monitors_reply_t *reply = xcb_randr_get_monitors_reply(QX11Info::connection(), cookie, NULL); + if(reply==0){ + qDebug() << "Could not get monitor list"; + return list; + } + xcb_randr_monitor_info_iterator_t iter = xcb_randr_get_monitors_monitors_iterator(reply); + qDebug() << "Number of Monitors:" << xcb_randr_get_monitors_monitors_length(reply); + while(iter.rem>0){ + qDebug() << "Found Monitor:"; + //qDebug() << " Index:" << iter.index << "Rem:" << iter.rem; + QString name = atomToName(iter.data->name); + /*xcb_get_atom_name_reply_t *nreply = xcb_get_atom_name_reply(QX11Info::connection(), xcb_get_atom_name_unchecked(QX11Info::connection(), iter.data->name), NULL); + QString name = QString::fromLocal8Bit(xcb_get_atom_name_name(nreply), xcb_get_atom_name_name_length(nreply)); + free(nreply);*/ + + qDebug() << " - Name:" << iter.data->name << name; + qDebug() << " - Primary:" << (iter.data->primary == 1); + qDebug() << " - Automatic:" << (iter.data->automatic == 1); + qDebug() << " - nOutput:" << iter.data->nOutput; + qDebug() << " - Geometry:" << QRect(iter.data->x, iter.data->y, iter.data->width, iter.data->height); + qDebug() << " - Physical Size (mm):" << iter.data->width_in_millimeters << "x" << iter.data->height_in_millimeters; + qDebug() << " - Number of outputs:" << xcb_randr_monitor_info_outputs_length(iter.data); + xcb_randr_monitor_info_next(&iter); + } + + //Free up any objects we are done with + free(reply); + //Return the list + return list; +} + +//FUNCTIONS (do not use directly - use the static list function instead) +OutputDevice::OutputDevice(){ + enabled = false; + p_obj = new p_objects(); + p_obj->monitor_atom = 0; +} + +OutputDevice::~OutputDevice(){ + +} + +//Modification +bool OutputDevice::setAsPrimary(){ + if(isPrimary){ return true; } + if( !p_obj->outputs.isEmpty() ){ + xcb_randr_set_output_primary (QX11Info::connection(), QX11Info::appRootWindow(), p_obj->outputs[0]); + isPrimary = true; + } + return isPrimary; +} + +bool OutputDevice::disable(){ + if(p_obj->monitor_atom!=0){ + xcb_randr_delete_monitor(QX11Info::connection(), QX11Info::appRootWindow(), p_obj->monitor_atom); + p_obj->monitor_atom = 0; + return true; + } + return false; +} + +void OutputDevice::enable(QRect geom){ + //if no geom provided, will add as the right-most screen at optimal resolution + if(p_obj->monitor_atom!=0){ return; } + qDebug() << "Enable Monitor:" << geom; + +} + +void OutputDevice::changeResolution(QSize){ + +} + +OutputDeviceList::OutputDeviceList(){ + xcb_randr_get_screen_resources_reply_t *reply = xcb_randr_get_screen_resources_reply(QX11Info::connection(), + xcb_randr_get_screen_resources_unchecked(QX11Info::connection(), QX11Info::appRootWindow()), + NULL); + int outputnum = xcb_randr_get_screen_resources_outputs_length(reply); + qDebug() << "Probing Screen Resources:"; + qDebug() << " - Number of Outputs:" << outputnum; + qDebug() << " - Number of CRTC's:" << xcb_randr_get_screen_resources_crtcs_length(reply); + int mode_len =xcb_randr_get_screen_resources_modes_length(reply); + qDebug() << " - Modes:" << mode_len; + for(int m=0; m<mode_len; m++){ + xcb_randr_mode_info_t mode = xcb_randr_get_screen_resources_modes(reply)[m]; + qDebug() << " -- Mode:" << mode.id; + qDebug() << " - Size:" << mode.width <<"x"<<mode.height; + } + //qDebug() << " -- " << atomsToNames( (xcb_atom_t*) xcb_randr_get_screen_resources_modes(reply), xcb_randr_get_screen_resources_modes_length(reply) ); + qDebug() << " - Names:" << xcb_randr_get_screen_resources_names_length(reply); + //qDebug() << " -- " << atomsToNames( (xcb_atom_t*) xcb_randr_get_screen_resources_names(reply), xcb_randr_get_screen_resources_names_length(reply)); + for(int i=0; i<outputnum; i++){ + xcb_randr_output_t output = xcb_randr_get_screen_resources_outputs(reply)[i]; + //Now display the info about this output + xcb_randr_get_output_info_reply_t *info = xcb_randr_get_output_info_reply(QX11Info::connection(), + xcb_randr_get_output_info_unchecked(QX11Info::connection(), output, QX11Info::appTime()), + NULL); + qDebug() << "==== Output Information #"+QString::number(i); + + //Modes + qDebug() << "Number of Modes:" << xcb_randr_get_output_info_modes_length(info); + + + //Clones + qDebug() << "Number of Clones:" << xcb_randr_get_output_info_clones_length(info); + + //Names + int name_len = xcb_randr_get_output_info_name_length(info); + qDebug() << "Names:" << atomsToNames( (xcb_atom_t*) xcb_randr_get_output_info_name(info), name_len); + for(int n=0; n<name_len; n++){ + QString name = atomToName( xcb_randr_get_output_info_name(info)[n] ); + qDebug() << " -- " << name; + } + + //Properties + xcb_randr_list_output_properties_reply_t *pinfo = xcb_randr_list_output_properties_reply(QX11Info::connection(), + xcb_randr_list_output_properties_unchecked(QX11Info::connection(), output), + NULL); + int pinfo_len = xcb_randr_list_output_properties_atoms_length(pinfo); + qDebug() << "Properties:" << pinfo_len; + for(int p=0; p<pinfo_len; p++){ + xcb_atom_t atom = xcb_randr_list_output_properties_atoms(pinfo)[p]; + //Property Name + QString name = atomToName(atom); + //Property Value + xcb_randr_query_output_property_reply_t *pvalue = xcb_randr_query_output_property_reply(QX11Info::connection(), + xcb_randr_query_output_property_unchecked(QX11Info::connection(), output, atom), + NULL); + QStringList values = atomsToNames ( (xcb_atom_t*) xcb_randr_query_output_property_valid_values(pvalue), xcb_randr_query_output_property_valid_values_length(pvalue) ); //need to read values + /*for(int v=0; v<xcb_randr_query_output_property_valid_values_length(pvalue); v++){ + //values << QString::number(xcb_randr_query_output_property_valid_values(pvalue)[v] ); + values << atomToName( xcb_randr_query_output_property_valid_values(pvalue)[v] ); + }*/ + free(pvalue); + qDebug() << " -- " << name << "=" << values; + + } + free(pinfo); + + free(info); + } + + free(reply); +} + +OutputDeviceList::~OutputDeviceList(){ + +} + +//Simplification functions for dealing with multiple monitors +void OutputDeviceList::setPrimaryMonitor(QString id){ + +} + +void OutputDeviceList::disableMonitor(QString id){ + +} diff --git a/src-qt5/core/libLumina/LuminaRandR.cpp b/src-qt5/core/libLumina/LuminaRandR.cpp deleted file mode 100644 index eefc5aa8..00000000 --- a/src-qt5/core/libLumina/LuminaRandR.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "LuminaRandR.h" diff --git a/src-qt5/core/libLumina/LuminaRandR.h b/src-qt5/core/libLumina/LuminaRandR.h index 3cdff651..448c676d 100644 --- a/src-qt5/core/libLumina/LuminaRandR.h +++ b/src-qt5/core/libLumina/LuminaRandR.h @@ -1,35 +1,70 @@ //=========================================== // Lumina-DE source code -// Copyright (c) 2016, Ken Moore +// Copyright (c) 2017, Ken Moore // Available under the 3-clause BSD license // See the LICENSE file for full details //=========================================== // This class governs all the xcb/randr interactions // and provides simpler Qt-based functions for use elsewhere //=========================================== +#ifndef _LUMINA_LIBRARY_RANDR_MONITORS_H +#define _LUMINA_LIBRARY_RANDR_MONITORS_H //Qt includes #include <QSize> +#include <QString> +#include <QPoint> +#include <QRect> +#include <QList> -#include "xcb/randr.h" -class outputDevice{ +class OutputDevice{ public: QString id; //output ID bool enabled; + bool isPrimary; //Monitor Geometry QPoint geom; //geometry of monitor within session //Monitor Resolution QSize cRes; //current resolution of the monitor (could be different from geom.size() if panning is enabled) QList<QSize> availRes; //available resolutions supported by the monitor //Refresh Rate - int cHz; //current refresh rate - QList<int> availHz; //available refresh rates + //int cHz; //current refresh rate + //QList<int> availHz; //available refresh rates //Expand this later to include: // panning (current/possible) // rotation (current/possible) - //FUNCTIONS - - //Modification + //Global Listing of Devices + static QList<OutputDevice> availableMonitors(); + + //FUNCTIONS (do not use directly - use the static list function instead) + OutputDevice(); + ~OutputDevice(); + + //Modification + bool setAsPrimary(); + bool disable(); + void enable(QRect geom = QRect()); //if no geom provided, will add as the right-most screen at optimal resolution + void changeResolution(QSize); + + //Now define a simple public_objects class so that each implementation + // has a storage container for placing private objects as needed + class p_objects; + p_objects* p_obj; +}; + +class OutputDeviceList : public QList<OutputDevice>{ +public: + OutputDeviceList(); + ~OutputDeviceList(); + + //Simplification functions for dealing with multiple monitors + void setPrimaryMonitor(QString id); + void disableMonitor(QString id); + //void enableMonitor(QString id, + +private: + }; +#endif diff --git a/src-qt5/core/libLumina/LuminaRandR.pri b/src-qt5/core/libLumina/LuminaRandR.pri new file mode 100644 index 00000000..0812819f --- /dev/null +++ b/src-qt5/core/libLumina/LuminaRandR.pri @@ -0,0 +1,12 @@ +#include("$${PWD}/../../OS-detect.pri") + +QT *= x11extras + +#X11/XCB includes +LIBS *= -lxcb -lxcb-randr +SOURCES *= $${PWD}/LuminaRandR-X11.cpp + +#General API/Header +HEADERS *= $${PWD}/LuminaRandR.h + +INCLUDEPATH *= ${PWD} diff --git a/src-qt5/core/libLumina/LuminaX11.cpp b/src-qt5/core/libLumina/LuminaX11.cpp index a8016460..e9eb4b7c 100644 --- a/src-qt5/core/libLumina/LuminaX11.cpp +++ b/src-qt5/core/libLumina/LuminaX11.cpp @@ -1470,7 +1470,17 @@ void LXCB::WM_ICCCM_SetProtocols(WId win, LXCB::ICCCM_PROTOCOLS flags){ // _NET_SUPPORTED (Root) void LXCB::WM_Set_Root_Supported(){ //NET_WM standards (ICCCM implied - no standard way to list those) - xcb_atom_t list[] = {}; + xcb_atom_t list[] = {EWMH._NET_WM_NAME, + EWMH._NET_WM_ICON, + EWMH._NET_WM_ICON_NAME, + EWMH._NET_WM_DESKTOP, + /*_NET_WINDOW_TYPE (and all the various types)*/ + EWMH._NET_WM_WINDOW_TYPE, EWMH._NET_WM_WINDOW_TYPE_DESKTOP, EWMH._NET_WM_WINDOW_TYPE_DOCK, + EWMH._NET_WM_WINDOW_TYPE_TOOLBAR, EWMH._NET_WM_WINDOW_TYPE_MENU, EWMH._NET_WM_WINDOW_TYPE_UTILITY, + EWMH._NET_WM_WINDOW_TYPE_SPLASH, EWMH._NET_WM_WINDOW_TYPE_DIALOG, EWMH._NET_WM_WINDOW_TYPE_NORMAL, + EWMH._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, EWMH._NET_WM_WINDOW_TYPE_POPUP_MENU, EWMH._NET_WM_WINDOW_TYPE_TOOLTIP, + EWMH._NET_WM_WINDOW_TYPE_NOTIFICATION, EWMH._NET_WM_WINDOW_TYPE_COMBO, EWMH._NET_WM_WINDOW_TYPE_DND, + }; xcb_ewmh_set_supported(&EWMH, QX11Info::appScreen(), 0,list); } @@ -1609,7 +1619,23 @@ WId LXCB::WM_Get_Active_Window(){ } void LXCB::WM_Set_Active_Window(WId win){ - xcb_ewmh_set_active_window(&EWMH, QX11Info::appScreen(), win); + xcb_ewmh_set_active_window(&EWMH, QX11Info::appScreen(), win); + //Also send the active window a message to take input focus + //Send the window a WM_TAKE_FOCUS message + if(atoms.isEmpty()){ createWMAtoms(); } //need these atoms + xcb_client_message_event_t event; + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = win; + event.type = ATOMS[atoms.indexOf("WM_PROTOCOLS")]; + event.data.data32[0] = ATOMS[atoms.indexOf("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()); } // _NET_WORKAREA diff --git a/src-qt5/core/libLumina/LuminaX11.h b/src-qt5/core/libLumina/LuminaX11.h index 2c741111..2f66ce06 100644 --- a/src-qt5/core/libLumina/LuminaX11.h +++ b/src-qt5/core/libLumina/LuminaX11.h @@ -23,7 +23,6 @@ #include <QObject> #include <QFlags> - #include <xcb/xcb_ewmh.h> //SYSTEM TRAY STANDARD DEFINITIONS @@ -67,6 +66,18 @@ public: || width_inc>=0 || height_inc>=0 || min_aspect_num>=0 || min_aspect_den>=0 || max_aspect_num>=0 || max_aspect_den>=0 \ || base_width>=0 || base_height>=0 || win_gravity>0 ); } + bool validMaxSize(){ + return (max_width>0 && max_width>=min_width) && (max_height>0 && max_height>=min_height); + } + bool validMinSize(){ + return (min_width>0 && min_height>0); + } + bool validBaseSize(){ + return (base_width>0 && base_height>0); + } + bool validSize(){ //only check this if the base sizes are invalid (this is the old spec and should not be used any more) + return (x>0 && y>0); + } }; //simple data structure for passing around the XRANDR information diff --git a/src-qt5/core/libLumina/NativeWindow.cpp b/src-qt5/core/libLumina/NativeWindow.cpp new file mode 100644 index 00000000..bd42ecaa --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindow.cpp @@ -0,0 +1,37 @@ +//=========================================== +// 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" + +// === PUBLIC === +NativeWindow::NativeWindow(WId id) : QObject(){ + winid = id; + WIN = QWindow::fromWinId(winid); +} + +NativeWindow::~NativeWindow(){ + hash.clear(); + //WIN->deleteLater(); //This class only deals with Native windows which were created outside the app - they need to be cleaned up outside the app too +} + +WId NativeWindow::id(){ + return winid; +} + +QWindow* NativeWindow::window(){ + return WIN; +} + +QVariant NativeWindow::property(NativeWindow::Property prop){ + if(hash.contains(prop)){ return hash.value(prop); } + return QVariant(); //null variant +} + +void NativeWindow::setProperty(NativeWindow::Property prop, QVariant val){ + if(prop == NativeWindow::None){ return; } + hash.insert(prop, val); + emit PropertyChanged(prop, val); +} diff --git a/src-qt5/core/libLumina/NativeWindow.h b/src-qt5/core/libLumina/NativeWindow.h new file mode 100644 index 00000000..59b955c3 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindow.h @@ -0,0 +1,81 @@ +//=========================================== +// 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 <QString> +#include <QRect> +#include <QSize> +#include <QObject> +#include <QWindow> +#include <QHash> +#include <QVariant> + +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, /*null*/ + MinSize, /*QSize*/ + MaxSize, /*QSize*/ + Size, /*QSize*/ + GlobalPos, /*QPoint*/ + Title, /*QString*/ + ShortTitle, /*QString*/ + Icon, /*QIcon*/ + Name, /*QString*/ + Workspace, /*int*/ + States, /*QList<NativeWindow::State> : Current state of the window */ + WinTypes, /*QList<NativeWindow::Type> : Current type of window (typically does not change)*/ + WinActions, /*QList<NativeWindow::Action> : Current actions that the window allows (Managed/set by the WM)*/ + Active, /*bool*/ + Visible /*bool*/ + }; + + + NativeWindow(WId id); + ~NativeWindow(); + + WId id(); + QWindow* window(); + + QVariant property(NativeWindow::Property); + void setProperty(NativeWindow::Property, QVariant); + +private: + QHash <NativeWindow::Property, QVariant> hash; + QWindow *WIN; + WId winid; + +signals: + //General Notifications + void PropertyChanged(NativeWindow::Property, QVariant); + void WindowClosed(WId); + + //Action Requests (not automatically emitted - typically used to ask the WM to do something) + //Note: "WId" should be the NativeWindow id() + void RequestActivate(WId); //Activate the window + void RequestClose(WId); //Close the window + void RequestSetVisible(WId, bool); //Minimize/restore visiblility + void RequestSetGeometry(WId, QRect); //Register the location/size of the window + void RequestSetFrameExtents(WId, QList<int>); //Register the size of the frame around the window [Left,Right, Top,Bottom] in pixels + + // System Tray Icon Embed/Unembed Requests + //void RequestEmbed(WId, QWidget*); + //void RequestUnEmbed(WId, QWidget*); +}; +#endif diff --git a/src-qt5/core/libLumina/NativeWindow.pri b/src-qt5/core/libLumina/NativeWindow.pri new file mode 100644 index 00000000..4a585a06 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindow.pri @@ -0,0 +1,8 @@ + +# Files +SOURCES *= $${PWD}/NativeWindow.cpp + +HEADERS *= $${PWD}/NativeWindow.h + +INCLUDEPATH *= ${PWD} + diff --git a/src-qt5/core/libLumina/NativeWindowSystem.cpp b/src-qt5/core/libLumina/NativeWindowSystem.cpp new file mode 100644 index 00000000..c8e6d483 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindowSystem.cpp @@ -0,0 +1,221 @@ +//=========================================== +// 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 <QX11Info> +#include <QDebug> + +//XCB Library functions +#include <xcb/xcb_ewmh.h> + +//XCB Library includes +#include <xcb/xcb.h> +#include <xcb/xcb_atom.h> +#include <xcb/xproto.h> +#include <xcb/xcb_ewmh.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xcb_image.h> +#include <xcb/xcb_aux.h> +#include <xcb/composite.h> +#include <xcb/damage.h> + +//XLib includes (XCB Damage lib does not appear to register for damage events properly) +#include <X11/extensions/Xdamage.h> + +//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_REDIRECT | \ + 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) + +//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<QString, xcb_atom_t> 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(){ + QStringList atoms; + atoms << "WM_TAKE_FOCUS" << "WM_DELETE_WINDOW" << "WM_PROTOCOLS" << "WM_CHANGE_STATE" << "_NET_SYSTEM_TRAY_OPCODE" << "_NET_SYSTEM_TRAY_ORIENTATION" << "_NET_SYSTEM_TRAY_VISUAL" << QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(QX11Info::appScreen())); + //Create all the requests for the atoms + QList<xcb_intern_atom_reply_t*> reply; + for(int i=0; i<atoms.length(); i++){ + reply << xcb_intern_atom_reply(QX11Info::connection(), \ + xcb_intern_atom(QX11Info::connection(), 0, atoms[i].length(), atoms[i].toLocal8Bit()), NULL); + } + //Now evaluate all the requests and save the atoms + for(int i=0; i<reply.length(); i++){ //NOTE: this will always be the same length as the "atoms" list + if(reply[i]!=0){ + obj->ATOMS.insert(atoms[i], reply[i]->atom); + 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 (obj->ATOMS.keys.length() == atoms.length()); + } + + 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, \ + win, 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 startSystemTray{ + 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) + //TODO + } + +}; //end private objects class + + +//inline functions for setting up the internal objects + + +// === PUBLIC === +NativeWindowSystem::NativeWindowSystem() : QObject(){ + obj = 0; +} + +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 + + return true; +} + +void NativeWindowSystem::stop(){ + +} + +// === PRIVATE === +void NativeWindowSystem::UpdateWindowProperties(NativeWindow* win, QList< NativeWindow::Property > props){ + +} + +// === PUBLIC SLOTS === +//These are the slots which are only used by the desktop system itself or the NativeWindowEventFilter +void NativeWindowSystem::RegisterVirtualRoot(WId){ + +} + +//NativeWindowEventFilter interactions +void NativeWindowSystem::NewWindowDetected(WId){ + +} + +void NativeWindowSystem::WindowCloseDetected(WId){ + +} + +void NativeWindowSystem::WindowPropertyChanged(WId, NativeWindow::Property){ + +} + +void NativeWindowSystem::NewKeyPress(int keycode){ + +} + +void NativeWindowSystem::NewKeyRelease(int keycode){ + +} + +void NativeWindowSystem::NewMousePress(int buttoncode){ + +} + +void NativeWindowSystem::NewMouseRelease(int buttoncode){ + +} + +// === PRIVATE SLOTS === +//These are the slots which are built-in and automatically connected when a new NativeWindow is created +void NativeWindowSystem::RequestActivate(WId){ + +} +void NativeWindowSystem::RequestClose(WId){ + +} + +void NativeWindowSystem::RequestSetVisible(WId, bool){ + +} +void NativeWindowSystem::RequestSetGeometry(WId, QRect){ + +} +void NativeWindowSystem::RequestSetFrameExtents(WId, QList<int>){ + //[Left,Top,Right,Bottom] in pixels + +} diff --git a/src-qt5/core/libLumina/NativeWindowSystem.h b/src-qt5/core/libLumina/NativeWindowSystem.h new file mode 100644 index 00000000..ef169059 --- /dev/null +++ b/src-qt5/core/libLumina/NativeWindowSystem.h @@ -0,0 +1,92 @@ +//=========================================== +// 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" + +class NativeWindowSystem : public QObject{ + Q_OBJECT +private: + QList<NativeWindow*> NWindows; + QList<NativeWindow*> TWindows; + + //Simplifications to find an already-created window object + NativeWindow* findWindow(WId id){ + for(int i=0; i<NWindows.length(); i++){ + if(id==NWindows[i]->id()){ return NWindows[i]; } + } + } + + NativeWindow* findTrayWindow(WId id){ + for(int i=0; i<TWindows.length(); i++){ + if(id==TWindows[i]->id()){ return TWindows[i]; } + } + } + + //Now define a simple private_objects class so that each implementation + // has a storage container for placing private objects as needed + class p_objects; + p_objects* obj; + + // 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); + +public: + NativeWindowSystem(); + ~NativeWindowSystem(); + + //Overarching start/stop functions + bool start(); + void stop(); + + //General-purpose listing functions + QList<NativeWindow*> currentWindows(){ return NWindows; } + +public slots: + //These are the slots which are typically only used by the desktop system itself or the NativeWindowEventFilter + + //RootWindow interactions + void RegisterVirtualRoot(WId); + //void GoToWorkspace(int); + //void RegisterWorkspaces(QStringList); //Names of workspaces, in ascending order + //void RegisterKnownInteractions(); + + + //NativeWindowEventFilter interactions + void NewWindowDetected(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 NewKeyPress(int keycode); + void NewKeyRelease(int keycode); + void NewMousePress(int buttoncode); + void NewMouseRelease(int buttoncode); + void CheckDamageID(WId); + +private slots: + //These are the slots which are built-in and automatically connected when a new NativeWindow is created + void RequestActivate(WId); + void RequestClose(WId); + void RequestSetVisible(WId, bool); + void RequestSetGeometry(WId, QRect); + void RequestSetFrameExtents(WId, QList<int>); //[Left,Right,Top,Bottom] in pixels + +signals: + void NewWindowAvailable(NativeWindow*); + void NewInputEvent(); //a mouse or keypress was detected (lock-state independent); + void NewKeyPress(int); //only emitted if lockstate = false + void NewKeyRelease(int); //only emitted if lockstate = false + void NewMousePress(Qt::MouseButton); //only emitted if lockstate = false + +}; + +#endif diff --git a/src-qt5/core/libLumina/RootSubWindow.cpp b/src-qt5/core/libLumina/RootSubWindow.cpp new file mode 100644 index 00000000..7be89f48 --- /dev/null +++ b/src-qt5/core/libLumina/RootSubWindow.cpp @@ -0,0 +1,110 @@ +//=========================================== +// 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 <QDebug> + +// === PUBLIC === +RootSubWindow::RootSubWindow(QMdiArea *root, NativeWindow *win) : QMdiSubWindow(0){ + this->setAttribute(Qt::WA_DeleteOnClose); + //Create the QWindow and QWidget containers for the window + WIN = win; + closing = false; + WinWidget = QWidget::createWindowContainer( WIN->window(), this); + this->setWidget(WinWidget); + LoadProperties( QList< NativeWindow::Property>() << NativeWindow::WindowFlags << NativeWindow::Title << NativeWindow::Icon \ + << NativeWindow::MinSize << NativeWindow::MaxSize << NativeWindow::Size ); + //Hookup the signals/slots + connect(this, SIGNAL(aboutToActivate()), this, SLOT(aboutToActivate()) ); + connect(WIN, SIGNAL(PropertyChanged(NativeWindow::Property, QVariant)), this, SLOT(propertyChanged(NativeWindow::Property, QVariant))); + //Now add this window to the root QMdiArea + root->addSubWindow(this); + //Make sure the visibily property only gets loaded after it is added to the root area + propertyChanged(NativeWindow::Visible, WIN->property(NativeWindow::Visible)); +} + +RootSubWindow::~RootSubWindow(){ + +} + +WId RootSubWindow::id(){ + return WIN->id(); +} + +// === PRIVATE === +void RootSubWindow::LoadProperties( QList< NativeWindow::Property> list){ + for(int i=0; i<list.length(); i++){ + propertyChanged( list[i], WIN->property(list[i]) ); + } +} + +// === PUBLIC SLOTS === +void RootSubWindow::clientClosed(){ + qDebug() << "Client Closed"; + closing = true; + this->close(); +} + +void RootSubWindow::clientHidden(){ + qDebug() << "Client Hidden"; + this->hide(); +} + +void RootSubWindow::clientShown(){ + qDebug() << "Client Shown"; + this->show(); +} + +// === PRIVATE SLOTS === +void RootSubWindow::aboutToActivate(){ + WIN->emit RequestActivate(WIN->id()); +} + +void RootSubWindow::propertyChanged(NativeWindow::Property prop, QVariant val){ + if(val.isNull()){ return; } //not the same as a default/empty value - the property has just not been set yet + qDebug() << "Set Window Property:" << prop << val; + switch(prop){ + case NativeWindow::Visible: + if(val.toBool()){ clientShown(); } + else{ clientHidden(); } + break; + case NativeWindow::Title: + this->setWindowTitle(val.toString()); + break; + case NativeWindow::Icon: + this->setWindowIcon(val.value< QIcon>()); + break; + case NativeWindow::Size: + this->resize(val.toSize()); + break; + case NativeWindow::MinSize: + this->setMinimumSize(val.toSize()); + break; + case NativeWindow::MaxSize: + this->setMaximumSize(val.toSize()); + break; + case NativeWindow::Active: + if(val.toBool()){ this->mdiArea()->setActiveSubWindow(this); } + break; + case NativeWindow::WindowFlags: + this->setWindowFlags( val.value< Qt::WindowFlags >() ); + break; + default: + qDebug() << "Window Property Unused:" << prop << val; + } +} + +// === PROTECTED === +void RootSubWindow::closeEvent(QCloseEvent *ev){ + if(!closing){ + //qDebug() << "Close Window By Button:" << WIN->id(); + ev->ignore(); + WIN->emit RequestClose(WIN->id()); + }else{ + QMdiSubWindow::closeEvent(ev); + } + +} diff --git a/src-qt5/core/libLumina/RootSubWindow.h b/src-qt5/core/libLumina/RootSubWindow.h new file mode 100644 index 00000000..c56f3c96 --- /dev/null +++ b/src-qt5/core/libLumina/RootSubWindow.h @@ -0,0 +1,51 @@ +//=========================================== +// 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 <QMdiArea> +#include <QMdiSubWindow> +#include <QWindow> +#include <QWidget> +#include <QCloseEvent> + +#include <NativeWindow.h> + +class RootSubWindow : public QMdiSubWindow{ + Q_OBJECT +public: + RootSubWindow(QMdiArea *root, NativeWindow *win); + ~RootSubWindow(); + + WId id(); + +private: + NativeWindow *WIN; + QWidget *WinWidget; + bool closing; + + void LoadProperties( QList< NativeWindow::Property> list); + +public slots: + void clientClosed(); + +private slots: + void clientHidden(); + void clientShown(); + void aboutToActivate(); + void propertyChanged(NativeWindow::Property, QVariant); + + +protected: + void closeEvent(QCloseEvent*); + +}; + +#endif diff --git a/src-qt5/core/libLumina/RootWindow.cpp b/src-qt5/core/libLumina/RootWindow.cpp index aa5957b5..0758653b 100644 --- a/src-qt5/core/libLumina/RootWindow.cpp +++ b/src-qt5/core/libLumina/RootWindow.cpp @@ -11,7 +11,7 @@ #include <QDebug> // === PUBLIC === -RootWindow::RootWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){ +RootWindow::RootWindow() : QMdiArea(0){ //QWidget(0, Qt::Window | Qt::BypassWindowManagerHint | Qt::WindowStaysOnBottomHint){ qRegisterMetaType<WId>("WId"); autoResizeTimer = 0; } @@ -166,13 +166,32 @@ void RootWindow::ChangeWallpaper(QString id, RootWindow::ScaleType scale, QStrin } +void RootWindow::NewWindow(NativeWindow *win){ + RootSubWindow *subwin = 0; + for(int i=0; i<WINDOWS.length() && subwin==0; i++){ + if(WINDOWS[i]->id() == win->id()){ subwin = WINDOWS[i]; } + } + if(subwin==0){ + subwin = new RootSubWindow(this, win); + connect(win, SIGNAL(WindowClosed(WId)), this, SLOT(CloseWindow(WId)) ); + WINDOWS << subwin; + } + //subwin->show(); +} + +void RootWindow::CloseWindow(WId win){ + for(int i=0; i<WINDOWS.length(); i++){ + if(WINDOWS[i]->id() == win){ WINDOWS.takeAt(i)->clientClosed(); break; } + } +} + // === PRIVATE SLOTS === // === PROTECTED === void RootWindow::paintEvent(QPaintEvent *ev){ //qDebug() << "RootWindow: PaintEvent:" << ev->rect(); //<< QDateTime::currentDateTime()->toString(QDateTime::ShortDate); bool found = false; - QPainter painter(this); + QPainter painter(this->viewport()); for(int i=0; i<WALLPAPERS.length(); i++){ if(WALLPAPERS[i].area.intersects(ev->rect()) ){ found = true; diff --git a/src-qt5/core/libLumina/RootWindow.h b/src-qt5/core/libLumina/RootWindow.h index b371d239..5d3bc963 100644 --- a/src-qt5/core/libLumina/RootWindow.h +++ b/src-qt5/core/libLumina/RootWindow.h @@ -18,8 +18,12 @@ #include <QTimer> #include <QApplication> #include <QPaintEvent> +#include <QMdiArea> -class RootWindow : public QWidget{ +#include "RootSubWindow.h" +#include "NativeWindow.h" + +class RootWindow : public QMdiArea{ Q_OBJECT public: enum ScaleType{ SolidColor, Stretch, Full, Fit, Center, Tile, BottomLeft, BottomRight, BottomCenter, \ @@ -43,11 +47,17 @@ private: QList<screeninfo> WALLPAPERS; void updateScreenPixmap(screeninfo *info); //used for recalculating the wallpaper pixmap based on file/area/scale as needed + //Window Management + QList<RootSubWindow*> WINDOWS; + 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 NewWindow(NativeWindow*); + void CloseWindow(WId); //automatically connected for any new native window + private slots: protected: diff --git a/src-qt5/core/libLumina/RootWindow.pri b/src-qt5/core/libLumina/RootWindow.pri index 7ef3efb0..35e0e770 100644 --- a/src-qt5/core/libLumina/RootWindow.pri +++ b/src-qt5/core/libLumina/RootWindow.pri @@ -1,9 +1,13 @@ # Files -SOURCES *= $${PWD}/RootWindow.cpp -HEADERS *= $${PWD}/RootWindow.h +SOURCES *= $${PWD}/RootWindow.cpp \ + $${PWD}/RootSubWindow.cpp + +HEADERS *= $${PWD}/RootWindow.h \ + $${PWD}/RootSubWindow.h INCLUDEPATH *= ${PWD} -# include LUtils and LuminaX11 +# include other library dependencies include(LUtils.pri) +include(NativeWindow.pri); diff --git a/src-qt5/core/libLumina/test/main.cpp b/src-qt5/core/libLumina/test/main.cpp new file mode 100644 index 00000000..309fb938 --- /dev/null +++ b/src-qt5/core/libLumina/test/main.cpp @@ -0,0 +1,13 @@ + +#include "../LuminaRandR.h" +#include <QDebug> +#include <QApplication> + +int main(int argc, char** argv){ + QApplication A(argc, argv); + qDebug() << "Starting monitor scan..."; + QList<OutputDevice> outputs = OutputDevice::availableMonitors(); + qDebug() << "Finished monitor Scan"; + OutputDeviceList(); + return 0; +} diff --git a/src-qt5/core/libLumina/test/test.pro b/src-qt5/core/libLumina/test/test.pro new file mode 100644 index 00000000..9674801b --- /dev/null +++ b/src-qt5/core/libLumina/test/test.pro @@ -0,0 +1,7 @@ +QT = core gui widgets + +TARGET = test + +SOURCES += main.cpp + +include(../LuminaRandR.pri) diff --git a/src-qt5/core/lumina-desktop-unified/LSession.cpp b/src-qt5/core/lumina-desktop-unified/LSession.cpp index cb0144d5..1c8d3c45 100644 --- a/src-qt5/core/lumina-desktop-unified/LSession.cpp +++ b/src-qt5/core/lumina-desktop-unified/LSession.cpp @@ -24,11 +24,12 @@ RootWindow* Lumina::ROOTWIN = 0; XDGDesktopList* Lumina::APPLIST = 0; LShortcutEvents* Lumina::SHORTCUTS = 0; -LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lumina-desktop"){ +LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lumina-desktop-unified"){ //Initialize the global objects to null pointers mediaObj = 0; //private object used for playing login/logout chimes if(this->isPrimaryProcess()){ //Setup the global registrations + qsrand(QDateTime::currentMSecsSinceEpoch()); this->setApplicationName("Lumina Desktop Environment"); this->setApplicationVersion( LDesktopUtils::LuminaDesktopVersion() ); this->setOrganizationName("LuminaDesktopEnvironment"); @@ -41,7 +42,7 @@ LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lu //this->setAttribute(Qt::AA_UseHighDpiPixmaps); //allow pixmaps to be scaled up as well as down //Now initialize the global objects (but do not start them yet) - Lumina::EFILTER = new EventFilter(); //Need the XCB Event filter + Lumina::EFILTER = new EventFilter(); //Need the XCB Event filter first Lumina::SETTINGS = new DesktopSettings(); Lumina::SS = new LScreenSaver(); //Lumina::WM = new LWindowManager(); @@ -60,7 +61,7 @@ LSession::LSession(int &argc, char ** argv) : LSingleApplication(argc, argv, "lu //Setup the various connections between the global classes // NOTE: Most of these connections will only become "active" as the global objects get started during the setupSession routine connect(Lumina::ROOTWIN, SIGNAL(RegisterVirtualRoot(WId)), Lumina::EFILTER, SLOT(RegisterVirtualRoot(WId)) ); - + connect(Lumina::EFILTER, SIGNAL(WindowCreated(NativeWindow*)), Lumina::ROOTWIN, SLOT(NewWindow(NativeWindow*)) ); } //end check for primary process } @@ -176,7 +177,7 @@ void LSession::setupSession(){ Lumina::SHORTCUTS->start(); //Startup the shortcut handler now //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 //launchStartupApps(); - //QTimer::singleShot(500, this, SLOT(launchStartupApps()) ); + QTimer::singleShot(500, this, SLOT(launchStartupApps()) ); splash.hide(); LSession::processEvents(); splash.close(); @@ -279,7 +280,7 @@ void LSession::launchStartupApps(){ LOS::setScreenBrightness( tmp ); qDebug() << " - - Screen Brightness:" << QString::number(tmp)+"%"; } - QProcess::startDetached("nice lumina-open -autostart-apps"); + //ExternalProcess::launch("nice lumina-open -autostart-apps"); //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 diff --git a/src-qt5/core/lumina-desktop-unified/global-includes.h b/src-qt5/core/lumina-desktop-unified/global-includes.h index 6a753cd1..867076db 100644 --- a/src-qt5/core/lumina-desktop-unified/global-includes.h +++ b/src-qt5/core/lumina-desktop-unified/global-includes.h @@ -57,6 +57,8 @@ #include <LuminaSingleApplication.h> #include <DesktopSettings.h> #include <RootWindow.h> +#include <ExternalProcess.h> +#include <NativeWindow.h> // Standard C includes #include <unistd.h> diff --git a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro index 497ce635..1de8308d 100644 --- a/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro +++ b/src-qt5/core/lumina-desktop-unified/lumina-desktop.pro @@ -17,6 +17,7 @@ include(../libLumina/LuminaSingleApplication.pri) include(../libLumina/LuminaThemes.pri) include(../libLumina/DesktopSettings.pri) include(../libLumina/RootWindow.pri) +include(../libLumina/ExternalProcess.pri) #include all the main individual source groups include(src-screensaver/screensaver.pri) diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.cpp b/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.cpp index fa4af5ba..e363af01 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.cpp @@ -24,7 +24,7 @@ void DesktopContextMenu::UpdateMenu(){ for(int i=0; i<items.length(); i++){ if(items[i]=="terminal"){ this->addAction(LXDG::findIcon("utilities-terminal",""), tr("Terminal"))->setWhatsThis("lumina-open -terminal"); } else if(items[i]=="lockdesktop"){ this->addAction(LXDG::findIcon("system-lock-screen",""), tr("Lock Session"), this, SIGNAL(LockSession()) ); } - else if(items[i]=="filemanager"){ this->addAction( LXDG::findIcon("user-home",""), tr("Browse Files"))->setWhatsThis("lumina-open ~"); } + else if(items[i]=="filemanager"){ this->addAction( LXDG::findIcon("user-home",""), tr("Browse Files"))->setWhatsThis("lumina-open \""+QDir::homePath()+"\""); } //else if(items[i]=="applications"){ this->addMenu( LSession::handle()->applicationMenu() ); } else if(items[i]=="line"){ this->addSeparator(); } //else if(items[i]=="settings"){ this->addMenu( LSession::handle()->settingsMenu() ); } @@ -34,7 +34,7 @@ void DesktopContextMenu::UpdateMenu(){ QString file = items[i].section("::::",1,1).simplified(); XDGDesktop xdgf(file);// = LXDG::loadDesktopFile(file, ok); if(xdgf.type!=XDGDesktop::BAD){ - this->addAction( LXDG::findIcon(xdgf.icon,""), xdgf.name)->setWhatsThis(file); + this->addAction( LXDG::findIcon(xdgf.icon,""), xdgf.name)->setWhatsThis("lumina-open \""+file+"\""); }else{ qDebug() << "Could not load application file:" << file; } @@ -86,8 +86,9 @@ void DesktopContextMenu::start(){ // === PRIVATE SLOTS === void DesktopContextMenu::LaunchAction(QAction *act){ if(act->whatsThis().isEmpty() || act->parent()!=this ){ return; } + qDebug() << "Launch Menu Action:" << act->whatsThis(); QString cmd = act->whatsThis(); - emit LaunchApplication(cmd); + ExternalProcess::launch(cmd); } void DesktopContextMenu::showMenu(const QPoint &pt){ diff --git a/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.h b/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.h index 1a4befc9..8b0509fb 100644 --- a/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.h +++ b/src-qt5/core/lumina-desktop-unified/src-desktop/ContextMenu.h @@ -30,7 +30,6 @@ private slots: void showMenu(const QPoint&); signals: - void LaunchApplication(QString); //cmd to run void LockSession(); void showLeaveDialog(); }; diff --git a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp index 4a192aa4..7031f3df 100644 --- a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.cpp @@ -53,6 +53,7 @@ void EventFilter::start(){ XCB->setupEventsForRoot(WMFlag); XCB->WM_Set_Supporting_WM(WMFlag); + XCB->WM_Set_Root_Supported(); //announce all the various options that the WM supports static_cast<XCBEventFilter*>(EF)->startSystemTray(); QCoreApplication::instance()->flush(); @@ -71,11 +72,22 @@ unsigned int EventFilter::currentWorkspace(){ return XCB->CurrentWorkspace(); } +QList<NativeWindow*> EventFilter::currentWindows(){ + return static_cast<XCBEventFilter*>(EF)->windowList(); +} + // === PUBLIC SLOTS === void EventFilter::RegisterVirtualRoot(WId id){ XCB->WM_Set_Virtual_Roots( QList<WId>() << id ); } +void EventFilter::TryCloseWindow(WId id){ + XCB->WM_CloseWindow(id, false); //do not force close +} + +void EventFilter::TryActivateWindow(WId id){ + XCB->WM_Set_Active_Window(id); +} //============================= // XCBEventFilter Class //============================= @@ -132,13 +144,13 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag //============================== case XCB_KEY_PRESS: //This is a keyboard key press - qDebug() << "Key Press Event"; + //qDebug() << "Key Press Event"; stopevent = BlockInputEvent( ((xcb_key_press_event_t *) ev)->root ); //use the main "root" window - not the child widget if(!stopevent){ obj->emit KeyPressed( InputWindow(((xcb_key_press_event_t *) ev)->root), ((xcb_key_press_event_t *) ev)->detail ); } break; case XCB_KEY_RELEASE: //This is a keyboard key release - qDebug() << "Key Release Event"; + //qDebug() << "Key Release Event"; stopevent = BlockInputEvent( ((xcb_key_release_event_t *) ev)->root ); //use the main "root" window - not the child widget if(!stopevent){ obj->emit KeyReleased( InputWindow(((xcb_key_release_event_t *) ev)->root), ((xcb_key_release_event_t *) ev)->detail ); } break; @@ -183,25 +195,42 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag break; //============================== case XCB_MAP_NOTIFY: + //qDebug() << "Window Map Event:" << ((xcb_map_notify_event_t *)ev)->window; + if(Lumina::SS->isLocked()){ waitingToShow << ((xcb_map_notify_event_t *)ev)->window ; } + else{ + for(int i=0; i<windows.length(); i++){ + if(windows[i]->id() == ((xcb_map_notify_event_t *)ev)->window){ windows[i]->setProperty(NativeWindow::Visible, true); break; } + } + } 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 ModifyWindow( ((xcb_map_request_event_t *) ev)->window, Lumina::Show); + //qDebug() << "Window Map Request Event"; + SetupNewWindow( ((xcb_map_request_event_t *) ev) ); break; //============================== case XCB_CREATE_NOTIFY: - qDebug() << "Window Create Event"; + //qDebug() << "Window Create Event"; break; //============================== case XCB_UNMAP_NOTIFY: - qDebug() << "Window Unmap Event"; - obj->emit ModifyWindow( ((xcb_unmap_notify_event_t *)ev)->window, Lumina::Hide); + //qDebug() << "Window Unmap Event:" << ((xcb_unmap_notify_event_t *)ev)->window; + if(waitingToShow.contains(((xcb_unmap_notify_event_t *)ev)->window)){ waitingToShow.removeAll(((xcb_unmap_notify_event_t *)ev)->window); } + for(int i=0; i<windows.length(); i++){ + if(windows[i]->id() == ((xcb_unmap_notify_event_t *)ev)->window){ windows[i]->setProperty(NativeWindow::Visible, false); break; } + } break; //============================== case XCB_DESTROY_NOTIFY: - qDebug() << "Window Closed Event"; + //qDebug() << "Window Closed Event:" << ((xcb_destroy_notify_event_t *)ev)->window; if( !rmTrayApp( ((xcb_destroy_notify_event_t *) ev)->window ) ){ - obj->emit WindowClosed( ((xcb_destroy_notify_event_t *) ev)->window ); + //qDebug() <<" - Non-tray window"; + for(int i=0; i<windows.length(); i++){ + if(windows[i]->id() == ((xcb_destroy_notify_event_t *)ev)->window){ + windows[i]->emit WindowClosed(windows[i]->id()); + QTimer::singleShot(500, windows.takeAt(i), SLOT(deleteLater()) ); //give a few moments first, then clean up the object + break; + } + } } break; //============================== @@ -215,7 +244,7 @@ bool XCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *messag //============================== case XCB_PROPERTY_NOTIFY: //qDebug() << "Property Notify Event:"; - //qDebug() << " - Given Window:" << ((xcb_property_notify_event_t*)ev)->window; + ParsePropertyEvent((xcb_property_notify_event_t*)ev); break; //============================== case XCB_CLIENT_MESSAGE: @@ -305,6 +334,10 @@ bool XCBEventFilter::stopSystemTray(){ return true; } +QList<NativeWindow*> XCBEventFilter::windowList(){ + return windows; +} + //========= // PRIVATE //========= @@ -389,3 +422,79 @@ void XCBEventFilter::checkDamageID(WId id){ //Could check for window damage ID's - but we should not need this } } + +// WINDOW HANDLING FUNCTIONS +void XCBEventFilter::SetupNewWindow(xcb_map_request_event_t *ev){ + WId win = ev->window; + + bool ok = obj->XCB->WM_ManageWindow(win, true); + //Quick check if this is a transient window if we could not manage it directly + if(!ok){ + WId tran = obj->XCB->WM_ICCCM_GetTransientFor(win); + if(tran!=win && tran!=0){ + win = tran; + ok = obj->XCB->WM_ManageWindow(win); + } + } + qDebug() << "New Window:" << win << obj->XCB->WM_ICCCM_GetClass(win) << " Managed:" << ok; + obj->XCB->WM_Set_Active_Window(win); + //Determing the requested geometry/location/management within the event, + NativeWindow *nwin = new NativeWindow(win); + QObject::connect(nwin, SIGNAL(RequestClose(WId)), obj, SLOT(TryCloseWindow(WId)) ); + QObject::connect(nwin, SIGNAL(RequestActivate(WId)), obj, SLOT(TryActivateWindow(WId)) ); + windows << nwin; + bool show_now = !Lumina::SS->isLocked(); + if(!show_now){ waitingToShow << win; } //add to the list to get set visible later + //populate the native window settings as they are right now + nwin->setProperty(NativeWindow::Active, true); + nwin->setProperty(NativeWindow::Visible, show_now); + nwin->setProperty(NativeWindow::Workspace, obj->XCB->CurrentWorkspace()); + icccm_size_hints hints = obj->XCB->WM_ICCCM_GetNormalHints(win); + if(!hints.isValid()){ hints = obj->XCB->WM_ICCCM_GetSizeHints(win); } + if(hints.validMinSize()){ nwin->setProperty(NativeWindow::MinSize, QSize(hints.min_width,hints.min_height)); } + if(hints.validMaxSize()){ nwin->setProperty(NativeWindow::MaxSize, QSize(hints.max_width,hints.max_height)); } + if(hints.validBaseSize()){ nwin->setProperty(NativeWindow::Size, QSize(hints.base_width,hints.base_height)); } + else if(hints.validSize()){ nwin->setProperty(NativeWindow::Size, QSize(hints.width, hints.height)); } + nwin->setProperty(NativeWindow::Icon, obj->XCB->WM_Get_Icon(win)); + QString title = obj->XCB->WM_Get_Name(win); + if(title.isEmpty()){ title = obj->XCB->WM_Get_Visible_Name(win); } + if(title.isEmpty()){ title = obj->XCB->WM_ICCCM_GetName(win); } + nwin->setProperty(NativeWindow::Title, title); + title = obj->XCB->WM_Get_Icon_Name(win); + if(title.isEmpty()){ title = obj->XCB->WM_Get_Visible_Icon_Name(win); } + if(title.isEmpty()){ title = obj->XCB->WM_ICCCM_GetIconName(win); } + nwin->setProperty(NativeWindow::ShortTitle, title); + + obj->emit WindowCreated(nwin); +} + +void XCBEventFilter::ParsePropertyEvent(xcb_property_notify_event_t *ev){ + //First find the NativeWindow associated with the event + NativeWindow *nwin = 0; + for(int i=0; i<windows.length() && nwin==0; i++){ + if(windows[i]->id() == ev->window){ nwin = windows[i]; } + } + if(nwin==0){ return; } //unmanaged window - ignore this event + qDebug() << "Got Property Event:" << ev->window << ev->atom; + //Now determine which properties are getting changed, and update the native window as appropriate + if(ev->atom == obj->XCB->EWMH._NET_WM_NAME){ + qDebug() << " - Found _NET_WM_NAME atom"; + nwin->setProperty(NativeWindow::Title, obj->XCB->WM_Get_Name(nwin->id())); + }else if(ev->atom == obj->XCB->EWMH._NET_WM_ICON){ + qDebug() << " - Found _NET_WM_ICON atom"; + nwin->setProperty(NativeWindow::Icon, obj->XCB->WM_Get_Icon(nwin->id())); + }else if(ev->atom == obj->XCB->EWMH._NET_WM_ICON_NAME){ + qDebug() << " - Found _NET_WM_ICON_NAME atom"; + nwin->setProperty(NativeWindow::ShortTitle, obj->XCB->WM_Get_Icon_Name(nwin->id())); + }else if(ev->atom == obj->XCB->EWMH._NET_WM_DESKTOP){ + qDebug() << " - Found _NET_WM_DESKTOP atom"; + nwin->setProperty(NativeWindow::Workspace, obj->XCB->WM_Get_Desktop(nwin->id())); + }else if(ev->atom == obj->XCB->EWMH._NET_WM_WINDOW_TYPE ){ + qDebug() << " - Found _NET_WM_WINDOW_TYPE atom"; + + }else if( ev->atom == obj->XCB->EWMH._NET_WM_STATE){ + qDebug() << " - Found _NET_WM_STATE atom"; + + } + +} diff --git a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.h b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.h index 9e76ba53..9f2530e8 100644 --- a/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.h +++ b/src-qt5/core/lumina-desktop-unified/src-events/LXcbEventFilter.h @@ -60,18 +60,21 @@ public: //Public Session Interaction Functions unsigned int currentWorkspace(); + + //Public Window Management Lists + QList<NativeWindow*> currentWindows(); //always returned in creation-order (oldest first) //Variables/Functions needed by the XCBEventFilter class only (not really needed by anything else) LXCB *XCB; //used to interact with the X11 graphics subsystem public slots: void RegisterVirtualRoot(WId); + void TryCloseWindow(WId); + void TryActivateWindow(WId); signals: void NewInputEvent(); - void NewManagedWindow(WId); - void WindowClosed(WId); - void ModifyWindow(WId win, Lumina::WindowAction); + void WindowCreated(NativeWindow*); // Session Signals void WorkspaceChanged(unsigned int); @@ -99,6 +102,9 @@ public: bool startSystemTray(); bool stopSystemTray(); + //Window List Functions + QList<NativeWindow*> windowList(); + private: EventFilter *obj; QList<xcb_atom_t> WinNotifyAtoms, SysNotifyAtoms; @@ -119,13 +125,19 @@ private: bool rmTrayApp(WId); //returns "true" if the tray app was found and removed void checkDamageID(WId); + //Window List Variables + QList<NativeWindow*> windows; + QList<WId> waitingToShow; + //Longer Event handling functions + void SetupNewWindow(xcb_map_request_event_t *ev); + //bool ParseKeyPressEvent(); //bool ParseKeyReleaseEvent(); //bool ParseButtonPressEvent(); //bool ParseButtonReleaseEvent(); //bool ParseMotionEvent(); - //bool ParsePropertyEvent(); + void ParsePropertyEvent(xcb_property_notify_event_t *ev); //bool ParseClientMessageEvent(); //bool ParseDestroyEvent(); //bool ParseConfigureEvent(); 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 83b82ff8..9ad31f5c 100644 --- a/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp +++ b/src-qt5/core/lumina-desktop-unified/src-screensaver/SSBaseWidget.cpp @@ -19,6 +19,7 @@ SSBaseWidget::SSBaseWidget(QWidget *parent, QSettings *set) : QWidget(parent){ this->setObjectName("LuminaBaseSSWidget"); ANIM = 0; this->setMouseTracking(true); + plugType="none"; } SSBaseWidget::~SSBaseWidget(){ @@ -51,7 +52,7 @@ void SSBaseWidget::startPainting(){ //Now list all the various plugins and start them appropriately QString style; if(cplug=="none"){ - style = "background: transparent;"; //show the underlying black parent widget + style = "background: black;"; //show the underlying black parent widget }else{ style = "background: black;"; } diff --git a/src-qt5/core/lumina-desktop/LDesktop.cpp b/src-qt5/core/lumina-desktop/LDesktop.cpp index d4ebaa7f..92cef4d1 100644 --- a/src-qt5/core/lumina-desktop/LDesktop.cpp +++ b/src-qt5/core/lumina-desktop/LDesktop.cpp @@ -265,7 +265,7 @@ void LDesktop::SettingsChanged(){ UpdatePanels(); UpdateMenu(); issyncing = false; - QTimer::singleShot(100, this, SLOT(UnlockSettings()) ); //give it a few moments to settle before performing another sync + QTimer::singleShot(50, this, SLOT(UnlockSettings()) ); //give it a few moments to settle before performing another sync } void LDesktop::LocaleChanged(){ @@ -456,7 +456,7 @@ void LDesktop::UpdatePanels(){ } } //Give it a 1/2 second before ensuring that the visible desktop area is correct - QTimer::singleShot(500, this, SLOT(UpdateDesktopPluginArea()) ); + QTimer::singleShot(1500, this, SLOT(UpdateDesktopPluginArea()) ); } void LDesktop::UpdateDesktopPluginArea(){ @@ -484,7 +484,8 @@ void LDesktop::UpdateDesktopPluginArea(){ } //Now make sure the desktop plugin area is only the visible area QRect rec = visReg.boundingRect(); - //qDebug() << " - DPArea: Panel-Adjusted rectangle:" << rec; +// QRect rec = LSession::desktop()->availableGeometry(Screen()); + qDebug() << " - DPArea: Panel-Adjusted rectangle:" << rec; //LSession::handle()->XCB->SetScreenWorkArea((unsigned int) Screen(), rec); //Now remove the X offset to place it on the current screen (needs widget-coords, not global) globalWorkRect = rec; //save this for later diff --git a/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp b/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp index 18126dfa..75e4affc 100644 --- a/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp +++ b/src-qt5/core/lumina-desktop/LDesktopPluginSpace.cpp @@ -325,8 +325,9 @@ void LDesktopPluginSpace::reloadPlugins(bool ForceIconUpdate ){ void LDesktopPluginSpace::paintEvent(QPaintEvent*ev){ if(!wallpaper.isNull()){ QPainter painter(this); - painter.setBrush(wallpaper); - painter.drawRect(ev->rect().adjusted(-1,-1,2,2)); + //painter.setBrush(wallpaper); + //painter.drawRect(ev->rect().adjusted(-1,-1,2,2)); + painter.drawPixmap(ev->rect(), wallpaper, ev->rect() ); }else{ QWidget::paintEvent(ev); } diff --git a/src-qt5/core/lumina-desktop/i18n/lumina-desktop_de.ts b/src-qt5/core/lumina-desktop/i18n/lumina-desktop_de.ts index b9d1e7c5..2935b900 100644 --- a/src-qt5/core/lumina-desktop/i18n/lumina-desktop_de.ts +++ b/src-qt5/core/lumina-desktop/i18n/lumina-desktop_de.ts @@ -6,7 +6,7 @@ <message> <location filename="../panel-plugins/applauncher/AppLaunchButton.cpp" line="37"/> <source>Click to assign an application</source> - <translation>Klicke um Programm zuzuweisen</translation> + <translation>Klicken Sie, um eine Anwendung zuzuweisen</translation> </message> <message> <location filename="../panel-plugins/applauncher/AppLaunchButton.cpp" line="42"/> @@ -16,7 +16,7 @@ <message> <location filename="../panel-plugins/applauncher/AppLaunchButton.cpp" line="49"/> <source>Open %1</source> - <translation>Öffne %1</translation> + <translation>%1 öffnen</translation> </message> <message> <location filename="../panel-plugins/applauncher/AppLaunchButton.cpp" line="67"/> @@ -146,17 +146,17 @@ <message> <location filename="../BootSplash.ui" line="94"/> <source>Starting the Lumina Desktop...</source> - <translation type="unfinished"></translation> + <translation>Lumina-Arbeitsfläche wird gestartet...</translation> </message> <message> <location filename="../BootSplash.cpp" line="15"/> <source>Version %1</source> - <translation type="unfinished"></translation> + <translation>Version %1</translation> </message> <message> <location filename="../BootSplash.cpp" line="39"/> <source>This desktop is powered by coffee, coffee, and more coffee.</source> - <translation type="unfinished"></translation> + <translation>Diese Arbeitsfläche wird durch Kaffee, Kaffee und mehr Kaffee angetrieben.</translation> </message> <message> <location filename="../BootSplash.cpp" line="41"/> @@ -181,12 +181,12 @@ <message> <location filename="../BootSplash.cpp" line="49"/> <source>This desktop is generously sponsored by iXsystems</source> - <translation type="unfinished"></translation> + <translation>Diese Arbeitsfläche wird großzügig von iXsystems gesponsert</translation> </message> <message> <location filename="../BootSplash.cpp" line="51"/> <source>I have never been hurt by what I have not said</source> - <translation type="unfinished"></translation> + <translation>Ich bin niemals durch das verletzt worden, was ich nicht gesagt habe</translation> </message> <message> <location filename="../BootSplash.cpp" line="53"/> @@ -196,17 +196,17 @@ <message> <location filename="../BootSplash.cpp" line="55"/> <source>Everything has its beauty but not everyone sees it.</source> - <translation type="unfinished"></translation> + <translation>Alles hat seine Schönheit, aber nicht jeder sieht es.</translation> </message> <message> <location filename="../BootSplash.cpp" line="57"/> <source>Before God we are all equally wise - and equally foolish.</source> - <translation type="unfinished"></translation> + <translation>Vor Gott sind wir alle gleich weise - und gleich dumm.</translation> </message> <message> <location filename="../BootSplash.cpp" line="59"/> <source>We cannot do everything at once, but we can do something at once.</source> - <translation type="unfinished"></translation> + <translation>Wir können nicht alles auf einmal machen, aber wir können etwas auf einmal machen.</translation> </message> <message> <location filename="../BootSplash.cpp" line="61"/> @@ -215,13 +215,13 @@ </message> <message> <location filename="../BootSplash.cpp" line="63"/> - <source>Don't expect to build up the weak by pulling down the strong.</source> + <source>Don't expect to build up the weak by pulling down the strong.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../BootSplash.cpp" line="65"/> - <source>You can't know too much, but you can say too much.</source> - <translation type="unfinished"></translation> + <source>You can't know too much, but you can say too much.</source> + <translation>Sie können nicht zu viel wissen, aber Sie können zu viel sagen.</translation> </message> <message> <location filename="../BootSplash.cpp" line="67"/> @@ -236,12 +236,12 @@ <message> <location filename="../BootSplash.cpp" line="71"/> <source>Never trust a computer you can’t throw out a window.</source> - <translation type="unfinished"></translation> + <translation>Trauen Sie niemals einem Computer, den Sie nicht aus einem Fenster werfen können.</translation> </message> <message> <location filename="../BootSplash.cpp" line="73"/> <source>Study the past if you would define the future.</source> - <translation type="unfinished"></translation> + <translation>Studieren Sie die Vergangenheit, wenn Sie die Zukunft bestimmen würden.</translation> </message> <message> <location filename="../BootSplash.cpp" line="75"/> @@ -261,12 +261,12 @@ <message> <location filename="../BootSplash.cpp" line="81"/> <source>A person who never made a mistake never tried anything new.</source> - <translation type="unfinished"></translation> + <translation>Eine Person, die nie einen Fehler gemacht hat, hat nie etwas Neues versucht.</translation> </message> <message> <location filename="../BootSplash.cpp" line="83"/> <source>It does not matter how slowly you go as long as you do not stop.</source> - <translation type="unfinished"></translation> + <translation>Es spielt keine Rolle, wie langsam Sie gehen, solange Sie nicht aufhören.</translation> </message> <message> <location filename="../BootSplash.cpp" line="85"/> @@ -291,17 +291,17 @@ <message> <location filename="../BootSplash.cpp" line="93"/> <source>The only way to do great work is to love what you do.</source> - <translation type="unfinished"></translation> + <translation>Der einzige Weg großartige Arbeit zu verrichten, ist zu lieben, was Sie machen.</translation> </message> <message> <location filename="../BootSplash.cpp" line="95"/> <source>Political correctness is tyranny with manners.</source> - <translation type="unfinished"></translation> + <translation>Politische Korrektheit ist Tyrannei mit Manieren.</translation> </message> <message> <location filename="../BootSplash.cpp" line="97"/> - <source>Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.</source> - <translation type="unfinished"></translation> + <source>Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.</source> + <translation>Nur zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber beim ersten bin ich mir nicht sicher.</translation> </message> <message> <location filename="../BootSplash.cpp" line="99"/> @@ -310,13 +310,13 @@ </message> <message> <location filename="../BootSplash.cpp" line="101"/> - <source>Do, or do not. There is no 'try'.</source> - <translation type="unfinished"></translation> + <source>Do, or do not. There is no 'try'.</source> + <translation>Machen oder nicht machen. Es gibt kein "Versuchen".</translation> </message> <message> <location filename="../BootSplash.cpp" line="103"/> <source>A mathematician is a device for turning coffee into theorems.</source> - <translation type="unfinished"></translation> + <translation>Ein Mathematiker ist ein Gerät, um Kaffee in Theoreme umzuwandeln.</translation> </message> <message> <location filename="../BootSplash.cpp" line="105"/> @@ -326,22 +326,22 @@ <message> <location filename="../BootSplash.cpp" line="107"/> <source>Black holes are where God divided by zero.</source> - <translation type="unfinished"></translation> + <translation>Schwarze Löcher sind, wo Gott durch Null geteilt hat.</translation> </message> <message> <location filename="../BootSplash.cpp" line="109"/> - <source>It's kind of fun to do the impossible.</source> - <translation type="unfinished"></translation> + <source>It's kind of fun to do the impossible.</source> + <translation>Es macht Spaß, das Unmögliche zu tun.</translation> </message> <message> <location filename="../BootSplash.cpp" line="111"/> <source>Knowledge speaks, but wisdom listens.</source> - <translation type="unfinished"></translation> + <translation>Wissen spricht, aber Weisheit hört zu.</translation> </message> <message> <location filename="../BootSplash.cpp" line="113"/> <source>A witty saying proves nothing.</source> - <translation type="unfinished"></translation> + <translation>Ein witziges Sprichwort beweist nichts.</translation> </message> <message> <location filename="../BootSplash.cpp" line="115"/> @@ -351,7 +351,7 @@ <message> <location filename="../BootSplash.cpp" line="117"/> <source>Well-timed silence hath more eloquence than speech.</source> - <translation type="unfinished"></translation> + <translation>Zeitlich gut angesetzte Stille hat mehr Sprachfertigkeit als eine Rede.</translation> </message> <message> <location filename="../BootSplash.cpp" line="119"/> @@ -361,12 +361,12 @@ <message> <location filename="../BootSplash.cpp" line="121"/> <source>The best way to predict the future is to invent it.</source> - <translation type="unfinished"></translation> + <translation>Der beste Weg, die Zukunft vorauszusagen, ist, sie zu erfinden.</translation> </message> <message> <location filename="../BootSplash.cpp" line="123"/> <source>Well done is better than well said.</source> - <translation type="unfinished"></translation> + <translation>Gut gemacht ist besser als gut gesagt.</translation> </message> <message> <location filename="../BootSplash.cpp" line="125"/> @@ -376,7 +376,7 @@ <message> <location filename="../BootSplash.cpp" line="127"/> <source>The truth is more important than the facts.</source> - <translation type="unfinished"></translation> + <translation>Die Wahrheit ist wichtiger als die Fakten.</translation> </message> <message> <location filename="../BootSplash.cpp" line="129"/> @@ -642,7 +642,7 @@ <message> <location filename="../desktop-plugins/LDPlugin.cpp" line="38"/> <source>Launch Item</source> - <translation type="unfinished"></translation> + <translation>Element starten</translation> </message> <message> <location filename="../desktop-plugins/LDPlugin.cpp" line="42"/> @@ -738,7 +738,7 @@ <message> <location filename="../LDesktop.cpp" line="292"/> <source>Lock Session</source> - <translation type="unfinished"></translation> + <translation>Sitzung sperren</translation> </message> <message> <location filename="../LDesktop.cpp" line="293"/> @@ -982,7 +982,7 @@ <message> <location filename="../panel-plugins/audioplayer/PPlayerWidget.ui" line="14"/> <source>Form</source> - <translation type="unfinished"></translation> + <translation>Formular</translation> </message> <message> <location filename="../panel-plugins/audioplayer/PPlayerWidget.cpp" line="69"/> @@ -1264,7 +1264,7 @@ <message> <location filename="../SettingsMenu.cpp" line="33"/> <source>Wallpaper</source> - <translation type="unfinished"></translation> + <translation>Hintergrundbild</translation> </message> <message> <location filename="../SettingsMenu.cpp" line="36"/> @@ -1274,7 +1274,7 @@ <message> <location filename="../SettingsMenu.cpp" line="39"/> <source>All Desktop Settings</source> - <translation type="unfinished"></translation> + <translation>Alle Arbeitsflächeneinstellungen</translation> </message> <message> <location filename="../SettingsMenu.cpp" line="54"/> diff --git a/src-qt5/core/lumina-desktop/i18n/lumina-desktop_it.ts b/src-qt5/core/lumina-desktop/i18n/lumina-desktop_it.ts index 26c14237..8dac2274 100644 --- a/src-qt5/core/lumina-desktop/i18n/lumina-desktop_it.ts +++ b/src-qt5/core/lumina-desktop/i18n/lumina-desktop_it.ts @@ -221,7 +221,7 @@ <message> <location filename="../BootSplash.cpp" line="65"/> <source>You can't know too much, but you can say too much.</source> - <translation type="unfinished"></translation> + <translation>Non puoi sapere troppo, ma puoi dire troppo.</translation> </message> <message> <location filename="../BootSplash.cpp" line="67"/> diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp index 0dd68bb0..ab4e786f 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp @@ -16,7 +16,6 @@ LTaskButton::LTaskButton(QWidget *parent, bool smallDisplay) : LTBWidget(parent) winMenu = new QMenu(this); UpdateMenus(); showText = !smallDisplay; - this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setAutoRaise(false); //make sure these always look like buttons this->setContextMenuPolicy(Qt::CustomContextMenu); this->setFocusPolicy(Qt::NoFocus); @@ -126,16 +125,15 @@ void LTaskButton::UpdateButton(){ QString txt = WINLIST[0].text(); if(txt.length()>30){ txt.truncate(27); txt.append("..."); } else if(txt.length()<30){ txt = txt.leftJustified(30, ' '); } - this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText(txt); - }else if(noicon){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( cname ); } - else{ this->setToolButtonStyle(Qt::ToolButtonIconOnly); this->setText(""); } + this->setText(txt); + }else if(noicon){ this->setText( cname ); } + else{ this->setText(""); } this->setToolTip(WINLIST[0].text()); }else if(WINLIST.length() > 1){ //multiple windows this->setPopupMode(QToolButton::InstantPopup); this->setMenu(winMenu); - this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - if(noicon || showText){ "("+QString::number(WINLIST.length())+") "+cname; } + if(noicon || showText){ this->setText("("+QString::number(WINLIST.length())+") "+cname); } else{ this->setText("("+QString::number(WINLIST.length())+")"); } } this->setState(showstate); //Make sure this is after the button setup so that it properly sets the margins/etc diff --git a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp index 79c5dd36..c8e24702 100644 --- a/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp +++ b/src-qt5/core/lumina-desktop/panel-plugins/taskmanager/LTaskManagerPlugin.cpp @@ -116,8 +116,10 @@ void LTaskManagerPlugin::UpdateButtons(){ but->addWindow( winlist[i] ); if(this->layout()->direction()==QBoxLayout::LeftToRight){ but->setIconSize(QSize(this->height(), this->height())); + but->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); }else{ but->setIconSize(QSize(this->width(), this->width())); + but->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); } this->layout()->addWidget(but); connect(but, SIGNAL(MenuClosed()), this, SIGNAL(MenuClosed())); diff --git a/src-qt5/core/lumina-open/LFileDialog.cpp b/src-qt5/core/lumina-open/LFileDialog.cpp index a0fef17c..a400c60b 100644 --- a/src-qt5/core/lumina-open/LFileDialog.cpp +++ b/src-qt5/core/lumina-open/LFileDialog.cpp @@ -161,11 +161,13 @@ void LFileDialog::generateAppList(bool shownetwork){ XDGDesktopList applist; applist.updateList(); PREFAPPS = getPreferredApplications(); - //qDebug() << "Preferred Apps:" << PREFAPPS; + qDebug() << "Preferred Apps:" << PREFAPPS; ui->combo_rec->clear(); //Now get the application mimetype for the file extension (if available) QStringList mimetypes = LXDG::findAppMimeForFile(filePath, true).split("::::"); //use all mimetypes mimetypes.removeDuplicates(); + QString defapp = getDefaultApp(mimetypes.first()); //default application + if(!defapp.isEmpty() && !PREFAPPS.contains(defapp) ){ PREFAPPS << defapp; } //ensure this is listed in the preferred apps list //Now add all the detected applications QHash< QString, QList<XDGDesktop*> > hash = LXDG::sortDesktopCats( applist.apps(false,true) ); QStringList cat = hash.keys(); @@ -205,7 +207,9 @@ void LFileDialog::generateAppList(bool shownetwork){ for(int i=0; i<PREFAPPS.length(); i++){ XDGDesktop dFile(PREFAPPS[i]); if( dFile.isValid() ){ - ui->combo_rec->addItem( LXDG::findIcon(dFile.icon, "application-x-desktop"), dFile.name); + QString txt = dFile.name; + if(PREFAPPS[i] == defapp){ txt.prepend( tr("[default] ") ); } + ui->combo_rec->addItem( LXDG::findIcon(dFile.icon, "application-x-desktop"), txt); if(i==0){ ui->combo_rec->setCurrentIndex(0); } //make sure the first item is selected }else{ PREFAPPS.removeAt(i); //invalid app diff --git a/src-qt5/core/lumina-open/i18n/lumina-open_de.ts b/src-qt5/core/lumina-open/i18n/lumina-open_de.ts index 8af30d78..08e0bb7e 100644 --- a/src-qt5/core/lumina-open/i18n/lumina-open_de.ts +++ b/src-qt5/core/lumina-open/i18n/lumina-open_de.ts @@ -161,7 +161,7 @@ <message> <location filename="../main.cpp" line="264"/> <source>Application entry is invalid: %1</source> - <translation type="unfinished"></translation> + <translation>Anwendungseintrag ist ungültig: %1</translation> </message> <message> <location filename="../main.cpp" line="273"/> @@ -171,17 +171,17 @@ <message> <location filename="../main.cpp" line="284"/> <source>URL shortcut is missing the URL: %1</source> - <translation>fehlende URL für URL: %1</translation> + <translation>URL-Verknüpfung fehlt die URL: %1</translation> </message> <message> <location filename="../main.cpp" line="295"/> <source>Directory shortcut is missing the path to the directory: %1</source> - <translation>fehlender Pfad zum Verzeichnis der Verknüpfung: %1</translation> + <translation>Verzeichnisverknüpfung fehlt der Pfad zum Verzeichnis: %1</translation> </message> <message> <location filename="../main.cpp" line="300"/> <source>Unknown type of shortcut : %1</source> - <translation>unbekannter Typ für Vernüpfung: %1</translation> + <translation>Unbekannter Typ für Vernüpfung: %1</translation> </message> <message> <location filename="../main.cpp" line="363"/> @@ -190,8 +190,8 @@ </message> <message> <location filename="../main.cpp" line="363"/> - <source>Could not find "%1". Please ensure it is installed first.</source> - <translation>Konnte "%1" nicht finden. Bitte stellen Sie zuerst sicher, dass es installiert ist.</translation> + <source>Could not find "%1". Please ensure it is installed first.</source> + <translation>Konnte "%1" nicht finden. Bitte stellen Sie zuerst sicher, dass es installiert ist.</translation> </message> <message> <location filename="../main.cpp" line="413"/> diff --git a/src-qt5/core/lumina-open/i18n/lumina-open_it.ts b/src-qt5/core/lumina-open/i18n/lumina-open_it.ts index 341374d2..415476ca 100644 --- a/src-qt5/core/lumina-open/i18n/lumina-open_it.ts +++ b/src-qt5/core/lumina-open/i18n/lumina-open_it.ts @@ -26,7 +26,7 @@ <message> <location filename="../LFileDialog.ui" line="131"/> <source>Binary Location</source> - <translation type="unfinished">Posizione codice binario</translation> + <translation>Posizione codice binario</translation> </message> <message> <location filename="../LFileDialog.ui" line="138"/> diff --git a/src-qt5/core/lumina-session/main.cpp b/src-qt5/core/lumina-session/main.cpp index ed391e04..3696ed20 100644 --- a/src-qt5/core/lumina-session/main.cpp +++ b/src-qt5/core/lumina-session/main.cpp @@ -61,7 +61,9 @@ int main(int argc, char ** argv) //Check for any stale desktop lock files and clean them up QString cfile = QDir::tempPath()+"/.LSingleApp-%1-%2-%3"; - cfile = cfile.arg( QString(getlogin()), "lumina-desktop", QString::number(QX11Info::appScreen()) ); + QString desk = "lumina-desktop"; + if(unified){ desk.append("-unified"); } + cfile = cfile.arg( QString(getlogin()), desk, QString::number(QX11Info::appScreen()) ); if(QFile::exists(cfile)){ qDebug() << "Found Desktop Lock for X session:" << disp; qDebug() << " - Disabling Lock and starting new desktop session"; diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp index e465cdf8..2972550c 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.cpp @@ -42,6 +42,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ connect(ui->actionAdd_Dirs, SIGNAL(triggered()), this, SLOT(addDirs()) ); connect(ui->tree_contents, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(ViewFile(QTreeWidgetItem*)) ); connect(ui->actionUSB_Image, SIGNAL(triggered()), this, SLOT(BurnImgToUSB()) ); + connect(ui->tree_contents, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()) ); //Set Keyboard Shortcuts ui->action_New->setShortcut(tr("CTRL+N")); @@ -88,7 +89,7 @@ void MainUI::loadIcons(){ ui->actionAdd_Dirs->setIcon( LXDG::findIcon("archive-insert-directory","") ); ui->actionRemove_File->setIcon( LXDG::findIcon("archive-remove","") ); ui->actionExtract_All->setIcon( LXDG::findIcon("archive-extract","") ); - ui->actionExtract_Sel->setIcon( LXDG::findIcon("archive-extract","") ); + ui->actionExtract_Sel->setIcon( LXDG::findIcon("edit-select-all","") ); ui->actionUSB_Image->setIcon( LXDG::findIcon("drive-removable-media-usb-pendrive","drive-removable-media-usb") ); } @@ -112,6 +113,12 @@ QTreeWidgetItem* MainUI::findItem(QString path, QTreeWidgetItem *start){ } bool MainUI::cleanItems(QStringList list, QTreeWidgetItem *start){ + //Quick detection for an empty list + if(list.isEmpty() && ui->tree_contents->topLevelItemCount()>0){ + ui->tree_contents->clear(); + return true; + } + //Recursive resolution of items bool changed = false; if(start==0){ for(int i=0; i<ui->tree_contents->topLevelItemCount(); i++){ @@ -154,7 +161,7 @@ QString MainUI::CreateFileTypes(){ QString MainUI::OpenFileTypes(){ QStringList types; - types << QString(tr("All Types %1")).arg("(*.tar.gz *.tar.xz *.tar.bz *.tar.bz2 *.tar.lzma *.tar *.zip *.tgz *.txz *.tbz *.tbz2 *.tlz *.cpio *.pax *.ar *.shar *.7z *.iso *.img *.xar *.jar *.rpm)"); + types << QString(tr("All Known Types %1")).arg("(*.tar.gz *.tar.xz *.tar.bz *.tar.bz2 *.tar.lzma *.tar *.zip *.tgz *.txz *.tbz *.tbz2 *.tlz *.cpio *.pax *.ar *.shar *.7z *.iso *.img *.xar *.jar *.rpm)"); types << tr("Uncompressed Archive (*.tar)"); types << tr("GZip Compressed Archive (*.tar.gz *.tgz)"); types << tr("BZip Compressed Archive (*.tar.bz *.tbz)"); @@ -171,6 +178,7 @@ QString MainUI::OpenFileTypes(){ types << tr("READ-ONLY: XAR archive (*.xar)"); types << tr("READ-ONLY: Java archive (*.jar)"); types << tr("READ-ONLY: RedHat Package (*.rpm)"); + types << tr("Show All Files (*)"); return types.join(";;"); } @@ -340,7 +348,8 @@ void MainUI::ProcFinished(bool success, QString msg){ canmodify = canmodify && BACKEND->canModify(); //also include the file type limitations ui->actionAdd_File->setEnabled(canmodify); ui->actionRemove_File->setEnabled(canmodify && info.exists()); - ui->actionExtract_All->setEnabled(info.exists()); + ui->actionExtract_All->setEnabled(info.exists() && ui->tree_contents->topLevelItemCount()>0); + ui->actionExtract_Sel->setEnabled(info.exists() && !ui->tree_contents->selectedItems().isEmpty()); ui->actionAdd_Dirs->setEnabled(canmodify); } @@ -349,3 +358,7 @@ void MainUI::ProcUpdate(int percent, QString txt){ ui->progressBar->setValue(percent); if(!txt.isEmpty()){ ui->label_progress->setText(txt); } } + +void MainUI::selectionChanged(){ + ui->actionExtract_Sel->setEnabled(!ui->tree_contents->selectedItems().isEmpty()); +} diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.h b/src-qt5/desktop-utils/lumina-archiver/MainUI.h index bf37d26a..273078ea 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.h +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.h @@ -55,6 +55,8 @@ private slots: void ProcFinished(bool, QString); void ProcUpdate(int percent, QString txt); + //UI Slots + void selectionChanged(); }; #endif diff --git a/src-qt5/desktop-utils/lumina-archiver/MainUI.ui b/src-qt5/desktop-utils/lumina-archiver/MainUI.ui index 6666b7cb..0fc9eadf 100644 --- a/src-qt5/desktop-utils/lumina-archiver/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-archiver/MainUI.ui @@ -15,6 +15,15 @@ </property> <widget class="QWidget" name="centralwidget"> <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>3</number> + </property> + <property name="topMargin"> + <number>1</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> @@ -111,7 +120,7 @@ <x>0</x> <y>0</y> <width>403</width> - <height>22</height> + <height>20</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -168,6 +177,7 @@ <addaction name="actionRemove_File"/> <addaction name="separator"/> <addaction name="actionExtract_All"/> + <addaction name="actionExtract_Sel"/> </widget> <action name="action_Open"> <property name="text"> @@ -226,6 +236,9 @@ <property name="text"> <string>Extract Selection</string> </property> + <property name="statusTip"> + <string>Extract Selected Items</string> + </property> </action> <action name="actionUSB_Image"> <property name="text"> diff --git a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp index 78efd51c..0659f8b1 100644 --- a/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp +++ b/src-qt5/desktop-utils/lumina-archiver/TarBackend.cpp @@ -27,6 +27,7 @@ Backend::~Backend(){ // PUBLIC //=============== void Backend::loadFile(QString path){ + //qDebug() << "Loading Archive:" << path; filepath = path; tmpfilepath = filepath.section("/",0,-2)+"/"+".tmp_larchiver_"+filepath.section("/",-1); flags.clear(); @@ -149,7 +150,7 @@ void Backend::startViewFile(QString path){ args << "-x"; args << flags <<"--include" << path <<"--strip-components" << QString::number(path.count("/")) << "-C" << QDir::tempPath(); STARTING=true; - qDebug() << "Starting command:" << "tar" << args; + //qDebug() << "Starting command:" << "tar" << args; PROC.start("tar", args); } @@ -195,6 +196,7 @@ void Backend::startList(){ QStringList args; args << "-tv"; LIST = STARTING=true; + //qDebug() << "Starting List:" << "tar "+args.join(" ")+" "+flags.join(" "); PROC.start("tar", QStringList() << args << flags); } @@ -203,12 +205,17 @@ void Backend::startList(){ //=============== void Backend::procFinished(int retcode, QProcess::ExitStatus){ static QString result; - processData(); //qDebug() << "Process Finished:" << PROC.arguments() << retcode; + processData(); LIST = STARTING = false; if(PROC.arguments().contains("-tv")){ - if(retcode!=0){ contents.clear(); } //could not read archive - emit ProcessFinished(true,result); + if(retcode!=0){ //could not read archive + contents.clear(); + result = tr("Could not read archive"); + }else if(result.isEmpty()){ + result = tr("Archive Loaded"); + } + emit ProcessFinished((retcode==0), result); result.clear(); }else{ bool needupdate = true; diff --git a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp index da3943a2..45ec860a 100644 --- a/src-qt5/desktop-utils/lumina-fm/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-fm/MainUI.cpp @@ -118,7 +118,7 @@ MainUI::~MainUI(){ } workThread->quit(); //Also ensure the work thread is stopped - workThread->wait(); +// workThread->wait(); } void MainUI::OpenDirs(QStringList dirs){ diff --git a/src-qt5/desktop-utils/lumina-fm/i18n/lumina-fm_de.ts b/src-qt5/desktop-utils/lumina-fm/i18n/lumina-fm_de.ts index 84c07a5e..26942d93 100644 --- a/src-qt5/desktop-utils/lumina-fm/i18n/lumina-fm_de.ts +++ b/src-qt5/desktop-utils/lumina-fm/i18n/lumina-fm_de.ts @@ -94,7 +94,7 @@ <message> <location filename="../BrowserWidget.cpp" line="343"/> <source>Files: %1</source> - <translation type="unfinished"></translation> + <translation>Dateien: %1</translation> </message> <message> <location filename="../BrowserWidget.cpp" line="349"/> @@ -104,7 +104,7 @@ <message> <location filename="../BrowserWidget.cpp" line="363"/> <source>No Directory Contents</source> - <translation type="unfinished"></translation> + <translation>Kein Verzeichnisinhalt</translation> </message> </context> <context> @@ -118,12 +118,12 @@ <message> <location filename="../widgets/DirWidget2.ui" line="145"/> <source>Increase Icon Sizes</source> - <translation type="unfinished"></translation> + <translation>Symbolgrößen erhöhen</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="161"/> <source>Decrease Icon Sizes</source> - <translation type="unfinished"></translation> + <translation>Symbolgrößen verringern</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="179"/> @@ -134,7 +134,7 @@ <location filename="../widgets/DirWidget2.ui" line="182"/> <location filename="../widgets/DirWidget2.ui" line="185"/> <source>Go back to previous directory</source> - <translation>zurück zum vorhergehenden Verzeichnis</translation> + <translation>Zurück zum vorherigen Verzeichnis</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="193"/> @@ -161,32 +161,32 @@ <message> <location filename="../widgets/DirWidget2.ui" line="218"/> <source>Menu</source> - <translation type="unfinished"></translation> + <translation>Menü</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="221"/> <source>Select Action</source> - <translation type="unfinished"></translation> + <translation>Aktion auswählen</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="229"/> <source>SingleColumn</source> - <translation type="unfinished"></translation> + <translation>EinzelneSpalte</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="232"/> <source>Single column view</source> - <translation type="unfinished"></translation> + <translation>Einzelspaltenansicht</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="240"/> <source>Dual Column</source> - <translation type="unfinished"></translation> + <translation>Doppelspalte</translation> </message> <message> <location filename="../widgets/DirWidget2.ui" line="243"/> <source>Dual Column View</source> - <translation type="unfinished"></translation> + <translation>Doppelspaltenansicht</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="533"/> @@ -231,17 +231,17 @@ <message> <location filename="../widgets/DirWidget2.cpp" line="488"/> <source>File Operations</source> - <translation type="unfinished"></translation> + <translation>Dateioperationen</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="502"/> <source>Directory Operations</source> - <translation type="unfinished"></translation> + <translation>Verzeichnisoperationen</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="514"/> <source>Loading...</source> - <translation type="unfinished"></translation> + <translation>Ladevorgang...</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="563"/> @@ -268,7 +268,7 @@ <message> <location filename="../widgets/DirWidget2.cpp" line="229"/> <source>Create...</source> - <translation type="unfinished"></translation> + <translation>Erstellen...</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="231"/> @@ -278,22 +278,22 @@ <message> <location filename="../widgets/DirWidget2.cpp" line="232"/> <source>Directory</source> - <translation type="unfinished"></translation> + <translation>Verzeichnis</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="233"/> <source>Application Launcher</source> - <translation type="unfinished"></translation> + <translation>Anwendungsstarter</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="237"/> <source>Launch...</source> - <translation type="unfinished"></translation> + <translation>Starten...</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="239"/> <source>Terminal</source> - <translation type="unfinished"></translation> + <translation>Terminal</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="240"/> @@ -303,22 +303,22 @@ <message> <location filename="../widgets/DirWidget2.cpp" line="241"/> <source>Multimedia Player</source> - <translation type="unfinished"></translation> + <translation>Multimedia-Abspieler</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="256"/> <source>View Files...</source> - <translation type="unfinished"></translation> + <translation>Dateien ansehen...</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="258"/> <source>Checksums</source> - <translation type="unfinished"></translation> + <translation>Prüfsummen</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="260"/> <source>Properties</source> - <translation type="unfinished"></translation> + <translation>Eigenschaften</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="448"/> @@ -332,8 +332,8 @@ </message> <message> <location filename="../widgets/DirWidget2.cpp" line="460"/> - <source>The "lumina-fileinfo" utility could not be found on the system. Please install it first.</source> - <translation>Das "lumina-fileinfo" Dienstprogramm konnte nicht gefunden werden. Bitte erst installieren.</translation> + <source>The "lumina-fileinfo" utility could not be found on the system. Please install it first.</source> + <translation>Das "lumina-fileinfo" Dienstprogramm konnte nicht gefunden werden. Bitte erst installieren.</translation> </message> <message> <location filename="../widgets/DirWidget2.cpp" line="485"/> @@ -553,7 +553,7 @@ Neue Position: %2</translation> <message> <location filename="../gitWizard.ui" line="159"/> <source>Custom Depth</source> - <translation>Benutzerdefinierter Wert für "depth"</translation> + <translation>Benutzerdefinierter Wert für "depth"</translation> </message> <message> <location filename="../gitWizard.ui" line="166"/> @@ -567,8 +567,8 @@ Neue Position: %2</translation> </message> <message> <location filename="../gitWizard.ui" line="232"/> - <source>Click "Next" to start downloading the repository</source> - <translation>Auf "Weiter" klicken, um das Repository herunterzuladen</translation> + <source>Click "Next" to start downloading the repository</source> + <translation>Auf "Weiter" klicken, um das Repository herunterzuladen</translation> </message> <message> <location filename="../gitWizard.h" line="58"/> @@ -631,17 +631,17 @@ Neue Position: %2</translation> <message> <location filename="../MainUI.ui" line="171"/> <source>New Tab</source> - <translation type="unfinished"></translation> + <translation>Neue Registerkarte</translation> </message> <message> <location filename="../MainUI.ui" line="174"/> <source>New Browser</source> - <translation>neuer Browser</translation> + <translation>Neuer Browser</translation> </message> <message> <location filename="../MainUI.ui" line="250"/> <source>Search Directory...</source> - <translation>Suche im Verzeichnis...</translation> + <translation>Im Verzeichnis suchen...</translation> </message> <message> <location filename="../MainUI.ui" line="283"/> @@ -711,17 +711,17 @@ Neue Position: %2</translation> <message> <location filename="../MainUI.ui" line="403"/> <source>Close Tab</source> - <translation type="unfinished"></translation> + <translation>Registerkarte schließen</translation> </message> <message> <location filename="../MainUI.ui" line="414"/> <source>Repo Status</source> - <translation>Status des Repositorys</translation> + <translation>Repositoriumsstatus</translation> </message> <message> <location filename="../MainUI.ui" line="419"/> <source>Clone Repository</source> - <translation>Repository klonen</translation> + <translation>Repositorium klonen</translation> </message> <message> <location filename="../MainUI.ui" line="177"/> @@ -846,12 +846,12 @@ Neue Position: %2</translation> <message> <location filename="../MainUI.cpp" line="222"/> <source>CTRL+B</source> - <translation type="unfinished"></translation> + <translation>STRG+B</translation> </message> <message> <location filename="../MainUI.cpp" line="231"/> <source>CTRL+E</source> - <translation type="unfinished"></translation> + <translation>STRG+E</translation> </message> <message> <location filename="../MainUI.cpp" line="336"/> @@ -1018,37 +1018,37 @@ Neue Position: %2</translation> <message> <location filename="../OPWidget.ui" line="60"/> <source>Evaluating...</source> - <translation type="unfinished"></translation> + <translation>Auswertung...</translation> </message> <message> <location filename="../OPWidget.cpp" line="52"/> <source>Move</source> - <translation type="unfinished"></translation> + <translation>Verschieben</translation> </message> <message> <location filename="../OPWidget.cpp" line="53"/> <source>Copy</source> - <translation type="unfinished"></translation> + <translation>Kopieren</translation> </message> <message> <location filename="../OPWidget.cpp" line="54"/> <source>Remove</source> - <translation type="unfinished"></translation> + <translation>Entfernen</translation> </message> <message> <location filename="../OPWidget.cpp" line="96"/> <source>File Operation Errors</source> - <translation type="unfinished"></translation> + <translation>Dateioperationsfehler</translation> </message> <message> <location filename="../OPWidget.cpp" line="108"/> <source>%1 Finished</source> - <translation type="unfinished"></translation> + <translation>%1 abgeschlossen</translation> </message> <message> <location filename="../OPWidget.cpp" line="108"/> <source>Errors Occured</source> - <translation type="unfinished"></translation> + <translation>Fehler aufgetreten</translation> </message> </context> <context> @@ -1164,7 +1164,7 @@ Neue Position: %2</translation> <message> <location filename="../TrayUI.cpp" line="76"/> <source>Errors during operation. Click to view details</source> - <translation type="unfinished"></translation> + <translation>Fehler während des Vorgangs. Zum Anzeigen von Details klicken</translation> </message> </context> </TS> diff --git a/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp b/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp index 40c9857b..25f4cc62 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp +++ b/src-qt5/desktop-utils/lumina-screenshot/MainUI.cpp @@ -9,12 +9,15 @@ #include <LuminaX11.h> #include <QMessageBox> +#include <QClipboard> - -MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ +MainUI::MainUI() + : QMainWindow(), ui(new Ui::MainUI), + mousegrabbed(false), + picSaved(false), + closeOnSave(false) +{ ui->setupUi(this); //load the designer file - mousegrabbed = false; - picSaved = false; XCB = new LXCB(); IMG = new ImageEditor(this); ui->scrollArea->setWidget(IMG); @@ -30,7 +33,8 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ scaleTimer->setSingleShot(true); scaleTimer->setInterval(200); //~1/5 second tabbar = new QTabBar(this); - ui->tabLayout->insertWidget(0,tabbar); + tabbar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + ui->tabLayout->insertWidget(0,tabbar, Qt::AlignLeft | Qt::AlignBottom); tabbar->addTab(LXDG::findIcon("view-preview",""), tr("View")); tabbar->addTab(LXDG::findIcon("preferences-other",""), tr("Settings")); ui->stackedWidget->setCurrentWidget(ui->page_current); @@ -47,6 +51,7 @@ MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){ //connect(ui->push_snap, SIGNAL(clicked()), this, SLOT(startScreenshot()) ); connect(ui->actionTake_Screenshot, SIGNAL(triggered()), this, SLOT(startScreenshot()) ); connect(ui->tool_crop, SIGNAL(clicked()), IMG, SLOT(cropImage()) ); + connect(ui->tool_copy_to_clipboard, SIGNAL(clicked()), this, SLOT(copyToClipboard()) ); connect(IMG, SIGNAL(selectionChanged(bool)), this, SLOT(imgselchanged(bool)) ); connect(IMG, SIGNAL(scaleFactorChanged(int)), this, SLOT(imgScalingChanged(int)) ); connect(ui->slider_zoom, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged()) ); @@ -74,16 +79,14 @@ MainUI::~MainUI(){} void MainUI::setupIcons(){ //Setup the icons - //ui->tool_save->setIcon( LXDG::findIcon("document-save","") ); ui->tool_quicksave->setIcon( LXDG::findIcon("document-edit","") ); ui->actionSave_As->setIcon( LXDG::findIcon("document-save-as","") ); ui->actionQuick_Save->setIcon( LXDG::findIcon("document-save","") ); ui->actionClose->setIcon( LXDG::findIcon("application-exit","") ); - //ui->push_snap->setIcon( LXDG::findIcon("camera-web","") ); + ui->tool_copy_to_clipboard->setIcon( LXDG::findIcon("insert-image","") ); ui->actionTake_Screenshot->setIcon( LXDG::findIcon("camera-web","") ); ui->tool_crop->setIcon( LXDG::findIcon("transform-crop","") ); ui->tool_resize->setIcon( LXDG::findIcon("transform-scale","") ); - //ui->actionEdit->setIcon( LXDG::findIcon("applications-graphics","") ); this->setWindowIcon( LXDG::findIcon("camera-web","") ); } @@ -96,13 +99,22 @@ void MainUI::showSaveError(QString path){ void MainUI::saveScreenshot(){ if(mousegrabbed){ return; } QString filepath = QFileDialog::getSaveFileName(this, tr("Save Screenshot"), ppath+"/"+QString( "Screenshot-%1.png" ).arg( lastScreenShot.toString("yyyy-MM-dd-hh-mm-ss")), tr("PNG Files (*.png);;AllFiles (*)") ); - if(filepath.isEmpty()){ return; } + if(filepath.isEmpty()){ + closeOnSave = false; + return; + } if(!filepath.endsWith(".png")){ filepath.append(".png"); } if( !IMG->image().save(filepath, "png") ){ + closeOnSave = false; showSaveError(filepath); }else{ picSaved = true; ppath = filepath.section("/",0,-2); //just the directory + if (closeOnSave) { + // We came here from close, now we need to close *after* handling + // the current screen event. + QTimer::singleShot(0, this, SLOT(close())); + } } } @@ -121,6 +133,12 @@ void MainUI::quicksave(){ } } +void MainUI::copyToClipboard(){ + qDebug() << "Copy Image to clipboard"; + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setImage(IMG->image()); + qDebug() << " - Success:" << !clipboard->image().isNull(); +} void MainUI::startScreenshot(){ if(mousegrabbed){ return; } @@ -243,8 +261,18 @@ void MainUI::closeEvent(QCloseEvent *ev){ //qDebug() << "Close Event:" << ui->check_show_popups->isChecked() << picSaved; if(ui->check_show_popups->isChecked() && !picSaved){ //Ask what to do about the unsaved changed - if(QMessageBox::Yes != QMessageBox::warning(this, tr("Unsaved Screenshot"), tr("The current screenshot has not been saved yet. Do you want to quit anyway?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){ - //cancelled close of window + const int messageRet = QMessageBox::warning(this, tr("Unsaved Screenshot"), + tr("The current screenshot has not been saved yet. Do you want to save or discard your changes?"), + QMessageBox::Discard | QMessageBox::Save |QMessageBox::Cancel, QMessageBox::Cancel); + switch (messageRet) { + case QMessageBox::Discard: + // Just close, we don't care about the file. + break; + case QMessageBox::Save: + closeOnSave = true; + saveScreenshot(); + // fall through + case QMessageBox::Cancel: ev->ignore(); return; } diff --git a/src-qt5/desktop-utils/lumina-screenshot/MainUI.h b/src-qt5/desktop-utils/lumina-screenshot/MainUI.h index 396bfafe..4a18ef74 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/MainUI.h +++ b/src-qt5/desktop-utils/lumina-screenshot/MainUI.h @@ -41,7 +41,7 @@ public slots: private: Ui::MainUI *ui; - bool mousegrabbed, picSaved; + bool mousegrabbed, picSaved, closeOnSave; QRect lastgeom; QString ppath; //previous file path WId cwin; //current window to screenshot @@ -63,6 +63,7 @@ private slots: } void saveScreenshot(); void quicksave(); + void copyToClipboard(); void startScreenshot(); diff --git a/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui b/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui index cddee009..f4230ff6 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui +++ b/src-qt5/desktop-utils/lumina-screenshot/MainUI.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>386</width> - <height>288</height> + <width>480</width> + <height>318</height> </rect> </property> <property name="sizePolicy"> @@ -54,7 +54,7 @@ <item> <widget class="QFrame" name="frame_modify"> <property name="frameShape"> - <enum>QFrame::NoFrame</enum> + <enum>QFrame::StyledPanel</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> @@ -83,12 +83,44 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="statusTip"> + <string>Open screenshot with an application</string> + </property> <property name="text"> - <string>Open With...</string> + <string>Open</string> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonTextBesideIcon</enum> </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_copy_to_clipboard"> + <property name="statusTip"> + <string>Copy screenshot to clipboard</string> + </property> + <property name="text"> + <string>Copy</string> + </property> + <property name="shortcut"> + <string>Ctrl+C</string> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> </widget> </item> <item> @@ -99,12 +131,18 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="statusTip"> + <string>Resize screenshot to selection</string> + </property> <property name="text"> <string>Resize</string> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonTextBesideIcon</enum> </property> + <property name="autoRaise"> + <bool>true</bool> + </property> </widget> </item> <item> @@ -115,12 +153,18 @@ <verstretch>0</verstretch> </sizepolicy> </property> + <property name="statusTip"> + <string>Crop screenshot to selection</string> + </property> <property name="text"> <string>&Crop</string> </property> <property name="toolButtonStyle"> <enum>Qt::ToolButtonTextBesideIcon</enum> </property> + <property name="autoRaise"> + <bool>true</bool> + </property> </widget> </item> </layout> @@ -210,8 +254,8 @@ <rect> <x>0</x> <y>0</y> - <width>344</width> - <height>216</height> + <width>439</width> + <height>230</height> </rect> </property> </widget> @@ -463,9 +507,9 @@ </attribute> <addaction name="actionTake_Screenshot"/> <addaction name="actionSave_As"/> - <addaction name="actionQuick_Save"/> <addaction name="actionClose"/> </widget> + <widget class="QStatusBar" name="statusBar"/> <action name="actionTake_Screenshot"> <property name="text"> <string>Capture</string> diff --git a/src-qt5/desktop-utils/lumina-screenshot/i18n/l-screenshot_de.ts b/src-qt5/desktop-utils/lumina-screenshot/i18n/l-screenshot_de.ts index ab4efacf..5888f671 100644 --- a/src-qt5/desktop-utils/lumina-screenshot/i18n/l-screenshot_de.ts +++ b/src-qt5/desktop-utils/lumina-screenshot/i18n/l-screenshot_de.ts @@ -50,17 +50,17 @@ <message> <location filename="../MainUI.ui" line="70"/> <source> Sec Delay</source> - <translation type="unfinished"></translation> + <translation> Sek. Verzögerung</translation> </message> <message> <location filename="../MainUI.ui" line="183"/> <source>Capture</source> - <translation type="unfinished"></translation> + <translation>Aufnehmen</translation> </message> <message> <location filename="../MainUI.ui" line="212"/> <source>Edit</source> - <translation type="unfinished"></translation> + <translation>Bearbeiten</translation> </message> <message> <location filename="../MainUI.ui" line="362"/> @@ -100,12 +100,12 @@ <message> <location filename="../MainUI.cpp" line="79"/> <source>Could not save screenshot</source> - <translation type="unfinished"></translation> + <translation>Bildschirmfoto konnte nicht gespeichert werden</translation> </message> <message> <location filename="../MainUI.cpp" line="79"/> <source>The screenshot could not be saved. Please check directory permissions or pick a different directory</source> - <translation type="unfinished"></translation> + <translation>Das Bildschirmfoto konnte nicht gespeichert werden. Bitte überprüfen Sie die Verzeichnisberechtigungen oder wählen Sie ein anderes Verzeichnis aus</translation> </message> <message> <location filename="../MainUI.cpp" line="86"/> diff --git a/src-qt5/desktop-utils/lumina-terminal/i18n/l-terminal_de.ts b/src-qt5/desktop-utils/lumina-terminal/i18n/l-terminal_de.ts index 9cf56536..606091e8 100644 --- a/src-qt5/desktop-utils/lumina-terminal/i18n/l-terminal_de.ts +++ b/src-qt5/desktop-utils/lumina-terminal/i18n/l-terminal_de.ts @@ -6,12 +6,12 @@ <message> <location filename="../TerminalWidget.cpp" line="60"/> <source>Copy Selection</source> - <translation type="unfinished"></translation> + <translation>Auswahl kopieren</translation> </message> <message> <location filename="../TerminalWidget.cpp" line="61"/> <source>Paste</source> - <translation type="unfinished"></translation> + <translation>Einfügen</translation> </message> </context> <context> @@ -24,12 +24,12 @@ <message> <location filename="../TrayIcon.cpp" line="125"/> <source>Top of Screen</source> - <translation type="unfinished"></translation> + <translation>Oben am Bildschirm</translation> </message> <message> <location filename="../TrayIcon.cpp" line="130"/> <source>Close Terminal</source> - <translation type="unfinished"></translation> + <translation>Terminal schließen</translation> </message> <message> <location filename="../TrayIcon.cpp" line="139"/> @@ -39,7 +39,7 @@ <message> <location filename="../TrayIcon.cpp" line="142"/> <source>Monitor %1</source> - <translation type="unfinished"></translation> + <translation>Monitor %1</translation> </message> </context> </TS> diff --git a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp index e8eaa007..a0aff9cc 100644 --- a/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp +++ b/src-qt5/desktop-utils/lumina-textedit/PlainTextEditor.cpp @@ -83,7 +83,7 @@ void PlainTextEditor::LoadFile(QString filepath){ this->centerCursor(); //scroll until cursor is centered (if possible) } hasChanges = false; - watcher->addPath(filepath); + if(QFile::exists(filepath)){ watcher->addPath(filepath); } emit FileLoaded(this->whatsThis()); } diff --git a/src-qt5/desktop-utils/lumina-textedit/i18n/l-te_de.ts b/src-qt5/desktop-utils/lumina-textedit/i18n/l-te_de.ts index d493699e..9d7c344b 100644 --- a/src-qt5/desktop-utils/lumina-textedit/i18n/l-te_de.ts +++ b/src-qt5/desktop-utils/lumina-textedit/i18n/l-te_de.ts @@ -241,7 +241,7 @@ <location filename="../MainUI.cpp" line="289"/> <location filename="../MainUI.cpp" line="386"/> <source>Lose Unsaved Changes?</source> - <translation type="unfinished"></translation> + <translation>Nicht gespeicherte Änderungen verlieren?</translation> </message> <message> <location filename="../MainUI.cpp" line="289"/> @@ -249,7 +249,10 @@ Do you want to close it anyway? %1</source> - <translation type="unfinished"></translation> + <translation>Diese Datei hat nicht gespeicherte Änderungen. +Möchten Sie sie trotzdem schließen? + +%1</translation> </message> <message> <location filename="../MainUI.cpp" line="386"/> @@ -257,7 +260,10 @@ Do you want to close it anyway? Do you want to close the editor anyway? %1</source> - <translation type="unfinished"></translation> + <translation>Es gibt nicht gespeicherte Änderungen. +Möchten Sie den Editor trotzdem schließen? + +%1</translation> </message> </context> <context> @@ -275,7 +281,7 @@ Do you want to close the editor anyway? <message> <location filename="../PlainTextEditor.cpp" line="289"/> <source>Row Number: %1, Column Number: %2</source> - <translation type="unfinished"></translation> + <translation>Zeilennummer: %1, Spaltennummer: %2</translation> </message> <message> <location filename="../PlainTextEditor.cpp" line="298"/> @@ -285,7 +291,7 @@ Do you want to close the editor anyway? <message> <location filename="../PlainTextEditor.cpp" line="300"/> <source>(Note: You will lose all currently-unsaved changes)</source> - <translation>(Hinweis: Sie werden alle momentan ungespeicherten Änderungen verlieren)</translation> + <translation>(Hinweis: Sie werden alle momentan nicht gespeicherten Änderungen verlieren)</translation> </message> <message> <location filename="../PlainTextEditor.cpp" line="304"/> |