source: src-qt4/PCDM/src/pcdm-gui.cpp @ f8b7298

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since f8b7298 was f8b7298, checked in by Ken Moore <ken@…>, 14 months ago

Turn off the debugging mode for the PCDM GUI (close PCDM option)

  • Property mode set to 100644
File size: 20.3 KB
Line 
1/* PCDM Login Manager:
2*  Written by Ken Moore (ken@pcbsd.org) 2012/2013
3*  Copyright(c) 2013 by the PC-BSD Project
4*  Available under the 3-clause BSD license
5*/
6
7#include <QProcess>
8#include <QTimer>
9#include <QGraphicsPixmapItem>
10#include <QStyle>
11#include <pcbsd-utils.h>
12
13#include "pcdm-gui.h"
14#include "pcdm-backend.h"
15#include "fancySwitcher.h"
16
17bool DEBUG_MODE=FALSE;
18QString VIRTUALKBDBIN="/usr/local/bin/xvkbd -compact";
19
20PCDMgui::PCDMgui() : QMainWindow()
21{
22    //Load the Theme
23    loadTheme();
24    //Create the GUI based upon the current Theme
25    createGUIfromTheme();
26    //Put the background image on all the other screens
27    fillExtraScreens();
28    //Now make sure that the login widget has keyboard focus
29    loginW->resetFocus();
30    this->setObjectName("PCDM-background");
31}
32
33PCDMgui::~PCDMgui()
34{
35    //delete ui;
36}
37
38void PCDMgui::loadTheme(){
39  currentTheme = new ThemeStruct();
40  QString themeFile = Config::themeFile();
41  if(!QFile::exists(themeFile)){ themeFile = ":samples/themes/default/default.theme"; }
42  currentTheme->loadThemeFile( themeFile );
43  //Check the Theme, using default values as necessary
44  QStringList invalid = currentTheme->invalidItems();
45  if( !invalid.isEmpty() ){
46    ThemeStruct* defaultTheme = new ThemeStruct();
47    defaultTheme->loadThemeFile( ":samples/themes/default/default.theme" );
48    for( int i=0; i<invalid.length(); i++){
49      //Replace the invalid items with the defaults
50      qDebug() << "Invalid Theme Item, Using defaults:" << invalid[i];
51      currentTheme->importItem( invalid[i] , defaultTheme->exportItem(invalid[i]) );
52    }
53  }
54 
55}
56
57void PCDMgui::createGUIfromTheme(){
58  QString style;
59  QString tmpIcon; //used for checking image files before loading them
60  //Set the background image
61  if(DEBUG_MODE){ qDebug() << "Setting Background Image"; }
62  if( currentTheme->itemIsEnabled("background") ){
63    tmpIcon = currentTheme->itemIcon("background");
64    if( tmpIcon.isEmpty() || !QFile::exists(tmpIcon) ){ tmpIcon = ":/images/backgroundimage.jpg"; }
65    //use "border-image" instead of "background-image" to stretch rather than tile the image
66    QString bgstyle = "QMainWindow#PCDM-background {border-image: url(BGIMAGE) stretch;}"; 
67    bgstyle.replace("BGIMAGE", tmpIcon);
68    style.append(bgstyle);
69  }
70  //Set the application style sheet
71  style.append(" "+ currentTheme->styleSheet() );
72  this->setStyleSheet( style.simplified() );
73
74  //Check for whether the desktop switcher is on the toolbar or not
75  simpleDESwitcher = (currentTheme->itemValue("desktop") == "simple");
76 
77  //get the default translation directory
78  if(DEBUG_MODE){ qDebug() << "Load Translations"; }
79  translationDir = "/usr/local/share/PCDM/i18n/";
80  //Fill the translator
81  m_translator = new QTranslator();
82  //Create the Toolbar
83  toolbar = new QToolBar();
84  //Add the Toolbar to the window
85  if(DEBUG_MODE){ qDebug() << "Create Toolbar"; }
86    //use the theme location   
87    QString tarea = currentTheme->itemValue("toolbar");
88    if(tarea == "left"){
89      this->addToolBar( Qt::LeftToolBarArea, toolbar );             
90    }else if( tarea=="top"){
91      this->addToolBar( Qt::TopToolBarArea, toolbar );             
92    }else if(tarea=="right"){
93      this->addToolBar( Qt::RightToolBarArea, toolbar );           
94    }else{ //bottom is default
95      this->addToolBar( Qt::BottomToolBarArea, toolbar );       
96    }
97    //Set toolbar flags
98    toolbar->setVisible(TRUE);
99    toolbar->setMovable(FALSE);
100    toolbar->setFloatable(FALSE);
101    //Set the default style and icon sizes
102    QString tstyle = currentTheme->itemIcon("toolbar").toLower(); //use the theme style
103    if(tstyle=="textonly"){ toolbar->setToolButtonStyle(Qt::ToolButtonTextOnly); }
104    else if(tstyle=="textbesideicon"){ toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); }
105    else if(tstyle=="textundericon"){ toolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); }
106    else{ toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly); } //default to icon only
107   
108    toolbar->setIconSize( currentTheme->itemIconSize("toolbar") ); //use theme size
109    toolbar->setFocusPolicy( Qt::NoFocus );
110  //Populate the Toolbar with items (starts at leftmost/topmost)
111    //----Virtual Keyboard
112    if(currentTheme->itemIsEnabled("vkeyboard") ){
113      if(DEBUG_MODE){ qDebug() << " - Create Virtual Keyboard Button"; }
114      tmpIcon = currentTheme->itemIcon("vkeyboard");
115      if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/input-keyboard.png"; }
116      virtkeyboardButton = new QAction( QIcon(tmpIcon),tr("Virtual Keyboard"),this );
117      toolbar->addAction(virtkeyboardButton);
118      connect( virtkeyboardButton, SIGNAL(triggered()), this, SLOT(slotPushVirtKeyboard()) );
119    }else{
120      virtkeyboardButton = new QAction(this);
121    }
122
123    //----Locale Switcher
124    if(DEBUG_MODE){ qDebug() << " - Create Locale Button"; }
125    tmpIcon = currentTheme->itemIcon("locale");
126    if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/language.png"; }
127    localeButton = new QAction( QIcon(tmpIcon),tr("Locale"),this );
128    toolbar->addAction(localeButton);
129    connect( localeButton, SIGNAL(triggered()), this, SLOT(slotChangeLocale()) );
130   
131    //----Keyboard Layout Switcher
132    if(DEBUG_MODE){ qDebug() << " - Create Keyboard Layout Button"; }
133    tmpIcon = currentTheme->itemIcon("keyboard");
134    if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/keyboard.png"; }
135    keyboardButton = new QAction( QIcon(tmpIcon),tr("Keyboard Layout"),this );
136    toolbar->addAction(keyboardButton);
137    connect( keyboardButton, SIGNAL(triggered()), this, SLOT(slotChangeKeyboardLayout()) );
138
139    //----Add a spacer
140    QWidget* spacer = new QWidget();
141    spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
142    toolbar->addWidget(spacer);
143       
144    //----System Shutdown/Restart
145    if(DEBUG_MODE){ qDebug() << " - Create System Button"; }
146    tmpIcon = currentTheme->itemIcon("system");
147    if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/system.png"; }
148    QAction* act = new QAction( QIcon(tmpIcon),tr("System"),this );
149    systemButton = new QToolButton();
150    systemButton->setDefaultAction(act);
151    systemMenu = new QMenu();
152    toolbar->addWidget(systemButton);
153    systemButton->setPopupMode( QToolButton::InstantPopup );
154    systemButton->setFocusPolicy( Qt::NoFocus );
155   
156  //Create the grid layout
157  QGridLayout* grid = new QGridLayout;
158  if(DEBUG_MODE){ qDebug() << "Fill Desktop Area"; }
159  //Populate the grid with items
160    //----Header Image
161    QLabel* header = new QLabel; 
162    if( currentTheme->itemIsEnabled("header") ){
163      if(DEBUG_MODE){ qDebug() << " - Create Header"; }
164      tmpIcon = currentTheme->itemIcon("header");
165      if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/banner.png"; }
166      QPixmap tmp( tmpIcon );
167      header->setPixmap( tmp.scaled( currentTheme->itemIconSize("header") ) );
168      grid->addWidget( header, currentTheme->itemLocation("header","row"), \
169                      currentTheme->itemLocation("header","col"), \
170                      currentTheme->itemLocation("header","rowspan"), \
171                      currentTheme->itemLocation("header","colspan"), Qt::AlignCenter);
172    }
173   
174    //Username/Password/Login widget
175    if(DEBUG_MODE){ qDebug() << " - Create Login Widget"; }
176    loginW = new LoginWidget;
177    loginW->setUsernames(Backend::getSystemUsers()); //add in the detected users
178    QString lastUser = Backend::getLastUser();
179    if(!lastUser.isEmpty()){ //set the previously used user
180        loginW->setCurrentUser(lastUser); 
181    } 
182    //Set Icons from theme
183    tmpIcon = currentTheme->itemIcon("login");
184    if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/next.png"; }
185    loginW->changeButtonIcon("login",tmpIcon, currentTheme->itemIconSize("login"));
186    tmpIcon = currentTheme->itemIcon("user");
187    slotUserChanged(loginW->currentUsername()); //Make sure that we have the correct user icon
188    tmpIcon = currentTheme->itemIcon("password");
189    if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/password.png"; }
190    loginW->changeButtonIcon("pwview",tmpIcon, currentTheme->itemIconSize("password"));
191    //Enable/disable the password view functionality
192    loginW->allowPasswordView( Config::allowPasswordView() );
193    //Add item to the grid
194    grid->addWidget( loginW, currentTheme->itemLocation("login","row"), \
195                      currentTheme->itemLocation("login","col"), \
196                      currentTheme->itemLocation("login","rowspan"), \
197                      currentTheme->itemLocation("login","colspan"), Qt::AlignCenter);
198    //Connect the signals/slots
199    connect(loginW,SIGNAL(loginRequested(QString,QString)),this,SLOT(slotStartLogin(QString,QString)));
200    connect(loginW,SIGNAL(escapePressed()),this,SLOT(slotShutdownComputer()));
201    connect(loginW,SIGNAL(UserSelected(QString)), this, SLOT(slotUserSelected(QString)) );
202    connect(loginW,SIGNAL(UserChanged(QString)), this, SLOT(slotUserChanged(QString)) );
203   
204    //----Desktop Environment Switcher
205    if(simpleDESwitcher){
206      loginW->setDesktopIconSize(currentTheme->itemIconSize("desktop"));
207    }else{
208      if(DEBUG_MODE){ qDebug() << " - Create DE Switcher"; }
209      //Create the switcher
210      deSwitcher = new FancySwitcher(this, !currentTheme->itemIsVertical("desktop") );
211      QSize deSize = currentTheme->itemIconSize("desktop");
212      deSwitcher->setIconSize(deSize.height());
213      tmpIcon = currentTheme->itemIcon("nextde");
214      if( !tmpIcon.isEmpty() && QFile::exists(tmpIcon) ){ deSwitcher->changeButtonIcon("forward", tmpIcon); }
215      tmpIcon = currentTheme->itemIcon("previousde");
216      if( !tmpIcon.isEmpty() && QFile::exists(tmpIcon) ){ deSwitcher->changeButtonIcon("back", tmpIcon); }
217      //Figure out if we need to smooth out the animation
218      deSwitcher->setNumberAnimationFrames("4"); 
219      //NOTE: A transparent widget background slows the full animation to a crawl with a stretched background image
220
221      grid->addWidget( deSwitcher, currentTheme->itemLocation("desktop","row"), \
222                      currentTheme->itemLocation("desktop","col"), \
223                      currentTheme->itemLocation("desktop","rowspan"), \
224                      currentTheme->itemLocation("desktop","colspan"), Qt::AlignCenter);
225    }
226    //----WINDOW SPACERS
227    QStringList spacers = currentTheme->getSpacers();
228    for(int i=0; i<spacers.length(); i++){
229      bool isVertical = (spacers[i].section("::",0,0) == "true");
230      int row = spacers[i].section("::",1,1).toInt();
231      int col = spacers[i].section("::",2,2).toInt();
232      //qDebug() << "Add Spacer:" << isVertical << row << col;
233      if(isVertical){
234        grid->setRowStretch(row,1);
235      }else{ //horizontal
236        grid->setColumnStretch(col,1);
237      }
238    }
239
240  //Connect the grid to the Window
241    QWidget* widget = new QWidget;
242    widget->setLayout(grid);
243    this->setCentralWidget(widget);
244   
245  //Now translate the UI and set all the text
246  if(DEBUG_MODE){ qDebug() << " - Fill GUI with data"; }
247  retranslateUi();
248  if(DEBUG_MODE){ qDebug() << "Done with initialization"; }
249
250}
251
252void PCDMgui::fillExtraScreens(){
253    //Set a background image on any other available screens
254    QDesktopWidget *DE = QApplication::desktop();
255    screens.clear();
256    //Generate the background style sheet
257    QString tmpIcon = currentTheme->itemIcon("background");
258    if( tmpIcon.isEmpty() || !QFile::exists(tmpIcon) ){ tmpIcon = ":/images/backgroundimage.jpg"; }
259    QString bgstyle = "border-image: url(BGIMAGE) stretch;"; 
260      bgstyle.replace("BGIMAGE", tmpIcon);
261    //Now apply the background to all the other screens   
262    for(int i=0; i<DE->screenCount(); i++){
263      if(i != DE->screenNumber(this)){
264        //Just show a generic QWidget with the proper background image on every other screen
265        QWidget *screen = new QWidget(0, Qt::X11BypassWindowManagerHint);
266        screen->setGeometry( DE->screenGeometry(i) );
267        screen->setStyleSheet(bgstyle);
268        screen->show();
269        screens << screen;
270      }
271    }   
272}
273
274void PCDMgui::slotStartLogin(QString displayname, QString password){
275  //Get user inputs
276  QString username = Backend::getUsernameFromDisplayname(displayname);
277  QString desktop;
278  if(simpleDESwitcher){
279    desktop = loginW->currentDE();
280  }else{
281    desktop = deSwitcher->currentItem();
282  }
283  //Disable user input while confirming login
284  loginW->setEnabled(FALSE);
285  if(!simpleDESwitcher){ deSwitcher->setEnabled(FALSE); }
286  toolbar->setEnabled(FALSE);
287  //Try to login
288  emit xLoginAttempt(username, password, desktop);
289  //Return signals are connected to the slotLogin[Success/Failure] functions
290 
291}
292
293void PCDMgui::slotLoginSuccess(){
294  /*QString de;
295  if(simpleDESwitcher){ de = loginW->currentDE(); }
296  else{ de = deSwitcher->currentItem(); }
297  saveLastLogin( loginW->currentUsername(), de );*/
298  slotClosePCDM(); //now start to close down the PCDM GUI
299}
300
301void PCDMgui::slotLoginFailure(){
302  //Display an info box that the login failed
303  QMessageBox notice(this);
304    notice.setWindowTitle(tr("Invalid Username/Password"));
305    notice.setIcon(QMessageBox::Warning);
306    notice.setText(tr("Username/Password combination is invalid, please try again."));
307    notice.setInformativeText("("+tr("Tip: Make sure that caps-lock is turned off.")+")");
308    notice.setStandardButtons(QMessageBox::Ok);
309    notice.setDefaultButton(QMessageBox::Ok);
310    notice.exec();
311       
312  //Re-Enable user input
313  loginW->setEnabled(TRUE);
314  if(!simpleDESwitcher){ deSwitcher->setEnabled(TRUE); }
315  toolbar->setEnabled(TRUE);
316}
317
318void PCDMgui::slotUserChanged(QString newuser){
319  if( !newuser.isEmpty() ){
320    //Try to load the custom user icon
321    QString tmpIcon = Backend::getUserHomeDir(newuser) + "/.loginIcon.png";
322    if(!QFile::exists(tmpIcon) ){ tmpIcon= currentTheme->itemIcon("user"); }
323    if(!QFile::exists(tmpIcon) || tmpIcon.isEmpty() ){ tmpIcon=":/images/user.png"; }
324    loginW->changeButtonIcon("display",tmpIcon, currentTheme->itemIconSize("user"));
325  }
326}
327
328void PCDMgui::slotUserSelected(QString newuser){
329  if(DEBUG_MODE){ qDebug() << "User selection changed:" << newuser; }
330  if(newuser.isEmpty()){
331    if(!simpleDESwitcher){ deSwitcher->setVisible(FALSE); }
332  }else{
333    if(!simpleDESwitcher){ deSwitcher->setVisible(TRUE); }
334    //Try to load the custom user icon
335    slotUserChanged(newuser);
336  }
337  retranslateUi();
338}
339
340void PCDMgui::slotShutdownComputer(){
341  QMessageBox verify;
342  verify.setWindowTitle(tr("System Shutdown"));
343  verify.setText(tr("You are about to shut down the system."));
344  verify.setInformativeText(tr("Are you sure?"));
345  verify.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
346  verify.setDefaultButton(QMessageBox::No);
347  int ret = verify.exec();
348
349  if(ret == QMessageBox::Yes){
350    Backend::log("PCDM: Shutting down computer");
351    system("shutdown -p now");
352    close();
353  }
354}
355
356void PCDMgui::slotRestartComputer(){
357  QMessageBox verify;
358  verify.setWindowTitle(tr("System Restart"));
359  verify.setText(tr("You are about to restart the system."));
360  verify.setInformativeText(tr("Are you sure?"));
361  verify.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
362  verify.setDefaultButton(QMessageBox::No);
363  int ret = verify.exec();
364
365  if(ret == QMessageBox::Yes){
366    Backend::log("PCDM: Restarting computer");
367    system("shutdown -r now");
368    close();
369  }
370}
371
372void PCDMgui::slotClosePCDM(){
373  system("killall -9 xvkbd"); //be sure to close the virtual keyboard
374  for(int i=0; i<screens.length(); i++){ screens[i]->close(); } //close all the other screens
375  QCoreApplication::exit(0);
376  close();
377}
378
379void PCDMgui::slotChangeLocale(){
380  //Open the selector
381  wLoc = new widgetLocale();
382  QLocale currLocale = this->locale();
383  Backend::log("Current PCDM Locale: " + currLocale.name() );
384  wLoc->setCurrentLocale(currLocale.name());
385  wLoc->setWindowModality(Qt::ApplicationModal);
386  wLoc->show();
387  wLoc->raise();
388
389  //Connect the language changed signal
390  connect(wLoc,SIGNAL(languageChanged(QString)),this,SLOT(slotLocaleChanged(QString)) );
391}
392
393void PCDMgui::slotLocaleChanged(QString langCode){
394  //Get the valid Locale code
395  QString translationFile;
396  if(!QFile::exists(translationDir+"PCDM_"+langCode+".qm")){
397    langCode = langCode.section("_",0,0);
398    if(!QFile::exists(translationDir+"PCDM_"+langCode+".qm")){
399      if(!QFile::exists(translationDir+"qt_"+langCode+".qm")){
400        Backend::log("Desired locale is not a valid translation: " + langCode);
401        return;
402      }else{
403        translationFile = translationDir+"qt_"+langCode+".qm";     
404      }
405    }else{
406      translationFile = translationDir+"PCDM_"+langCode+".qm";     
407    }
408  }else{
409    translationFile = translationDir+"PCDM_"+langCode+".qm";
410  }     
411       
412  Backend::log("Changing localization to " + langCode);
413
414  //Alternate method for changing Locale
415  QLocale locale(langCode);
416  this->setLocale(locale);
417  //this->setDefaultLocale(locale);
418  //Change the translator
419  if( !m_translator->isEmpty() ){
420    Backend::log("Remove the translator");
421    QCoreApplication::removeTranslator(m_translator);
422  }
423
424  if(m_translator->load(translationFile)){
425    Backend::log("Install the new translator: "+translationFile);
426    QCoreApplication::installTranslator(m_translator);   
427  }
428  //Re-draw the interface
429  retranslateUi();
430 
431  Backend::log("Current Locale after change: " + this->locale().name() );
432}
433
434void PCDMgui::slotChangeKeyboardLayout(){
435  //Fill a couple global variables
436  QStringList kModels = Backend::keyModels();
437  QStringList kLayouts = Backend::keyLayouts();
438  //Startup the GUI
439  wKey = new widgetKeyboard();
440  wKey->programInit(kModels, kLayouts);
441  wKey->setWindowModality(Qt::ApplicationModal);
442  wKey->show();
443  wKey->raise();
444}
445
446// Start xvkbd
447void PCDMgui::slotPushVirtKeyboard(){
448   QString cmd = "killall -9 "+VIRTUALKBDBIN.section(" ",0,0).section("/",-1)+"; "+VIRTUALKBDBIN+" &";
449   qDebug() << "Starting Virtual Keyboard:";
450   qDebug() << " - CMD: "+cmd;
451   system( cmd.toUtf8() );
452   loginW->resetFocus("password");
453}
454
455void PCDMgui::retranslateUi(){
456  //All the text-setting for the main interface needs to be done here
457  //virtual keyboard button
458  //if(currentTheme->itemIsEnabled("vkeyboard")){
459    virtkeyboardButton->setToolTip(tr("Virtual Keyboard"));
460    virtkeyboardButton->setText(tr("Virtual Keyboard"));
461  //}
462  //locale switcher button
463  localeButton->setToolTip(tr("Change locale"));
464  localeButton->setText(tr("Locale"));
465  //keyboard layout button
466  keyboardButton->setToolTip(tr("Change Keyboard Layout"));
467  keyboardButton->setText(tr("Keyboard Layout"));
468  //system button
469  systemButton->defaultAction()->setToolTip(tr("Shutdown the computer"));
470  systemButton->defaultAction()->setText(tr("System"));
471  //Menu entries for system button
472    systemMenu->clear();       
473    systemMenu->addAction( tr("Restart"),this, SLOT(slotRestartComputer()) );
474    systemMenu->addAction( tr("Shut Down"), this, SLOT(slotShutdownComputer()) );
475    if(DEBUG_MODE){systemMenu->addAction( tr("Close PCDM"), this, SLOT(slotClosePCDM()) ); }
476    systemButton->setMenu(systemMenu);
477  //The main login widget
478  if(hostname.isEmpty()){
479    //Find the system hostname
480    hostname = pcbsd::Utils::runShellCommand("hostname").join(" ").simplified();
481    loginW->displayHostName(hostname);   
482  }
483  loginW->retranslateUi();
484 
485  //The desktop switcher
486 
487    //Get the new desktop list (translated)
488    QStringList deList = Backend::getAvailableDesktops();
489    QString lastDE = Backend::getLastDE(loginW->currentUsername());
490    //Now fill the switcher
491    if(!simpleDESwitcher){
492      deSwitcher->removeAllItems();
493      for(int i=0; i<deList.length(); i++){
494        QString deIcon = Backend::getDesktopIcon(deList[i]);
495        if( deIcon.isEmpty() ){ deIcon = currentTheme->itemIcon("desktop"); } //set the default icon if none given
496        if( !QFile::exists(deIcon) ){ deIcon = ":/images/desktop.png"; }
497        //Now add the item back to the widget
498        deSwitcher->addItem( deList[i], deIcon, Backend::getDesktopComment(deList[i]) );
499      }
500      //Set the switcher to the last used desktop environment
501      if( !lastDE.isEmpty() ){ deSwitcher->setCurrentItem(lastDE); }
502
503    }else{
504      //Simple switcher on the login widget
505      QStringList deIcons, deInfo;
506      for(int i=0; i<deList.length(); i++){ 
507        QString ico = Backend::getDesktopIcon(deList[i]);
508        if(ico.isEmpty()){ ico = currentTheme->itemIcon("desktop"); }
509        if(!QFile::exists(ico)){ ico = ":/images/desktop.png"; }
510        deIcons << ico;
511        deInfo << Backend::getDesktopComment(deList[i]);
512      }
513      loginW->setDesktops(deList, deIcons, deInfo);
514      //Set the switcher to the last used desktop environment
515      loginW->setCurrentDE(lastDE);
516    }
517
518}
519
Note: See TracBrowser for help on using the repository browser.