1 //===========================================
2 // Lumina-DE source code
3 // Copyright (c) 2013, Ken Moore
4 // Available under the 3-clause BSD license
5 // See the LICENSE file for full details
6 //===========================================
7 #include "LFileDialog.h"
8 #include "ui_LFileDialog.h"
9
LFileDialog(QWidget * parent)10 LFileDialog::LFileDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LFileDialog() ){
11 ui->setupUi(this); //load the designer file
12 //set the output flags to the defaults
13 appSelected = false;
14 setDefault = false;
15 appExec.clear();
16 appPath.clear();
17 appFile.clear();
18 settings = new QSettings("lumina-desktop", "lumina-open", this);
19 //Connect the signals/slots
20 connect(ui->combo_apps, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()) );
21 connect(ui->radio_rec, SIGNAL(toggled(bool)), this, SLOT(radioChanged()) );
22 connect(ui->radio_avail, SIGNAL(toggled(bool)), this, SLOT(radioChanged()) );
23 connect(ui->radio_custom, SIGNAL(toggled(bool)), this, SLOT(radioChanged()) );
24 }
25
~LFileDialog()26 LFileDialog::~LFileDialog(){
27
28 }
29
30 // ----------
31 // PUBLIC
32 // ----------
setFileInfo(QString filename,QString extension,bool isFile)33 void LFileDialog::setFileInfo(QString filename, QString extension, bool isFile){
34 //Set the labels for the file
35 qDebug() << "SetFileInfo:" << filename << extension << isFile;
36 filePath = filename; //save for later
37 ui->label_file->setText( this->fontMetrics().elidedText( filename, Qt::ElideMiddle, 300 ) );
38 bool shownetwork = false;
39 if(isFile){ ui->label_extension->setText( "("+extension+")"); }
40 else if(extension=="email"){ ui->label_extension->setText( QString(tr("(Email Link)")) ); shownetwork = true; }
41 else if(extension.startsWith("x-scheme-handler/")){ ui->label_extension->setText( QString(tr("(Internet URL - %1)")).arg(extension.section("/",-1)) ); shownetwork = true; }
42 else{ui->label_extension->setText("("+extension+" link)"); }
43 fileEXT = extension; //NOTE: this is the mime-type for the file now, not the extension
44 generateAppList(shownetwork);
45 }
46
47 //static functions
getDefaultApp(QString extension)48 QString LFileDialog::getDefaultApp(QString extension){
49 if(!extension.contains("/")){ return ""; }
50 qDebug() << "Get Default App:" << extension;
51 return LXDG::findDefaultAppForMime(extension);
52 }
53
setDefaultApp(QString extension,QString appFile)54 void LFileDialog::setDefaultApp(QString extension, QString appFile){
55 if(!extension.contains("/")){ extension = LXDG::findAppMimeForFile(appFile); }
56
57 //mime type default: set on the system itself
58 //if(appFile.endsWith(".desktop")){ appFile = appFile.section("/",-1); } //only need the relative path
59 LXDG::setDefaultAppForMime(extension, appFile);
60 }
61
62 // -----------
63 // PRIVATE
64 // -----------
getPreferredApplications()65 QStringList LFileDialog::getPreferredApplications(){
66 QStringList out;
67 //First list all the applications registered for that same mimetype
68 QString mime = fileEXT;
69 out << LXDG::findAvailableAppsForMime(mime);
70
71 //Now search the internal settings for that extension and find any applications last used
72 QStringList keys = settings->allKeys();
73 for(int i=0; i<keys.length(); i++){
74 if(keys[i].startsWith("default/")){ continue; } //ignore the defaults (they will also be in the main)
75 if(keys[i].toLower() == fileEXT.toLower()){
76 QStringList files = settings->value(keys[i]).toString().split(":::");
77 qDebug() << "Found Files:" << keys[i] << files;
78 bool cleaned = false;
79 for(int j=0; j<files.length(); j++){
80 if(QFile::exists(files[j])){ out << files[j]; }
81 else{ files.removeAt(j); j--; cleaned=true; } //file no longer available - remove it
82 }
83 if(cleaned){ settings->setValue(keys[i], files.join(":::")); } //update the registry
84 if(!out.isEmpty()){ break; } //already found files
85 }
86 }
87 //Make sure we don't have any duplicates before we return the list
88 out.removeDuplicates();
89 return out;
90 }
91
setPreferredApplication(QString desktopfile)92 void LFileDialog::setPreferredApplication(QString desktopfile){
93 QStringList keys = settings->allKeys();
94 for(int i=0; i<keys.length(); i++){
95 if(keys[i].toLower() == fileEXT.toLower()){
96 QStringList files = settings->value(keys[i]).toString().split(":::");
97 files.removeAll(desktopfile);
98 QStringList newfiles;
99 newfiles << desktopfile;
100 //Only keep the 5 most recent preferred applications per extension
101 for(int j=0; j<5 && j<files.length(); j++){
102 newfiles << files[j];
103 }
104 settings->setValue(keys[i], newfiles.join(":::"));
105 return;
106 }
107 }
108 //No key found for this extension - make a new one
109 settings->setValue(fileEXT.toLower(), desktopfile);
110 }
111
translateCat(QString cat)112 QString LFileDialog::translateCat(QString cat){
113 QString out;
114 if(cat=="Audio"){ out = tr("Audio"); }
115 else if(cat=="Video"){ out = tr("Video"); }
116 else if(cat=="Multimedia"){ out = tr("Multimedia"); }
117 else if(cat=="Development"){ out = tr("Development"); }
118 else if(cat=="Education"){ out = tr("Education"); }
119 else if(cat=="Game"){ out = tr("Game"); }
120 else if(cat=="Graphics"){ out = tr("Graphics"); }
121 else if(cat=="Network"){ out = tr("Network"); }
122 else if(cat=="Office"){ out = tr("Office"); }
123 else if(cat=="Science"){ out = tr("Science"); }
124 else if(cat=="Settings"){ out = tr("Settings"); }
125 else if(cat=="System"){ out = tr("System"); }
126 else if(cat=="Utility"){ out = tr("Utilities"); }
127 else if(cat=="Other"){ out = tr("Other"); }
128 else{ out = cat; }
129 return out;
130 }
131
132 // -----------------
133 // PRIVATE SLOTS
134 // -----------------
updateUI()135 void LFileDialog::updateUI(){
136 //Check for a selected application
137 bool good = false;
138 if(ui->radio_custom->isChecked()){
139 if(!ui->line_bin->text().isEmpty()){
140 QString bin = ui->line_bin->text();
141 good = LUtils::isValidBinary(bin);
142 //Now verify that the file exists and is executable
143 if( good ){
144 ui->label_goodbin->setPixmap(QPixmap(":/icons/good.png"));
145 }else{
146 ui->label_goodbin->setPixmap(QPixmap(":/icons/bad.png"));
147 }
148 }
149 }
150 else if(ui->radio_rec->isChecked()){
151 good = true; //a valid app is always selected on this page if it is available
152 }
153 else if(ui->combo_apps->count() > 0 && !ui->combo_apps->currentData().toString().isEmpty() ){
154 good=true;
155 }
156 ui->tool_ok->setEnabled(good);
157 }
158
generateAppList(bool shownetwork)159 void LFileDialog::generateAppList(bool shownetwork){
160 //Now load the preferred applications
161 XDGDesktopList applist;
162 applist.updateList();
163 PREFAPPS = getPreferredApplications();
164 qDebug() << "Preferred Apps:" << PREFAPPS;
165 ui->combo_rec->clear();
166 //Now get the application mimetype for the file extension (if available)
167 QStringList mimetypes = LXDG::findAppMimeForFile(filePath, true).split("::::"); //use all mimetypes
168 mimetypes.removeDuplicates();
169 QString defapp = getDefaultApp(mimetypes.first()); //default application
170 if(!defapp.isEmpty() && !PREFAPPS.contains(defapp) ){ PREFAPPS << defapp; } //ensure this is listed in the preferred apps list
171 //Now add all the detected applications
172 QHash< QString, QList<XDGDesktop*> > hash = LXDG::sortDesktopCats( applist.apps(false,true) );
173 QStringList cat = hash.keys();
174 cat.sort(); //sort alphabetically
175 ui->combo_apps->clear();
176 for(int c=0; c<cat.length(); c++){
177 QList<XDGDesktop*> app = hash[cat[c]];
178 if(app.length()<1){ continue; }
179 if(ui->combo_apps->count() >1){ ui->combo_apps->insertSeparator(ui->combo_apps->count()); }
180 ui->combo_apps->addItem(translateCat(cat[c]));
181 ui->combo_apps->insertSeparator(ui->combo_apps->count());
182 for(int a=0; a<app.length(); a++){
183 if(shownetwork && (cat[c].toLower()=="network" || cat[c].toLower()=="utility") ){
184 //Need to show preferred internet applications - look for ones that handle URL's
185 if(app[a]->exec.contains("%u") || app[a]->exec.contains("%U")){
186 //qDebug() << "Add to Preferred Apps:" << app[a]->filePath;
187 PREFAPPS << app[a]->filePath;
188 }
189 }
190 ui->combo_apps->addItem(LXDG::findIcon(app[a]->icon, "application-x-desktop"), app[a]->name, app[a]->filePath);
191 //Check to see if this app matches the mime type
192 if(!mimetypes.isEmpty()){
193 QStringList tmp = mimetypes; tmp << app[a]->mimeList;
194 if(tmp.removeDuplicates() > 0 ){
195 // also put this app in the preferred list
196 //qDebug() << "Mimetype match:" << mimetypes << app[a]->mimeList;
197 PREFAPPS.append(app[a]->filePath);
198 //If this is the first preferred app found - select this app initially
199 if(ui->combo_apps->currentIndex()<=0){ ui->combo_apps->setCurrentIndex(ui->combo_apps->count()-1); }
200 }
201 }
202 }
203 }
204 if(ui->combo_apps->currentIndex()<=0){ ui->combo_apps->setCurrentIndex(2); } //Start on the first "real" app - not the first category header
205 //Now add all the preferred applications
206 PREFAPPS.removeDuplicates();
207 for(int i=0; i<PREFAPPS.length(); i++){
208 XDGDesktop dFile(PREFAPPS[i]);
209 if( dFile.isValid() ){
210 QString txt = dFile.name;
211 if(PREFAPPS[i] == defapp){ txt.prepend( tr("[default] ") ); }
212 ui->combo_rec->addItem( LXDG::findIcon(dFile.icon, "application-x-desktop"), txt);
213 if(i==0){ ui->combo_rec->setCurrentIndex(0); } //make sure the first item is selected
214 }else{
215 PREFAPPS.removeAt(i); //invalid app
216 i--;
217 }
218 }
219 //Update the UI
220 if(PREFAPPS.isEmpty()){
221 ui->radio_rec->setEnabled(false); //no preferred apps
222 ui->radio_avail->setChecked(true);
223 }else{
224 ui->radio_rec->setChecked(true);
225 }
226 }
227
radioChanged()228 void LFileDialog::radioChanged(){
229 if(ui->radio_rec->isChecked()){
230 ui->stackedWidget->setCurrentWidget(ui->page_rec);
231 }else if(ui->radio_avail->isChecked()){
232 ui->stackedWidget->setCurrentWidget(ui->page_avail);
233 }else{
234 ui->stackedWidget->setCurrentWidget(ui->page_custom);
235 }
236 //ui->check_default->setEnabled( !ui->radio_custom->isChecked() );
237 updateUI();
238 }
239
240 /*void LFileDialog::on_group_binary_toggled(bool checked){
241 ui->label_goodbin->setVisible(checked);
242 ui->line_bin->setVisible(checked);
243 ui->tool_findBin->setVisible(checked);
244 updateUI();
245 }*/
246
on_tool_ok_clicked()247 void LFileDialog::on_tool_ok_clicked(){
248 appSelected = true;
249 setDefault = ui->check_default->isChecked();
250 if(ui->radio_custom->isChecked()){
251 appExec = ui->line_bin->text();
252 }else if(ui->radio_rec->isChecked()){
253 //application selected
254 XDGDesktop app(PREFAPPS[ui->combo_rec->currentIndex()]);
255 //Set the output variables
256 appExec = app.getDesktopExec();
257 appPath = app.path;
258 appFile = app.filePath;
259 setPreferredApplication(app.filePath); //bump this to the top of the preferred list for next time
260 }else{
261 //application selected
262 XDGDesktop app(ui->combo_apps->currentData().toString());
263 //Set the output variables
264 appExec = app.getDesktopExec();
265 appPath = app.path;
266 appFile = app.filePath;
267 setPreferredApplication(app.filePath); //save this app to this extension as a recommendation
268 }
269 this->close();
270 }
271
on_tool_cancel_clicked()272 void LFileDialog::on_tool_cancel_clicked(){
273 appSelected = false;
274 this->close();
275 }
276
on_tool_findBin_clicked()277 void LFileDialog::on_tool_findBin_clicked(){
278 QString filepath = QFileDialog::getOpenFileName(this, tr("Find Application Binary"), QDir::homePath() );
279 if(filepath.isEmpty()){ return; }
280 ui->line_bin->setText(filepath);
281 }
282
on_line_bin_textChanged()283 void LFileDialog::on_line_bin_textChanged(){
284 updateUI();
285 }
286