1 //===========================================
2 //  Lumina-DE source code
3 //  Copyright (c) 2014, Ken Moore
4 //  Available under the 3-clause BSD license
5 //  See the LICENSE file for full details
6 //===========================================
7 #include "MainUI.h"
8 #include "ui_MainUI.h"
9 
10 #include "ConfigUI.h"
11 
12 #include <LUtils.h>
13 
MainUI()14 MainUI::MainUI() : QMainWindow(), ui(new Ui::MainUI){
15   ui->setupUi(this); //load the designer file
16   //setupIcons();
17   ui->radio_apps->setChecked(true); //always default to starting here
18   ui->tool_stop->setVisible(false); //no search running initially
19   ui->tool_configure->setVisible(false); //app search initially set
20 
21   livetime = new QTimer(this);
22     livetime->setInterval(500); //1/2 second for live searches
23     livetime->setSingleShot(true);
24 
25   workthread = new QThread(this);
26 	workthread->setObjectName("Lumina Search Process");
27 
28   searcher = new Worker();
29     searcher->moveToThread(workthread);
30 
31   closeShort = new QShortcut(QKeySequence(tr("Esc")), this);
32 
33   //Setup the connections
34   connect(livetime, SIGNAL(timeout()), this, SLOT(startSearch()) );
35   connect(this, SIGNAL(SearchTerm(QString, bool)), searcher, SLOT(StartSearch(QString, bool)) );
36   connect(searcher, SIGNAL(FoundItem(QString)), this, SLOT(foundSearchItem(QString)) );
37   connect(searcher, SIGNAL(SearchUpdate(QString)), this, SLOT(searchMessage(QString)) );
38   connect(searcher, SIGNAL(SearchDone()), this, SLOT(searchFinished()) );
39   connect(ui->tool_stop, SIGNAL(clicked()), this, SLOT(stopSearch()) );
40   connect(ui->push_done, SIGNAL(clicked()), this, SLOT(closeApplication()) );
41   connect(ui->push_launch, SIGNAL(clicked()), this, SLOT(LaunchItem()) );
42   connect(ui->line_search, SIGNAL(textEdited(QString)), this, SLOT(searchChanged()) );
43   connect(ui->line_search, SIGNAL(returnPressed()), this, SLOT(LaunchItem()) );
44   connect(ui->radio_apps, SIGNAL(toggled(bool)), this, SLOT(searchTypeChanged()) );
45   connect(ui->listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(LaunchItem(QListWidgetItem*)) );
46   connect(ui->listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(LaunchItem(QListWidgetItem*)) );
47   connect(ui->tool_configure, SIGNAL(clicked()), this, SLOT(configureSearch()) );
48   connect(closeShort, SIGNAL(activated()), this, SLOT( close() ) );
49 
50   //Setup the settings file
51   settings = LUtils::openSettings("lumina-desktop", "lumina-search",this);
52   searcher->startDir = settings->value("StartSearchDir", QDir::homePath()).toString();
53   searcher->skipDirs = settings->value("SkipSearchDirs", QStringList()).toStringList();
54   updateDefaultStatusTip();
55   this->show();
56   workthread->start();
57   QTimer::singleShot(0,this, SLOT(setupIcons()) );
58 }
59 
~MainUI()60 MainUI::~MainUI(){
61   searcher->StopSearch();
62   workthread->quit();
63   workthread->wait();
64 }
65 
setupIcons()66 void MainUI::setupIcons(){
67   //Setup the icons
68   this->setWindowIcon( LXDG::findIcon("edit-find","") );
69   ui->push_launch->setIcon( LXDG::findIcon("quickopen","") );
70   ui->push_done->setIcon( LXDG::findIcon("window-close","") );
71   ui->tool_stop->setIcon( LXDG::findIcon("dialog-cancel","") );
72   ui->tool_configure->setIcon( LXDG::findIcon("configure","") );
73 }
74 
75 // ===============
76 //    PUBLIC FUNCTIONS (for input handling primarily)
77 // ===============
disableExcludes()78 void MainUI::disableExcludes(){
79   searcher->skipDirs.clear();
80   updateDefaultStatusTip();
81 }
82 
setSearchDirectory(QString path)83 void MainUI::setSearchDirectory(QString path){
84   ui->radio_files->setChecked(true);
85   searcher->startDir = path;
86   updateDefaultStatusTip();
87 }
88 
setSearchTerm(QString text)89 void MainUI::setSearchTerm(QString text){
90   ui->line_search->setText(text);
91 }
92 
93 //==============
94 //  PRIVATE
95 //==============
updateDefaultStatusTip()96 void MainUI::updateDefaultStatusTip(){
97   if(ui->radio_files->isChecked()){
98     QString txt = tr("Search: %1 -- Smart: %2");
99     QString dir = searcher->startDir;
100       dir.replace(QDir::homePath(), "~");
101     QString smart = searcher->skipDirs.isEmpty() ? tr("Off"): tr("On");
102     txt = txt.arg(dir,smart);
103     ui->statusbar->showMessage(txt);
104   }
105 }
106 
107 //==============
108 //  PRIVATE SLOTS
109 //==============
LaunchItem()110 void MainUI::LaunchItem(){
111 int index = ui->listWidget->currentRow();
112 if(index<0 && ui->listWidget->count()>0){ index = 0; } //grab the first item instead
113 else if(index<0){ return; } //no items available/selected
114 QString item = ui->listWidget->item(index)->whatsThis();
115 QProcess::startDetached("lumina-open \""+item+"\"");
116 //Close the search utility if an application was launched (quick launch functionality)
117 if(ui->radio_apps->isChecked()){ this->close(); }
118 }
119 
LaunchItem(QListWidgetItem * item)120 void MainUI::LaunchItem(QListWidgetItem *item){
121     QProcess::startDetached("lumina-open \""+item->whatsThis()+"\"");
122 }
123 
searchTypeChanged()124 void MainUI::searchTypeChanged(){
125   startSearch();
126 }
127 
configureSearch()128 void MainUI::configureSearch(){
129   ConfigUI dlg(this);
130     dlg.loadInitialValues( settings->value("StartSearchDir",QDir::homePath()).toString(), settings->value("SkipSearchDirs",QStringList()).toStringList());
131     dlg.exec();
132   if(dlg.newStartDir.isEmpty()){ return; }//cancelled
133   QString startdir = dlg.newStartDir;
134   QStringList skipdirs = dlg.newSkipDirs;
135 
136   //Save these values for later (if selected)
137   if(dlg.newDefaults){
138     //save these values as the new defaults
139     settings->setValue("StartSearchDir", startdir);
140     settings->setValue("SkipSearchDirs", skipdirs);
141   }
142 
143   //Set these values in the searcher
144   searcher->startDir = startdir;
145   searcher->skipDirs = skipdirs;
146   updateDefaultStatusTip();
147 }
148 
searchChanged()149 void MainUI::searchChanged(){
150   if(livetime->isActive()){ livetime->stop(); }
151   livetime->start();
152 }
153 
154 //Worker Interaction
startSearch()155 void MainUI::startSearch(){
156   ui->listWidget->clear();
157   stopSearch(); //just in case a search is still running
158   if(ui->line_search->text().isEmpty()){ updateDefaultStatusTip(); return; } //nothing to search for
159 
160   //emit the proper signal for the worker
161   if(!workthread->isRunning()){ workthread->start(); } //make sure the thread is running
162   emit SearchTerm(ui->line_search->text(), ui->radio_apps->isChecked());
163   ui->tool_stop->setVisible(true);
164   ui->tool_configure->setVisible(false);
165 }
166 
foundSearchItem(QString path)167 void MainUI::foundSearchItem(QString path){
168    //To get the worker's results
169   QListWidgetItem *it = new QListWidgetItem;
170     it->setWhatsThis(path);
171     it->setToolTip(path);
172   //Now setup the visuals
173   if(path.simplified().endsWith(".desktop")){
174     bool ok = false;
175     XDGDesktop desk(path);
176     if( !desk.isValid() ){delete it; return; } //invalid file
177     it->setText(desk.name);
178     it->setIcon( LXDG::findIcon(desk.icon, "application-x-desktop") );
179   }else{
180     if(QFileInfo(path).isDir()){
181       it->setIcon( LXDG::findIcon("inode-directory","") );
182       it->setText( path.replace(QDir::homePath(), "~") );
183     }else{
184       if(QFileInfo(path).isExecutable()){
185 	it->setIcon( LXDG::findIcon("application-x-executable","") );
186       }else{
187         it->setIcon( LXDG::findMimeIcon(path.section("/",-1).section(".",-1)) );
188       }
189       it->setText( path.section("/",-1) );
190     }
191 
192   }
193   //Now add it to the widget
194   ui->listWidget->addItem(it);
195   if(ui->listWidget->count()>100){ searcher->StopSearch(); } //just in case
196 }
197 
stopSearch()198 void MainUI::stopSearch(){
199   searcher->StopSearch();
200   ui->tool_stop->setVisible(false);
201   ui->tool_configure->setVisible(ui->radio_files->isChecked());
202   updateDefaultStatusTip();
203 }
204 
searchMessage(QString msg)205 void MainUI::searchMessage(QString msg){
206   ui->statusbar->showMessage(msg,2000);
207 }
208 
searchFinished()209 void MainUI::searchFinished(){
210   ui->tool_stop->setVisible(false);
211   ui->tool_configure->setVisible(ui->radio_files->isChecked());
212   updateDefaultStatusTip();
213 }
214