aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--DeveloperGuidelines.txt47
-rw-r--r--libLumina/LuminaOS-FreeBSD.cpp4
-rw-r--r--libLumina/LuminaX11.cpp36
-rw-r--r--libLumina/LuminaX11.h10
-rw-r--r--lumina-config/LPlugins.cpp9
-rw-r--r--lumina-config/mainUI.cpp101
-rw-r--r--lumina-desktop/LSession.cpp5
-rw-r--r--lumina-desktop/LWinInfo.cpp8
-rw-r--r--lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp42
-rw-r--r--lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h8
-rw-r--r--lumina-desktop/lumina-desktop.pro2
-rw-r--r--lumina-desktop/panel-plugins/NewPP.h3
-rw-r--r--lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp73
-rw-r--r--lumina-desktop/panel-plugins/applauncher/AppLaunchButton.h63
-rw-r--r--lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp7
-rw-r--r--lumina-fm/FODialog.cpp24
-rw-r--r--lumina-fm/MainUI.cpp11
-rw-r--r--lumina-wm/LScreenSaver.cpp97
-rw-r--r--lumina-wm/LScreenSaver.h43
-rw-r--r--lumina-wm/WMSession.h40
-rw-r--r--lumina-wm/lumina-wm.pro106
-rw-r--r--lumina-wm/main.cpp40
23 files changed, 720 insertions, 60 deletions
diff --git a/.gitignore b/.gitignore
index fce388d6..fea2c534 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,4 +13,3 @@ lumina-open/lumina-open
lumina-screenshot/lumina-screenshot
lumina-search/lumina-search
libLumina/libLuminaUtils.so.1.0
-
diff --git a/DeveloperGuidelines.txt b/DeveloperGuidelines.txt
new file mode 100644
index 00000000..3ad23291
--- /dev/null
+++ b/DeveloperGuidelines.txt
@@ -0,0 +1,47 @@
+Notes and guidelines for developers/contributors to the Lumina desktop environment
+----------------------------------------------------------------
+
+1) General Organization:
+ a) libLumina: This is where all frameworks or general-purpose functions should be placed
+ LuminaOS: Any operating-system specific routines (usually running 3rd-party or OS-specific utilities)
+ LuminaX11: Any X11/XCB interactions. This keeps it separate for the future conversion to other graphics subsystems (Wayland?)
+ LuminaXDG: Any FreeDesktop/XDG standards functionality.
+ LuminaUtils: Any static functions/utilities that are useful for multiple utilities/plugins.
+ Lumina<X>: The class/framework for functionality <X> (Examples: LuminaThemes, LuminaSingleApplication)
+
+ b) Utility naming:
+ Make sure that the binary names for utilities start with "lumina-". This ensures that it is easy for a command-line user to find/list lumina-specific utilities
+
+ c) Utility Combinations:
+ In order to avoid adding tons of extra utilities to Lumina, see if that functionality can be easily added to existing utilities first.
+ For example, "lumina-open" contains not just the file detection/usage, but also the application crash handler and small/fast system interactions (for keyboard shortcut usage).
+
+ d) 3rd-party dependencies
+ Try to avoid using 3rd-party dependencies whenever possible. Qt provides almost all the functionaliaty necessary (in a cross-OS capability) for 95% of what is necessary.
+ If another utility *is* required, place it within the LuminaOS class, and also provide a function for checking if that functionality is possible (is the utility installed?).
+ If the utility is *not* installed, just disable/hide that functionality within the Lumina utility and move on.
+
+2) General Coding Guidelines
+ a) Keep it simple! Try to have many small functions instead of a couple large ones. This makes it easier to maintain/update later on, and allows for a lot more "re-use" of functionality.
+ b) Keep it readable! Remember that other people may need to make changes in the future.
+ c) Keep is translatable! Try to put all the text-setting routines (for a static form) within a single function that can be re-run if the locale changes.
+ d) Comment what you are doing! It is very helpful to have the comments form an "outline" of the functionality so somebody reading the code can easily get an idea of what is happening.
+ NOTE: See reference [1] for a nice synopsis of good practices for coding.
+
+3) Specific Qt/Lumina Coding Guidelines
+ a) When using a Qt designer form (recommended for any UI with more than a couple widgets), make sure it is loaded under the "ui" namespace/variable
+ This ensures that when browsing the *.cpp code, it is easy to distinguish the widgets which should be configured/modified in the Qt designer utility.
+ b) When naming widgets, try to put a descriptor of the widget type at the front of the object name.
+ For example, a QComboBox should be named "combo_<something>", a QLabel would be "label_<something>". This makes it very easy to see in the code what type of widget is being used/modified at any given time.
+ c) Try to make function/variable names descriptive of what it manages.
+ For example, a QSpinBox which handles the maximum number of items could be named "spin_maxItems". If there are multiple widgets with similar functionality, make sure to distinguish them in the name (Example: spin_maxDesktopItems, spin_maxPanelItems)
+ d) Make any custom dialogs/windows a separate class, and ensure the filenames (*.cpp/h) are the same as the class name.
+ This makes it easy for someone to determine which file(s) contain the particular piece of information that is needed.
+ e) Don't break the event loop unless necessary! This is especially true for the lumina-desktop (plugins included) since you want to ensure that the UI remains responsive and does not "freeze" while waiting on some user-input.
+ f) When designing a UI, try to remember that the user might not have a mouse/keyboard when using the utility (it could be a touchscreen on a small device for instance).
+ g) Don't forget to update any packaging lists (pkg-plist) if you add new binaries/files that get installed. This makes it easier for packagers/distributors to know exactly what should be getting installed on the target system.
+
+4) When in doubt about something, just ask!
+ Ken Moore is usually available/active on the "Lumina-DE" channel on the Freenode IRC server, or you can contact him via GitHub or email.
+
+[1] https://www.codecogs.com/pages/standards/programming.htm
diff --git a/libLumina/LuminaOS-FreeBSD.cpp b/libLumina/LuminaOS-FreeBSD.cpp
index 269bed52..d454ce22 100644
--- a/libLumina/LuminaOS-FreeBSD.cpp
+++ b/libLumina/LuminaOS-FreeBSD.cpp
@@ -152,12 +152,12 @@ bool LOS::userHasShutdownAccess(){
//System Shutdown
void LOS::systemShutdown(){ //start poweroff sequence
- QProcess::startDetached("shutdown -p now");
+ QProcess::startDetached("shutdown -po now");
}
//System Restart
void LOS::systemRestart(){ //start reboot sequence
- QProcess::startDetached("shutdown -r now");
+ QProcess::startDetached("shutdown -ro now");
}
//Battery Availability
diff --git a/libLumina/LuminaX11.cpp b/libLumina/LuminaX11.cpp
index 199dd6ed..43d4e577 100644
--- a/libLumina/LuminaX11.cpp
+++ b/libLumina/LuminaX11.cpp
@@ -1012,7 +1012,7 @@ LXCB::WINDOWSTATE LXCB::WindowState(WId win){
}
// === WindowVisibleIconName() ===
-QString LXCB::WindowVisibleIconName(WId win){ //_WM_VISIBLE_ICON_NAME
+QString LXCB::WindowVisibleIconName(WId win){ //_NET_WM_VISIBLE_ICON_NAME
QString out;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_icon_name_unchecked(&EWMH, win);
if(cookie.sequence == 0){ return out; }
@@ -1024,7 +1024,7 @@ QString LXCB::WindowVisibleIconName(WId win){ //_WM_VISIBLE_ICON_NAME
}
// === WindowIconName() ===
-QString LXCB::WindowIconName(WId win){ //_WM_ICON_NAME
+QString LXCB::WindowIconName(WId win){ //_NET_WM_ICON_NAME
QString out;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_icon_name_unchecked(&EWMH, win);
if(cookie.sequence == 0){ return out; }
@@ -1036,7 +1036,7 @@ QString LXCB::WindowIconName(WId win){ //_WM_ICON_NAME
}
// === WindowVisibleName() ===
-QString LXCB::WindowVisibleName(WId win){ //_WM_VISIBLE_NAME
+QString LXCB::WindowVisibleName(WId win){ //_NET_WM_VISIBLE_NAME
QString out;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_visible_name_unchecked(&EWMH, win);
if(cookie.sequence == 0){ return out; }
@@ -1048,7 +1048,7 @@ QString LXCB::WindowVisibleName(WId win){ //_WM_VISIBLE_NAME
}
// === WindowName() ===
-QString LXCB::WindowName(WId win){ //_WM_NAME
+QString LXCB::WindowName(WId win){ //_NET_WM_NAME
QString out;
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked(&EWMH, win);
if(cookie.sequence == 0){ return out; }
@@ -1059,6 +1059,32 @@ QString LXCB::WindowName(WId win){ //_WM_NAME
return out;
}
+// === OldWindowName() ===
+QString LXCB::OldWindowName(WId win){ //WM_NAME (old standard)
+ xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_name_unchecked(QX11Info::connection(), win);
+ xcb_icccm_get_text_property_reply_t reply;
+ if(1 == xcb_icccm_get_wm_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){
+ QString name = QString::fromLocal8Bit(reply.name);
+ xcb_icccm_get_text_property_reply_wipe(&reply);
+ return name;
+ }else{
+ return "";
+ }
+}
+
+// === OldWindowIconName() ===
+QString LXCB::OldWindowIconName(WId win){ //WM_ICON_NAME (old standard)
+ xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_icon_name_unchecked(QX11Info::connection(), win);
+ xcb_icccm_get_text_property_reply_t reply;
+ if(1 == xcb_icccm_get_wm_icon_name_reply(QX11Info::connection(), cookie, &reply, NULL) ){
+ QString name = QString::fromLocal8Bit(reply.name);
+ xcb_icccm_get_text_property_reply_wipe(&reply);
+ return name;
+ }else{
+ return "";
+ }
+}
+
// === WindowIsMaximized() ===
bool LXCB::WindowIsMaximized(WId win){
//See if the _NET_WM_STATE_MAXIMIZED_[VERT/HORZ] flags are set on the window
@@ -1348,4 +1374,4 @@ void LXCB::MoveResizeWindow(WId win, QRect geom){
xcb_ewmh_set_workarea(&EWMH, 0, desks, dareas); //_NET_WORKAREA
//Make sure to clear that reply
xcb_ewmh_get_workarea_reply_wipe(&work);
-}*/ \ No newline at end of file
+}*/
diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h
index cd5f8183..62146ebe 100644
--- a/libLumina/LuminaX11.h
+++ b/libLumina/LuminaX11.h
@@ -133,10 +133,12 @@ public:
unsigned int WindowWorkspace(WId); //The workspace the window is on
QRect WindowGeometry(WId, bool includeFrame = true); //the geometry of the window (frame excluded)
WINDOWSTATE WindowState(WId win); //Visible state of window
- QString WindowVisibleIconName(WId win); //_WM_VISIBLE_ICON_NAME
- QString WindowIconName(WId win); //_WM_ICON_NAME
- QString WindowVisibleName(WId win); //_WM_VISIBLE_NAME
- QString WindowName(WId win); //_WM_NAME
+ QString WindowVisibleIconName(WId win); //_NET_WM_VISIBLE_ICON_NAME
+ QString WindowIconName(WId win); //_NET_WM_ICON_NAME
+ QString WindowVisibleName(WId win); //_NET_WM_VISIBLE_NAME
+ QString WindowName(WId win); //_NET_WM_NAME
+ QString OldWindowName(WId win); //WM_NAME (old standard)
+ QString OldWindowIconName(WId win); //WM_ICON_NAME (old standard)
bool WindowIsMaximized(WId win);
QIcon WindowIcon(WId win); //_NET_WM_ICON
QPixmap WindowImage(WId win); //Pull the image directly from the window
diff --git a/lumina-config/LPlugins.cpp b/lumina-config/LPlugins.cpp
index 55a5ee9e..94b61f34 100644
--- a/lumina-config/LPlugins.cpp
+++ b/lumina-config/LPlugins.cpp
@@ -135,13 +135,20 @@ void LPlugins::LoadPanelPlugins(){
info.ID = "homebutton";
info.icon = "go-home";
PANEL.insert(info.ID, info);
- //Desktop Bar
+ //Start Menu
info = LPI(); //clear it
info.name = QObject::tr("Start Menu");
info.description = QObject::tr("This provides instant-access to application that are installed on the system.");
info.ID = "appmenu";
info.icon = "Lumina-DE";
PANEL.insert(info.ID, info);
+ //Application Launcher
+ info = LPI(); //clear it
+ info.name = QObject::tr("Application Launcher");
+ info.description = QObject::tr("Pin an application shortcut directly to the panel");
+ info.ID = "applauncher";
+ info.icon = "quickopen";
+ PANEL.insert(info.ID, info);
}
void LPlugins::LoadDesktopPlugins(){
diff --git a/lumina-config/mainUI.cpp b/lumina-config/mainUI.cpp
index ba254d9f..744d4bdf 100644
--- a/lumina-config/mainUI.cpp
+++ b/lumina-config/mainUI.cpp
@@ -509,11 +509,21 @@ void MainUI::loadCurrentSettings(bool screenonly){
ui->list_panel1_plugins->clear();
for(int i=0; i<plugs.length(); i++){
QString pid = plugs[i].section("---",0,0);
- LPI info = PINFO->panelPluginInfo(pid);
- if(!info.ID.isEmpty()){
- QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(info.icon,""), info.name );
+ if(pid.startsWith("applauncher")){
+ bool ok = false;
+ XDGDesktop desk = LXDG::loadDesktopFile(pid.section("::",1,1),ok);
+ if(ok){
+ QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(desk.icon,""), desk.name );
+ it->setWhatsThis(plugs[i]); //make sure to preserve the entire plugin ID (is the unique version)
+ ui->list_panel1_plugins->addItem(it);
+ }
+ }else{
+ LPI info = PINFO->panelPluginInfo(pid);
+ if(!info.ID.isEmpty()){
+ QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(info.icon,""), info.name );
it->setWhatsThis(plugs[i]); //make sure to preserve the entire plugin ID (is the unique version)
- ui->list_panel1_plugins->addItem(it);
+ ui->list_panel1_plugins->addItem(it);
+ }
}
}
QString color = settings->value(PPrefix+"color","rgba(255,255,255,160)").toString();
@@ -891,8 +901,13 @@ void MainUI::adjustpanel1(){
if(loading || panadjust){ return; }
panadjust = true;
qDebug() << "Adjust Panel 1:";
- ui->toolBox_panel1->setCurrentIndex( ui->toolBox_panel2->currentIndex() );
- bool changed = false;
+ bool valchanged = ui->toolBox_panel1->currentIndex()==ui->toolBox_panel2->currentIndex();
+ if(!valchanged){
+ //Just a toolbox page change - switch to match and exit
+ ui->toolBox_panel1->setCurrentIndex( ui->toolBox_panel2->currentIndex() );
+ panadjust = false;
+ return;
+ }
int newindex=0;
switch(ui->combo_panel2_loc->currentIndex()){
case 0:
@@ -905,11 +920,11 @@ void MainUI::adjustpanel1(){
newindex = 2; break;
}
if(newindex != ui->combo_panel1_loc->currentIndex()){
- changed = true;
+ valchanged = true;
ui->combo_panel1_loc->setCurrentIndex(newindex);
}
panadjust = false;
- if(!loading){ ui->push_save->setEnabled(true); modpan = true; }
+ if(!loading && valchanged){ ui->push_save->setEnabled(true); modpan = true; }
}
void MainUI::adjustpanel2(){
@@ -917,8 +932,14 @@ void MainUI::adjustpanel2(){
panadjust = true;
//Adjust panel 2 to complement a panel 1 change
qDebug() << "Adjust Panel 2:";
- ui->toolBox_panel2->setCurrentIndex( ui->toolBox_panel1->currentIndex() );
- bool changed = false;
+ bool valchanged = ui->toolBox_panel1->currentIndex()==ui->toolBox_panel2->currentIndex();
+ if(!valchanged){
+ //Just a toolbox page change - switch to match and exit
+ ui->toolBox_panel2->setCurrentIndex( ui->toolBox_panel1->currentIndex() );
+ panadjust = false;
+ return;
+ }
+
int newindex=0;
switch(ui->combo_panel1_loc->currentIndex()){
case 0:
@@ -931,11 +952,11 @@ void MainUI::adjustpanel2(){
newindex = 2; break;
}
if(newindex != ui->combo_panel2_loc->currentIndex()){
- changed = true;
+ valchanged = true;
ui->combo_panel2_loc->setCurrentIndex(newindex);
}
panadjust = false;
- if(!loading && changed){ ui->push_save->setEnabled(true); modpan = true; }
+ if(!loading && valchanged){ ui->push_save->setEnabled(true); modpan = true; }
}
@@ -963,14 +984,26 @@ void MainUI::addpanel1plugin(){
dlg.exec();
if(!dlg.selected){ return; } //cancelled
QString pan = dlg.plugID; //getNewPanelPlugin();
- if(pan.isEmpty()){ return; } //nothing selected
- //Add the new plugin to the list
- LPI info = PINFO->panelPluginInfo(pan);
- QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(info.icon,""), info.name);
- it->setWhatsThis(info.ID);
- ui->list_panel1_plugins->addItem(it);
- ui->list_panel1_plugins->setCurrentItem(it);
- ui->list_panel1_plugins->scrollToItem(it);
+ if(pan == "applauncher"){
+ //Prompt for the application to add
+ XDGDesktop app = getSysApp();
+ if(app.filePath.isEmpty()){ return; } //cancelled
+ pan.append("::"+app.filePath);
+ QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(app.icon,""), app.name);
+ it->setWhatsThis(pan);
+ ui->list_panel1_plugins->addItem(it);
+ ui->list_panel1_plugins->setCurrentItem(it);
+ ui->list_panel1_plugins->scrollToItem(it);
+ }else{
+ if(pan.isEmpty()){ return; } //nothing selected
+ //Add the new plugin to the list
+ LPI info = PINFO->panelPluginInfo(pan);
+ QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(info.icon,""), info.name);
+ it->setWhatsThis(info.ID);
+ ui->list_panel1_plugins->addItem(it);
+ ui->list_panel1_plugins->setCurrentItem(it);
+ ui->list_panel1_plugins->scrollToItem(it);
+ }
checkpanels(); //update buttons
if(!loading){ ui->push_save->setEnabled(true); modpan = true; }
}
@@ -981,14 +1014,26 @@ void MainUI::addpanel2plugin(){
dlg.exec();
if(!dlg.selected){ return; } //cancelled
QString pan = dlg.plugID; //getNewPanelPlugin();
- if(pan.isEmpty()){ return; } //nothing selected
- //Add the new plugin to the list
- LPI info = PINFO->panelPluginInfo(pan);
- QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(info.icon,""), info.name);
- it->setWhatsThis(info.ID);
- ui->list_panel2_plugins->addItem(it);
- ui->list_panel2_plugins->setCurrentItem(it);
- ui->list_panel2_plugins->scrollToItem(it);
+ if(pan == "applauncher"){
+ //Prompt for the application to add
+ XDGDesktop app = getSysApp();
+ if(app.filePath.isEmpty()){ return; } //cancelled
+ pan.append("::"+app.filePath);
+ QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(app.icon,""), app.name);
+ it->setWhatsThis(pan);
+ ui->list_panel2_plugins->addItem(it);
+ ui->list_panel2_plugins->setCurrentItem(it);
+ ui->list_panel2_plugins->scrollToItem(it);
+ }else{
+ if(pan.isEmpty()){ return; } //nothing selected
+ //Add the new plugin to the list
+ LPI info = PINFO->panelPluginInfo(pan);
+ QListWidgetItem *it = new QListWidgetItem( LXDG::findIcon(info.icon,""), info.name);
+ it->setWhatsThis(info.ID);
+ ui->list_panel2_plugins->addItem(it);
+ ui->list_panel2_plugins->setCurrentItem(it);
+ ui->list_panel2_plugins->scrollToItem(it);
+ }
checkpanels(); //update buttons
if(!loading){ ui->push_save->setEnabled(true); modpan = true; }
}
diff --git a/lumina-desktop/LSession.cpp b/lumina-desktop/LSession.cpp
index 8eef0b95..6437524b 100644
--- a/lumina-desktop/LSession.cpp
+++ b/lumina-desktop/LSession.cpp
@@ -257,6 +257,11 @@ void LSession::checkUserFiles(){
}*/
LUtils::LoadSystemDefaults();
}
+ if(oldversion <= 83){
+ //Convert the old->new favorites framework
+
+ }
+
//Check for the default applications file for lumina-open
dset = QDir::homePath()+"/.lumina/LuminaDE/lumina-open.conf";
if(!QFile::exists(dset)){
diff --git a/lumina-desktop/LWinInfo.cpp b/lumina-desktop/LWinInfo.cpp
index 4ea91c1f..b1476c4e 100644
--- a/lumina-desktop/LWinInfo.cpp
+++ b/lumina-desktop/LWinInfo.cpp
@@ -15,9 +15,11 @@
QString LWinInfo::text(){
if(window==0){ return ""; }
QString nm = LSession::handle()->XCB->WindowVisibleIconName(window);
- if(nm.isEmpty()){ nm = LSession::handle()->XCB->WindowIconName(window); }
- if(nm.isEmpty()){ nm = LSession::handle()->XCB->WindowVisibleName(window); }
- if(nm.isEmpty()){ nm = LSession::handle()->XCB->WindowName(window); }
+ if(nm.simplified().isEmpty()){ nm = LSession::handle()->XCB->WindowIconName(window); }
+ if(nm.simplified().isEmpty()){ nm = LSession::handle()->XCB->WindowVisibleName(window); }
+ if(nm.simplified().isEmpty()){ nm = LSession::handle()->XCB->WindowName(window); }
+ if(nm.simplified().isEmpty()){ nm = LSession::handle()->XCB->OldWindowIconName(window); }
+ if(nm.simplified().isEmpty()){ nm = LSession::handle()->XCB->OldWindowName(window); }
return nm;
}
diff --git a/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp b/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp
index dc0c7596..b3c6afcf 100644
--- a/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp
+++ b/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.cpp
@@ -7,18 +7,19 @@ AppLauncherPlugin::AppLauncherPlugin(QWidget* parent, QString ID) : LDPlugin(par
lay->setContentsMargins(0,0,0,0);
button = new QToolButton(this);
button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
- button->setIconSize(QSize(64,64));
button->setAutoRaise(true);
button->setText("..."); //Need to set something here so that initial sizing works properly
+
lay->addWidget(button, 0, Qt::AlignCenter);
connect(button, SIGNAL(clicked()), this, SLOT(buttonClicked()) );
- this->setInitialSize(64,66+this->fontMetrics().height());
- /*if(this->settings->allKeys().isEmpty()){
- //Brand new plugin: set initial size
- this->settings->setValue("location/width",64);
- this->settings->setValue("location/height",66+this->fontMetrics().height());
- this->settings->sync();
- }*/
+ menu = new QMenu(this);
+ menu->addAction(LXDG::findIcon("zoom-in",""), tr("Increase Size"), this, SLOT(increaseIconSize()));
+ menu->addAction(LXDG::findIcon("zoom-out",""), tr("Decrease Size"), this, SLOT(decreaseIconSize()));
+ int icosize = settings->value("iconsize",64).toInt();
+ button->setIconSize(QSize(icosize,icosize));
+ this->setInitialSize(icosize,icosize+10+this->fontMetrics().height());
+ this->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(openContextMenu()) );
watcher = new QFileSystemWatcher(this);
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT( loadButton()) );
QTimer::singleShot(1,this, SLOT(loadButton()) );
@@ -62,4 +63,27 @@ void AppLauncherPlugin::buttonClicked(){
LSession::LaunchApplication("lumina-open \""+path+"\"");
}
-} \ No newline at end of file
+}
+
+void AppLauncherPlugin::openContextMenu(){
+ if(button->underMouse()){
+ menu->popup(QCursor::pos());
+ }else{
+ emit OpenDesktopMenu();
+ }
+}
+
+void AppLauncherPlugin::increaseIconSize(){
+ int icosize = settings->value("iconsize",64).toInt();
+ icosize += 16;
+ button->setIconSize(QSize(icosize,icosize));
+ settings->setValue("iconsize",icosize);
+}
+
+void AppLauncherPlugin::decreaseIconSize(){
+ int icosize = settings->value("iconsize",64).toInt();
+ if(icosize < 20){ return; } //cannot get smaller
+ icosize -= 16;
+ button->setIconSize(QSize(icosize,icosize));
+ settings->setValue("iconsize",icosize);
+}
diff --git a/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h b/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h
index bb21b636..2c861e4d 100644
--- a/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h
+++ b/lumina-desktop/desktop-plugins/applauncher/AppLauncherPlugin.h
@@ -16,6 +16,8 @@
#include <QFile>
#include <QFileSystemWatcher>
#include <QTimer>
+#include <QMenu>
+#include <QCursor>
#include "../LDPlugin.h"
@@ -30,9 +32,15 @@ public:
private:
QToolButton *button;
QFileSystemWatcher *watcher;
+ QMenu *menu;
private slots:
void loadButton();
void buttonClicked();
+ void openContextMenu();
+
+ void increaseIconSize();
+ void decreaseIconSize();
+
};
#endif
diff --git a/lumina-desktop/lumina-desktop.pro b/lumina-desktop/lumina-desktop.pro
index dc3db9bd..6c3ee0cc 100644
--- a/lumina-desktop/lumina-desktop.pro
+++ b/lumina-desktop/lumina-desktop.pro
@@ -50,6 +50,7 @@ SOURCES += main.cpp \
panel-plugins/systemdashboard/SysMenuQuick.cpp \
panel-plugins/showdesktop/LHomeButton.cpp \
panel-plugins/appmenu/LAppMenuPlugin.cpp \
+ panel-plugins/applauncher/AppLaunchButton.cpp \
desktop-plugins/applauncher/AppLauncherPlugin.cpp \
desktop-plugins/desktopview/DesktopViewPlugin.cpp \
desktop-plugins/notepad/NotepadPlugin.cpp \
@@ -89,6 +90,7 @@ HEADERS += Globals.h \
panel-plugins/systemdashboard/SysMenuQuick.h \
panel-plugins/showdesktop/LHomeButton.h \
panel-plugins/appmenu/LAppMenuPlugin.h \
+ panel-plugins/applauncher/AppLaunchButton.h \
desktop-plugins/SamplePlugin.h \
desktop-plugins/calendar/CalendarPlugin.h \
desktop-plugins/applauncher/AppLauncherPlugin.h \
diff --git a/lumina-desktop/panel-plugins/NewPP.h b/lumina-desktop/panel-plugins/NewPP.h
index 6c5c369c..3a593629 100644
--- a/lumina-desktop/panel-plugins/NewPP.h
+++ b/lumina-desktop/panel-plugins/NewPP.h
@@ -23,6 +23,7 @@
#include "systemdashboard/LSysDashboard.h"
#include "showdesktop/LHomeButton.h"
#include "appmenu/LAppMenuPlugin.h"
+#include "applauncher/AppLaunchButton.h"
#include "systemtray/LSysTray.h" //must be last due to X11 compile issues
class NewPP{
@@ -52,6 +53,8 @@ public:
plug = new LSysDashboard(parent, plugin, horizontal);
}else if(plugin.startsWith("appmenu---")){
plug = new LAppMenuPlugin(parent, plugin, horizontal);
+ }else if(plugin.section("---",0,0).section("::",0,0)=="applauncher"){
+ plug = new AppLaunchButtonPlugin(parent, plugin, horizontal);
}else{
qWarning() << "Invalid Panel Plugin:"<<plugin << " -- Ignored";
}
diff --git a/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp b/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp
new file mode 100644
index 00000000..5bd7fa96
--- /dev/null
+++ b/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.cpp
@@ -0,0 +1,73 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "AppLaunchButton.h"
+#include "../../LSession.h"
+
+#include <LuminaXDG.h>
+
+AppLaunchButtonPlugin::AppLaunchButtonPlugin(QWidget *parent, QString id, bool horizontal) : LPPlugin(parent, id, horizontal){
+ button = new QToolButton(this);
+ button->setAutoRaise(true);
+ button->setToolButtonStyle(Qt::ToolButtonIconOnly);
+ appfile = id.section("---",0,0).section("::",1,1);
+ if(!QFile::exists(appfile)){ appfile.clear(); }
+ connect(button, SIGNAL(clicked()), this, SLOT(AppClicked()));
+ this->layout()->setContentsMargins(0,0,0,0);
+ this->layout()->addWidget(button);
+
+ QTimer::singleShot(0,this, SLOT(OrientationChange())); //Update icons/sizes
+}
+
+AppLaunchButtonPlugin::~AppLaunchButtonPlugin(){
+
+}
+
+void AppLaunchButtonPlugin::updateButtonVisuals(){
+ QIcon icon;
+ QString tooltip = tr("Click to assign an application");
+ if(appfile.endsWith(".desktop")){
+ bool ok = false;
+ XDGDesktop desk = LXDG::loadDesktopFile(appfile,ok);
+ if(ok){
+ icon = LXDG::findIcon(desk.icon, "unknown");
+ tooltip = QString(tr("Launch %1")).arg(desk.name);
+ }else{
+ icon = LXDG::findIcon("task-attention","");
+ appfile.clear();
+ }
+ }else if(QFile::exists(appfile)){
+ icon = LXDG::findMimeIcon(appfile.section("/",-1));
+ tooltip = QString(tr("Open %1")).arg(appfile.section("/",-1));
+ }else{
+ icon = LXDG::findIcon("task-attention", "");
+ }
+ button->setIcon( icon );
+ button->setToolTip(tooltip);
+}
+
+// ========================
+// PRIVATE FUNCTIONS
+// ========================
+void AppLaunchButtonPlugin::AppClicked(){
+ if(appfile.isEmpty()){
+ //No App File selected
+ QList<XDGDesktop> apps = LSession::handle()->applicationMenu()->currentAppHash()->value("All");
+ QStringList names;
+ for(int i=0; i<apps.length(); i++){ names << apps[i].name; }
+ bool ok = false;
+ QString app = QInputDialog::getItem(this, tr("Select Application"), tr("Name:"), names, 0, false, &ok);
+ if(!ok || names.indexOf(app)<0){ return; } //cancelled
+ appfile = apps[ names.indexOf(app) ].filePath;
+ //Still need to find a way to set this value persistently
+ // --- perhaps replace the plugin in the desktop settings file with the new path?
+ // --- "applauncher::broken---<something>" -> "applauncher::fixed---<something>" ?
+ QTimer::singleShot(0,this, SLOT(updateButtonVisuals()));
+ }else{
+ LSession::LaunchApplication("lumina-open \""+appfile+"\"");
+ }
+}
+
diff --git a/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.h b/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.h
new file mode 100644
index 00000000..3aa3c7ad
--- /dev/null
+++ b/lumina-desktop/panel-plugins/applauncher/AppLaunchButton.h
@@ -0,0 +1,63 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+// This panel plugin is a simple button to launch a single application
+//===========================================
+#ifndef _LUMINA_DESKTOP_LAUNCH_APP_PANEL_PLUGIN_H
+#define _LUMINA_DESKTOP_LAUNCH_APP_PANEL_PLUGIN_H
+
+// Qt includes
+#include <QToolButton>
+#include <QString>
+#include <QWidget>
+
+
+// Lumina-desktop includes
+#include "../LPPlugin.h" //main plugin widget
+
+// libLumina includes
+#include "LuminaXDG.h"
+
+// PANEL PLUGIN BUTTON
+class AppLaunchButtonPlugin : public LPPlugin{
+ Q_OBJECT
+
+public:
+ AppLaunchButtonPlugin(QWidget *parent = 0, QString id = "applauncher", bool horizontal=true);
+ ~AppLaunchButtonPlugin();
+
+private:
+ QToolButton *button;
+ QString appfile;
+
+ void updateButtonVisuals();
+
+private slots:
+ void AppClicked();
+
+public slots:
+ void OrientationChange(){
+ if(this->layout()->direction()==QBoxLayout::LeftToRight){
+ this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
+ button->setIconSize( QSize(this->height(), this->height()) );
+ }else{
+ this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+ button->setIconSize( QSize(this->width(), this->width()) );
+ }
+ this->layout()->update();
+ updateButtonVisuals();
+ }
+
+ void LocaleChange(){
+ updateButtonVisuals();
+ }
+
+ void ThemeChange(){
+ updateButtonVisuals();
+ }
+};
+
+#endif \ No newline at end of file
diff --git a/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp b/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
index 7c24dc3d..20607c60 100644
--- a/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
+++ b/lumina-desktop/panel-plugins/taskmanager/LTaskButton.cpp
@@ -121,13 +121,14 @@ void LTaskButton::UpdateButton(){
//single window
this->setPopupMode(QToolButton::DelayedPopup);
this->setMenu(actMenu);
- if(showText){ this->setText( this->fontMetrics().elidedText(WINLIST[0].text(), Qt::ElideRight,80) ); }
- else if(noicon){ this->setText( this->fontMetrics().elidedText(cname, Qt::ElideRight ,80) ); }
- else{ this->setText(""); }
+ if(showText){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( this->fontMetrics().elidedText(WINLIST[0].text(), Qt::ElideRight,80) ); }
+ else if(noicon){ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); this->setText( this->fontMetrics().elidedText(cname, Qt::ElideRight ,80) ); }
+ else{ this->setToolButtonStyle(Qt::ToolButtonIconOnly); this->setText(""); }
}else if(WINLIST.length() > 1){
//multiple windows
this->setPopupMode(QToolButton::InstantPopup);
this->setMenu(winMenu);
+ this->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
if(noicon || showText){ this->setText( this->fontMetrics().elidedText(cname, Qt::ElideRight ,80) +" ("+QString::number(WINLIST.length())+")" ); }
else{ this->setText("("+QString::number(WINLIST.length())+")"); }
}
diff --git a/lumina-fm/FODialog.cpp b/lumina-fm/FODialog.cpp
index 165733e3..d182ed06 100644
--- a/lumina-fm/FODialog.cpp
+++ b/lumina-fm/FODialog.cpp
@@ -219,6 +219,7 @@ QStringList FOWorker::removeItem(QString path, bool recursive){
QStringList FOWorker::copyItem(QString oldpath, QString newpath){
QStringList err;
+ if(oldpath == newpath){ return err; } //copy something onto itself - just skip it
if(QFileInfo(oldpath).isDir()){
//Create a new directory with the same name (no way to copy dir+contents)
QDir dir;
@@ -268,6 +269,10 @@ void FOWorker::slotStartOperations(){
if(isRM){ //only old files
olist << subfiles(ofiles[i], false); //dirs need to be last for removals
}else if(isCP || isRESTORE){
+ if(nfiles[i] == ofiles[i]){
+ //Trying to copy a file/dir to itself - skip it
+ continue;
+ }
if(QFile::exists(nfiles[i])){
if(!overwrite){
nfiles[i] = newFileName(nfiles[i]); //prompt for new file name up front before anything starts
@@ -287,6 +292,12 @@ void FOWorker::slotStartOperations(){
QStringList err; err << tr("Invalid Move") << QString(tr("It is not possible to move a directory into itself. Please make a copy of the directory instead.\n\nOld Location: %1\nNew Location: %2")).arg(ofiles[i], nfiles[i]);
emit finished(err); return;
}else{
+ //Check for existance of the new name
+ if(QFile::exists(nfiles[i])){
+ if(!overwrite){
+ nfiles[i] = newFileName(nfiles[i]); //prompt for new file name up front before anything starts
+ }
+ }
//no changes necessary
olist << ofiles[i];
nlist << nfiles[i];
@@ -319,8 +330,17 @@ void FOWorker::slotStartOperations(){
/*ui->label->setText( QString(tr("Moving: %1 to %2")).arg(ofiles[i].section("/",-1), nfiles[i].section("/",-1)) );
QApplication::processEvents();*/
emit startingItem(i+1,olist.length(), olist[i], nlist[i]);
- if( !QFile::rename(ofiles[i], nfiles[i]) ){
- errlist << ofiles[i];
+ //Clean up any overwritten files/dirs
+ if(QFile::exists(nlist[i])){
+ if(overwrite){
+ errlist << removeItem(nlist[i], true); //recursively remove the file/dir since we are supposed to overwrite it
+ }
+ }
+ //Perform the move if no error yet (including skipping all children)
+ if( !errlist.contains(olist[i].section("/",0,-1)) ){
+ if( !QFile::rename(ofiles[i], nfiles[i]) ){
+ errlist << ofiles[i];
+ }
}
}
//ui->progressBar->setValue(i+1);
diff --git a/lumina-fm/MainUI.cpp b/lumina-fm/MainUI.cpp
index 1576e65a..9d66bc36 100644
--- a/lumina-fm/MainUI.cpp
+++ b/lumina-fm/MainUI.cpp
@@ -442,9 +442,11 @@ void MainUI::setCurrentDir(QString dir){
ui->tool_goToPlayer->setVisible(false);
ui->tool_goToRestore->setVisible(false);
ui->tool_goToImages->setVisible(false);
- //if(olddir!=rawdir){
+ //Make sure the shortcut buttons are enabled as necessary
+ // If the dir is already loaded into the fsmodel cache it will not emit the directoryLoaded() signal
+ if(rawdir == olddir){
emit DirChanged(rawdir); //This will be automatically run when a new dir is loaded
- //}
+ }
if(isUserWritable){ ui->label_dir_stats->setText(""); }
else{ ui->label_dir_stats->setText(tr("Limited Access Directory")); }
ui->tool_addToDir->setVisible(isUserWritable);
@@ -825,6 +827,7 @@ void MainUI::reloadDirectory(){
void MainUI::currentDirectoryLoaded(){
//The directory was just loaded: refresh the action buttons as neccesary
+ // NOTE: This is only "caught" when a *new* directory is loaded into the model
ui->tool_goToPlayer->setVisible(false);
ui->tool_goToRestore->setVisible(false);
ui->tool_goToImages->setVisible(false);
@@ -1037,6 +1040,10 @@ void MainUI::removePicture(){
QString file = getCurrentDir();
if(!file.endsWith("/")){ file.append("/"); }
file.append(ui->combo_image_name->currentText());
+ //Verify permanent removal of file/dir
+ if(QMessageBox::Yes != QMessageBox::question(this, tr("Verify Removal"), tr("WARNING: This will permanently delete the file from the system!")+"\n"+tr("Are you sure you want to continue?")+"\n\n"+file, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) ){
+ return; //cancelled
+ }
if( QFile::remove(file) ){
int index = ui->combo_image_name->currentIndex();
ui->combo_image_name->removeItem( index );
diff --git a/lumina-wm/LScreenSaver.cpp b/lumina-wm/LScreenSaver.cpp
new file mode 100644
index 00000000..7af3758f
--- /dev/null
+++ b/lumina-wm/LScreenSaver.cpp
@@ -0,0 +1,97 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include "LScreenSaver.h"
+
+LScreenSaver::LScreenSaver(){
+ starttimer = new QTimer(this);
+ starttimer->setSingleShot(true);
+ locktimer = new QTimer(this);
+ locktimer->setSingleShot(true);
+ hidetimer = new QTimer(this);
+ hidetimer->setSingleShot(true);
+
+ settings = new QSettings("LuminaDE","lumina-screensaver",this);
+ SSRunning = SSLocked = false;
+
+ connect(starttimer, SIGNAL(timeout()), this, SLOT(ShowScreenSaver()) );
+}
+
+LScreenSaver::~LScreenSaver(){
+
+}
+
+// ===========
+// PUBLIC SLOTS
+// ===========
+void LScreenSaver::start(){
+ reloadSettings(); //setup all the initial time frames
+
+}
+
+void LScreenSaver::reloadSettings(){
+ settings->sync();
+ starttimer->setInterval( settings.value("timedelaymin",10).toInt() * 60000 );
+ locktimer->setInterval( settings.value("lockdelaymin",1).toInt() * 60000 );
+ hidetimer->setInterval( settings.value("hidesecs",15).toInt() * 1000 );
+}
+
+void LScreenSaver::newInputEvent(){
+ //First stop any timers that are running
+ if(starttimer->isActive()){ starttimer->stop();}
+ if(locktimer->isActive()){ locktimer->stop(); }
+ if(hidetimer->isActive()){ hidetimer->stop(); }
+
+ if(SSRunning && SSLocked){
+ //Running and locked
+ // Hide the running setting, and display the lock screen
+
+ //Start the timer for restarting the SS and hiding the lockscreen
+ hidetimer->start();
+
+ }else if(SSRunning){
+ //Only running, not locked
+ //De-activate the screensaver and start the main timer
+ HideScreenSaver();
+ starttimer->start();
+
+ }else if(SSLocked){
+ //Only locked, not running
+ hidetimer->start(); //restart the time to hide the lock screen
+
+ }else{
+ //Neither running nor locked
+ if( settings.value("timedelaymin",10).toInt() > 0 ){ starttimer->start(); }
+ }
+
+}
+
+// ===========
+// PRIVATE SLOTS
+// ===========
+void LScreenSaver::ShowScreenSaver(){
+
+ SSRunning = true;
+ //Start the lock timer if necessary
+ if(!SSLocked && (settings.value("lockdelaymin",10).toInt()>0) ){ locktimer->start(); }
+}
+
+void LScreenSaver::ShowLockScreen(){
+
+ SSLocked = true;
+ //Start the timer for hiding the lock screen due to inactivity
+ if(settings.value("hidesecs",15).toInt() > 0 ){ hidetimer->start(); }
+}
+
+void LScreenSaver::HideScreenSaver(){
+
+ SSRunning = false;
+}
+
+void LScreenSaver::HideLockScreen(){
+
+ //Leave the Locked flag set (still locked, just not visible)
+}
diff --git a/lumina-wm/LScreenSaver.h b/lumina-wm/LScreenSaver.h
new file mode 100644
index 00000000..c2965ae6
--- /dev/null
+++ b/lumina-wm/LScreenSaver.h
@@ -0,0 +1,43 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_SCREEN_SAVER_H
+#define _LUMINA_DESKTOP_SCREEN_SAVER_H
+
+#include <QObject>
+#include <QStringList>
+#include <QTimer>
+#include <QSettings>
+
+class LScreenSaver : public QObject{
+ Q_OBJECT
+public:
+ LScreenSaver();
+ ~LScreenSaver();
+
+private:
+ QTimer *starttimer, *locktimer, *hidetimer;
+ QSettings *settings;
+ bool SSRunning, SSLocked;
+
+public slots:
+ void start();
+ void reloadSettings();
+ void newInputEvent();
+
+private slots:
+ void ShowScreenSaver();
+ void ShowLockScreen();
+ void HideScreenSaver();
+ void HideLockScreen();
+
+signals:
+ void StartingScreenSaver();
+ void ClosingScreenSaver();
+
+};
+
+#endif \ No newline at end of file
diff --git a/lumina-wm/WMSession.h b/lumina-wm/WMSession.h
new file mode 100644
index 00000000..a1212af5
--- /dev/null
+++ b/lumina-wm/WMSession.h
@@ -0,0 +1,40 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#ifndef _LUMINA_DESKTOP_WINDOW_MANAGER_SESSION_H
+#define _LUMINA_DESKTOP_WINDOW_MANAGER_SESSION_H
+
+#include <QObject>
+#include <QStringList>
+
+#include "LScreenSaver.h"
+
+class WMSession : public QObject{
+ Q_OBJECT
+public:
+ WMSession();
+ ~WMSession();
+
+ void start();
+
+private:
+ //XCB Event Watcher
+
+ //ScreenSaver
+ LScreenSaver *SS;
+
+ //Window Manager
+
+
+public slots:
+ void reloadIcons();
+ void newInputsAvailable(QStringList);
+
+private slots:
+
+};
+
+#endif \ No newline at end of file
diff --git a/lumina-wm/lumina-wm.pro b/lumina-wm/lumina-wm.pro
new file mode 100644
index 00000000..34d8a9ac
--- /dev/null
+++ b/lumina-wm/lumina-wm.pro
@@ -0,0 +1,106 @@
+
+QT += core gui network
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets x11extras
+
+TARGET = lumina-wm
+isEmpty(PREFIX) {
+ PREFIX = /usr/local
+}
+target.path = $$PREFIX/bin
+
+isEmpty(LIBPREFIX) {
+ LIBPREFIX = $$PREFIX/lib
+}
+
+LIBS += -L../libLumina -L$$LIBPREFIX -lLuminaUtils -lXdamage -lX11 -lxcb -lxcb-damage
+QMAKE_LIBDIR = ../libLumina
+DEPENDPATH += ../libLumina
+
+TEMPLATE = app
+
+isEmpty(QT5LIBDIR) {
+ QT5LIBDIR = $$PREFIX/lib/qt5
+}
+
+LRELEASE = $$QT5LIBDIR/bin/lrelease
+
+
+SOURCES += main.cpp \
+ WMSession.cpp \
+ LScreenSaver.cpp
+
+
+HEADERS += WMSession.h \
+ LScreenSaver.h
+
+FORMS +=
+
+INCLUDEPATH += ../libLumina $$PREFIX/include
+
+TRANSLATIONS = i18n/lumina-wm_af.ts \
+ i18n/lumina-wm_ar.ts \
+ i18n/lumina-wm_az.ts \
+ i18n/lumina-wm_bg.ts \
+ i18n/lumina-wm_bn.ts \
+ i18n/lumina-wm_bs.ts \
+ i18n/lumina-wm_ca.ts \
+ i18n/lumina-wm_cs.ts \
+ i18n/lumina-wm_cy.ts \
+ i18n/lumina-wm_da.ts \
+ i18n/lumina-wm_de.ts \
+ i18n/lumina-wm_el.ts \
+ i18n/lumina-wm_en_GB.ts \
+ i18n/lumina-wm_en_ZA.ts \
+ i18n/lumina-wm_es.ts \
+ i18n/lumina-wm_et.ts \
+ i18n/lumina-wm_eu.ts \
+ i18n/lumina-wm_fa.ts \
+ i18n/lumina-wm_fi.ts \
+ i18n/lumina-wm_fr.ts \
+ i18n/lumina-wm_fr_CA.ts \
+ i18n/lumina-wm_gl.ts \
+ i18n/lumina-wm_he.ts \
+ i18n/lumina-wm_hi.ts \
+ i18n/lumina-wm_hr.ts \
+ i18n/lumina-wm_hu.ts \
+ i18n/lumina-wm_id.ts \
+ i18n/lumina-wm_is.ts \
+ i18n/lumina-wm_it.ts \
+ i18n/lumina-wm_ja.ts \
+ i18n/lumina-wm_ka.ts \
+ i18n/lumina-wm_ko.ts \
+ i18n/lumina-wm_lt.ts \
+ i18n/lumina-wm_lv.ts \
+ i18n/lumina-wm_mk.ts \
+ i18n/lumina-wm_mn.ts \
+ i18n/lumina-wm_ms.ts \
+ i18n/lumina-wm_mt.ts \
+ i18n/lumina-wm_nb.ts \
+ i18n/lumina-wm_nl.ts \
+ i18n/lumina-wm_pa.ts \
+ i18n/lumina-wm_pl.ts \
+ i18n/lumina-wm_pt.ts \
+ i18n/lumina-wm_pt_BR.ts \
+ i18n/lumina-wm_ro.ts \
+ i18n/lumina-wm_ru.ts \
+ i18n/lumina-wm_sk.ts \
+ i18n/lumina-wm_sl.ts \
+ i18n/lumina-wm_sr.ts \
+ i18n/lumina-wm_sv.ts \
+ i18n/lumina-wm_sw.ts \
+ i18n/lumina-wm_ta.ts \
+ i18n/lumina-wm_tg.ts \
+ i18n/lumina-wm_th.ts \
+ i18n/lumina-wm_tr.ts \
+ i18n/lumina-wm_uk.ts \
+ i18n/lumina-wm_uz.ts \
+ i18n/lumina-wm_vi.ts \
+ i18n/lumina-wm_zh_CN.ts \
+ i18n/lumina-wm_zh_HK.ts \
+ i18n/lumina-wm_zh_TW.ts \
+ i18n/lumina-wm_zu.ts
+
+dotrans.path=$$PREFIX/share/Lumina-DE/i18n/
+dotrans.extra=cd i18n && $${LRELEASE} -nounfinished *.ts && cp *.qm $(INSTALL_ROOT)$$PREFIX/share/Lumina-DE/i18n/
+
+INSTALLS += target dotrans
diff --git a/lumina-wm/main.cpp b/lumina-wm/main.cpp
new file mode 100644
index 00000000..b19b00e3
--- /dev/null
+++ b/lumina-wm/main.cpp
@@ -0,0 +1,40 @@
+//===========================================
+// Lumina-DE source code
+// Copyright (c) 2015, Ken Moore
+// Available under the 3-clause BSD license
+// See the LICENSE file for full details
+//===========================================
+#include <QDebug>
+
+#include <QFile>
+#include <QDir>
+#include <QString>
+#include <QTextStream>
+#include <QUrl>
+
+
+#include "WMSession.h"
+
+#include <LuminaXDG.h> //from libLuminaUtils
+#include <LuminaThemes.h>
+#include <LuminaSingleApplication.h>
+
+//#define DEBUG 0
+
+int main(int argc, char ** argv)
+{
+ LSingleApplication a(argc, argv, "lumina-wm");
+ if(!a.isPrimaryProcess()){ return 0; } //Inputs forwarded on to the primary already
+ LuminaThemeEngine themes(&a);
+
+ //Setup the special settings prefix location
+ QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, QDir::homePath()+"/.lumina");
+
+ WMSession w;
+ w.start();
+ QObject::connect(themes, SIGNAL(updateIcons()), &w, SLOT(reloadIcons()) );
+ QObject::connect(a, SIGNAL(InputsAvailable(QStringList)), &w, SLOT(newInputsAvailable(QStringList)) );
+ int retCode = a.exec();
+
+ return retCode;
+}
bgstack15