source: src-qt4/EasyPBI/mainGUI.cpp

Last change on this file was de68b26, checked in by Ken Moore <ken@…>, 8 weeks ago

Fix a bug in EasyPBI where the xdg file remove button was enabled and crashed when the user attempted to remove an item when nothing was selected.

  • Property mode set to 100644
File size: 39.8 KB
Line 
1#include "mainGUI.h"
2#include "ui_mainGUI.h"
3#include "backend.h"
4#include "newModuleDialog.h"
5#include "preferencesDialog.h"
6#include "aboutDialog.h"
7
8MainGUI::MainGUI(QWidget *parent) :
9    QMainWindow(parent),
10    ui(new Ui::MainGUI)
11{
12        // NOTE: "plus"/"minus" icons are set in QtDesigner using the current theme
13        //      since none are available in the Qt Embedded resources
14       
15       //Setup Initial state of GUI objects and connect signal/slots
16       ui->setupUi(this);  //load the mainGUI.ui file
17        XDGUPDATING=false;
18        lastModuleDir.clear();
19        // Create the config class
20        settings = new Config();
21        //Setup the Menu items
22        ui->actionExit->setIcon(Backend::icon("close"));
23        ui->actionRefresh_Module->setIcon(Backend::icon("refresh"));
24        ui->actionLoad_Files->setIcon(Backend::icon("file"));
25        //Setup the pushbutton menu lists
26        QStringList tmp = ModuleUtils::validRepoTypes();
27        for(int i=0; i<tmp.length(); i++){ menu_validRepoTypes.addAction(tmp[i]); }
28        //Setup Toolbar
29        ui->actionNew_Module->setIcon(Backend::icon("new"));
30        ui->actionLoad_Module->setIcon(Backend::icon("load"));
31        line_module = new QLineEdit(this);
32        line_module->setPlaceholderText(tr("No Module Loaded"));
33        line_module->setReadOnly(TRUE);
34        line_module->setFocusPolicy(Qt::NoFocus);
35        ui->toolBar->addWidget(line_module);
36        //ui->toolBar->addSeparator();
37        //ui->toolBar->addAction(ui->actionLoad_Files);
38        //Setup Module Editor
39        connect(ui->tabWidget, SIGNAL(currentChanged(int)),this,SLOT(slotModTabChanged(int)) ); //setup to refresh each tab once it is selected
40        // -- pbi.conf tab --
41        ui->push_change_makeport->setIcon(Backend::icon("file"));
42        ui->push_config_save->setIcon(Backend::icon("save"));
43        ui->tool_repoType->setIcon(Backend::icon("left"));
44          ui->tool_repoType->setMenu(&menu_validRepoTypes);
45          connect(&menu_validRepoTypes, SIGNAL(triggered(QAction*)), this, SLOT(slotSetRepoType(QAction*)) );
46       
47        // -- XDG entries tab --
48        connect(ui->radio_xdg_desktop,SIGNAL(clicked()),this,SLOT(slotXdgTypeChanged()) );
49        connect(ui->radio_xdg_menu,SIGNAL(clicked()),this,SLOT(slotXdgTypeChanged()) );
50        connect(ui->list_xdg_files,SIGNAL(itemSelectionChanged()), this, SLOT(slotXdgFileChanged()) );
51        ui->push_xdg_refresh->setIcon(Backend::icon("refresh"));
52        connect(ui->push_xdg_refresh, SIGNAL(clicked()), this, SLOT(slotXdgTypeChanged()) );
53        ui->push_xdg_exec->setIcon(Backend::icon("left"));
54        ui->push_xdg_exec->setMenu(&menu_bins);
55        connect(&menu_bins, SIGNAL(triggered(QAction*)), this, SLOT(slotAddBin(QAction*)) );
56        ui->push_xdg_savechanges->setIcon(Backend::icon("save"));
57        ui->push_xdg_menu->setIcon(Backend::icon("left"));
58        ui->push_xdg_menu->setMenu(&menu_validMenuCats);
59        connect(&menu_validMenuCats,SIGNAL(triggered(QAction*)),this,SLOT(slotAddMenuCat(QAction*)) );
60        ui->push_xdg_clearentry->setIcon(Backend::icon("file"));
61       
62        // -- Scripts tab --
63        ui->push_scripts_save->setIcon(Backend::icon("save"));
64        ui->push_scripts_create->setIcon(Backend::icon("new"));
65        ui->list_scripts_file->addItems(QStringList() << " ---"+tr("Installation Scripts")+"---" << "post-install.sh" << "pre-remove.sh" );
66        connect(ui->list_scripts_file, SIGNAL(currentIndexChanged(int)), this, SLOT(slotScriptChanged(int)) );
67       
68      SetupDefaults(); //load program defaults
69      refreshGUI("all"); //make items visible/invisible as necessary
70     
71      //Connect "option changed" signals to the respective slot
72      // PBI tab
73      connect(ui->line_progname,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
74      connect(ui->line_progauthor,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
75      connect(ui->line_progweb,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
76      connect(ui->line_config_license,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
77      connect(ui->line_makeport,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
78      connect(ui->line_repoTags,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
79      connect(ui->line_repoType,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
80      connect(ui->line_summary, SIGNAL(textChanged(QString)), this, SLOT(slotOptionChanged(QString)) );
81      connect(ui->text_description, SIGNAL(textChanged()), this, SLOT(slotOptionChanged()) );
82      connect(ui->group_config_overrides, SIGNAL(clicked()), this, SLOT(updateConfigVisibility()) );
83      connect(ui->group_config_repo, SIGNAL(clicked()), this, SLOT(updateConfigVisibility()) );
84      // XDG tab
85      connect(ui->line_xdg_name,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
86      connect(ui->line_xdg_mimepatterns,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
87      connect(ui->line_xdg_exec,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
88      connect(ui->line_xdg_menu,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
89      connect(ui->check_xdg_nodisplay,SIGNAL(clicked()),this,SLOT(slotXDGOptionChanged()) );
90      connect(ui->check_xdg_requiresroot,SIGNAL(clicked()),this,SLOT(slotXDGOptionChanged()) );
91      connect(ui->check_xdg_terminal,SIGNAL(clicked()),this,SLOT(slotXDGOptionChanged()) );
92      connect(ui->radio_xdg_customicon,SIGNAL(toggled(bool)),this,SLOT(slotXDGOptionChanged()) );
93      // Scripts tab
94      connect(ui->text_scripts_edit,SIGNAL(textChanged()),this,SLOT(slotScriptModified()) );
95       
96}
97
98MainGUI::~MainGUI()
99{
100  qDebug() << "Shutting down EasyPBI normally";
101}
102
103void MainGUI::loadModule(QString confFile){
104  //Load a module that was specified on the CLI
105  if(confFile.isEmpty() || !QFile::exists(confFile) ){return;} //invalid file
106  bool ok = MODULE.loadModule(confFile);
107  if(ok){ 
108    qDebug() << "Loaded module:"<<confFile;
109    pkgplist.clear();
110    line_module->setText(MODULE.basepath().replace(QDir::homePath(),"~")); 
111    lastModuleDir = MODULE.basepath();
112    QTimer::singleShot(0,this, SLOT(on_actionLoad_Files_triggered()));
113  }
114  //Move to the pbi.conf tab
115  ui->tabWidget->setCurrentWidget(ui->tab_pbi_conf);
116  //Refresh the UI
117  refreshGUI("pbiconf");
118}
119
120void MainGUI::slotSingleInstance(){
121  this->showNormal();
122  this->activateWindow();
123  this->raise();
124}
125
126void MainGUI::SetupDefaults(){
127    qDebug() << "Starting up EasyPBI (version "+settings->value("version")+")"; 
128    //Make sure that the program is not being started with root permissions
129    QString id = QProcessEnvironment::systemEnvironment().toStringList().filter("HOME=").join(" ").simplified();
130    if( id.contains("root") ){
131      qDebug() << "EasyPBI should not be run with root permissions! exiting.....";
132      exit(1);
133    }
134
135    //Load the current configuration settings
136    settings->readMachineArch(); //set the 64-bit flag as appropriate
137    //Scan for the external utilities needed to build PBI's
138    settings->scanForExternalUtilities();
139    //Load Preferences file if possible
140    settings->loadSettingsFile();
141    //create the EasyPBI directory structure if needed
142    if( !settings->checkDirectoryStructure() ){
143        QMessageBox::warning(this,tr("Permissions Error"), tr("There was an error trying to create the local EasyPBI directory structure. Please check the permissions for your home directory and restart EasyPBI.") );
144        exit(1);
145    }
146    //Pop up a warning box if some external resources are not available
147    bool chkOK = settings->check("isSUavailable");
148    if( !chkOK ){
149        QMessageBox::warning(this, tr("Resources Unavailable"), tr("Some external resources could not be found, so the EasyPBI services that use these resources have been deactivated.")+"\n"+tr("Please open up the EasyPBI settings to correct this deficiency.") );
150    }
151   
152    updateConfigVisibility(); //on first run, always need to do this manually
153}
154
155void MainGUI::updateConfigVisibility(){
156  //Update the group visibility for the pbi.conf tab
157  ui->frame_pkgFix->setVisible(ui->group_config_overrides->isChecked());
158  //ui->frame_repoInfo->setVisible(ui->group_config_repo->isChecked());
159}
160
161void MainGUI::refreshGUI(QString item){
162  //Enable/disable the interface appropriately
163 
164  //Stupid check to make sure that a module is actually loaded
165  if( MODULE.basepath().isEmpty() ){ 
166    ui->actionPackage_Module->setEnabled(FALSE);
167    ui->actionRefresh_Module->setEnabled(FALSE);
168    ui->tabWidget->setEnabled(false);
169    return;
170  }else{ 
171    ui->actionPackage_Module->setEnabled(TRUE); 
172    ui->actionRefresh_Module->setEnabled(TRUE);
173    ui->tabWidget->setEnabled(true);
174  }
175  //See if we should refresh everything (default) 
176  bool doall = ( (item == "all") || item.isEmpty() );
177  bool doeditor = (item == "editor"); //also add a flag to just refresh the editor
178  //Refresh the desired tab(s)
179  // ------PBI.CONF------
180  if( doall || doeditor || (item == "pbiconf")){
181    //Update options visibility
182    updateConfigVisibility();
183    //Now reset the options to the current module values
184    MODULE.loadConfig();
185    // -- Text Values
186    ui->line_progname->setText( MODULE.stringVal("PBI_PROGNAME") );
187    ui->line_progweb->setText( MODULE.stringVal("PBI_PROGWEB") );
188    ui->line_progauthor->setText( MODULE.stringVal("PBI_PROGAUTHOR") );
189    ui->line_makeport->setText( MODULE.stringVal("PBI_ORIGIN") );
190    ui->line_config_license->setText( MODULE.stringVal("PBI_LICENSE") );
191    ui->line_repoTags->setText( MODULE.stringVal("PBI_TAGS") );
192    ui->line_repoType->setText( MODULE.stringVal("PBI_PROGTYPE") );
193    ui->line_summary->setText( MODULE.stringVal("PBI_SHORTDESC") );
194    ui->text_description->setPlainText( MODULE.stringVal("PBI_DESC") );
195    // -- Combo Boxes (filled with individual items from text)
196    ui->list_portafter->clear();
197    ui->list_portafter->addItems( MODULE.listVal("PBI_OTHERPKGS") );
198    ui->combo_plugins->clear();
199    ui->combo_plugins->addItems( MODULE.listVal("PBI_PLUGINS") );
200    ui->combo_screenshots->clear();
201    ui->combo_screenshots->addItems( MODULE.listVal("PBI_SCREENSHOTS") );
202    ui->combo_similar->clear();
203    ui->combo_similar->addItems( MODULE.listVal("PBI_RELATED") );
204    // -- Application Icon
205    ui->tool_showicon->setIcon( MODULE.appIcon() );
206   
207    //Now disable the save button
208    ui->push_config_save->setEnabled(FALSE);  //disable the save button until something changes
209    //Load the current package information and display it on the UI
210    QStringList pkgInfo = Backend::getPkgInfo(MODULE.stringVal("PBI_ORIGIN"));
211    //qDebug() << "pkg info:" << pkgInfo;
212    // <name>, <website>, <comment>, <description>, <license>
213    if(pkgInfo.length() >= 4){
214      ui->line_progname->setPlaceholderText( pkgInfo[0] );
215      ui->line_progweb->setPlaceholderText(pkgInfo[1]);
216      ui->line_summary->setPlaceholderText(pkgInfo[2]);
217      if(ui->text_description->toPlainText().isEmpty()){
218        ui->text_description->setPlainText(pkgInfo[3]);
219        ui->text_description->setWhatsThis(pkgInfo[3]);
220      }
221      ui->line_config_license->setPlaceholderText(pkgInfo[4]);
222    }else{
223      ui->line_progname->setPlaceholderText("");
224      ui->line_progweb->setPlaceholderText("");
225      ui->line_summary->setPlaceholderText("");
226      ui->line_config_license->setPlaceholderText("");
227    }
228
229  }
230  //------XDG------
231  if( doall || doeditor || (item == "xdg")){
232    slotXdgTypeChanged();
233  }
234  //------SCRIPTS-----
235  if( doall || doeditor || (item == "scripts")  ){
236    //Update the list of available scripts
237    QStringList exist = MODULE.existingScripts();
238    QStringList valid = MODULE.validScripts();
239    QString current="junk";
240    if(ui->list_scripts_file->count() > 0){
241        current = ui->list_scripts_file->currentText(); //get the current item before clearing it
242    }
243    ui->list_scripts_file->clear();
244    ui->list_scripts_file->addItem("-- Installation Scripts --");
245    int index = 0;
246    for(int i=0; i<valid.length(); i++){
247      if(exist.contains(valid[i])){ 
248         exist.removeAll(valid[i]); 
249         ui->list_scripts_file->addItem(Backend::icon("file"), valid[i]);
250      }else{ ui->list_scripts_file->addItem(Backend::icon("close"), valid[i]); }
251      if(valid[i] == current){ index = i+1; }
252    }
253    //Now add the rest of the existing scripts (that are no longer valid)
254    for(int i=0; i<exist.length(); i++){
255      ui->list_scripts_file->addItem(Backend::icon("delete"), exist[i]);
256      if(exist[i] == current){ index = valid.length()+i+1; }
257    }
258    //Now reset to the appropriate item (will automatically load appropriately)
259    ui->list_scripts_file->setCurrentIndex(index);
260  }
261
262  //------OVERALL SETTINGS------
263  if( doall || doeditor ){
264    //Check for a 64-bit system to enable the 32-bit build option
265    //if( settings->check("is64bit") ){ ui->check_build_32->setVisible(TRUE); }
266    //else{ ui->check_build_32->setVisible(FALSE); ui->check_build_32->setChecked(FALSE); }
267   
268    //Set the default focus on the "load" button
269    this->setFocus();
270  }
271}
272
273QString MainGUI::getPortPackage(){
274  QString portSel;
275  /*if( settings->check("isportsavailable") ){
276    //Prompt for a new port
277    portSel = QFileDialog::getExistingDirectory(this, tr("Select Port"), settings->value("portsdir")); 
278  }else{*/
279    //Prompt for a package
280    pkgSelect dlg(this);
281    dlg.exec();
282    if(dlg.selected){ portSel = dlg.portSelected; };
283  //}
284  return portSel;
285}
286
287QStringList MainGUI::getPackages(){
288    QStringList portSel;
289    pkgSelect dlg(this, false); //run this in multi-selection mode
290    dlg.exec();
291    if(dlg.selected){ portSel = dlg.portsSelected; };
292    return portSel;   
293}
294
295/*----------------------------------
296   MENU OPTIONS
297  -----------------------------------
298*/
299
300void MainGUI::on_actionBulk_Module_Creator_triggered(){
301  this->hide();
302  BulkModuleDialog dlg;
303  dlg.exec();
304  this->show();
305}
306void MainGUI::on_actionExit_triggered(){
307  qDebug() << "Close EasyPBI requested";
308  this->close();
309}
310
311void MainGUI::on_actionPreferences_triggered(){
312  //Open up the preferences dialog
313  PreferencesDialog dlg(this);
314  //make the dialog modal and wait for it to close
315  dlg.exec(); 
316  //Re-check for system commands
317  settings->scanForExternalUtilities();
318  //Now reload the saved settings
319  settings->loadSettingsFile();
320  //Now refresh the GUI
321  refreshGUI("all");
322}
323
324void MainGUI::on_actionPackage_Module_triggered(){
325   ModuleUtils::compressModule(MODULE.basepath()); //currentModule->compressModule();
326   QMessageBox::information(this,tr("Success"),tr("A copy of the current module has been successfully packaged  within the module directory.") );
327
328}
329
330void MainGUI::on_actionRefresh_Module_triggered(){
331  QString modSel = MODULE.basepath(); //currentModule->path(); //re-load the current module
332  bool ok = MODULE.loadModule(modSel+"/pbi.conf"); 
333  if(ok){ 
334    qDebug() << "Loaded module:"<<modSel;         
335    line_module->setText(modSel.replace(QDir::homePath(),"~"));
336    refreshGUI("all");
337  }
338}
339
340void MainGUI::on_actionFreeBSD_Ports_triggered(){
341  QString port;
342  if(!line_module->text().isEmpty()){
343        //Get the currently selected port
344        port = MODULE.stringVal("PBI_ORIGIN");
345  }
346  QString target_url = "http://www.freshports.org/" + port;
347  qDebug() << "Opening URL:" << target_url; 
348  target_url.prepend("xdg-open ");
349  system(target_url.toUtf8()); 
350}
351
352void MainGUI::on_actionPBI_Modules_triggered(){
353  //Open the PC-BSD wiki to the module builders guide
354   QString target_url = "http://wiki.pcbsd.org/index.php/PBI_Module_Builder_Guide/10.0";
355   qDebug() << "Opening URL:" << target_url; 
356   target_url.prepend("xdg-open ");
357   system(target_url.toUtf8());
358}
359
360void MainGUI::on_actionAbout_EasyPBI_triggered(){
361  aboutDialog dlg(this,settings->value("version"));
362  dlg.exec();
363}
364
365
366/*----------------------------------
367   TOOLBAR OPTIONS
368  -----------------------------------
369*/
370void MainGUI::on_actionNew_Module_triggered(){
371  qDebug() << "New Module triggered";
372  //Create and run the new dialog
373  QString pDir = "";
374  if(settings->check("isportsavailable")){ pDir = settings->value("portsdir"); }
375  NewModuleDialog* dlg = new NewModuleDialog(this, pDir);
376  dlg->setDefaultIconFile(settings->value("defaulticon"));
377  dlg->exec();
378  //Determine if the action was cancelled
379  if( dlg->isAccepted ){
380    //Now create the new module
381    QString modPath, modBase, oldIconPath;
382    modBase = dlg->moduleData; //port cat/name
383    oldIconPath = dlg->moduleIcon; //PNG icon to use for the program
384    modPath = settings->value("moduledir"); //base directory to create modules in
385    if(dlg->quickMake){
386      pkgplist.clear();
387      MODULE = ModuleUtils::newModule(modPath, modBase, oldIconPath, 0);
388    }else{
389      MODULE = ModuleUtils::newModule(modPath, modBase, oldIconPath, &pkgplist);
390    }
391    //qDebug() << "pkgplist:" << pkgplist;
392    if(MODULE.basepath().isEmpty()){
393      QMessageBox::warning(this,tr("EasyPBI: Permissions Error"), tr("Could not create PBI module. Please check the directory permissions and try again."));
394    }else{
395      line_module->setText( MODULE.basepath().replace(QDir::homePath(), "~") );
396    }
397  }
398  //Move to the pbi.conf tab
399  ui->tabWidget->setCurrentWidget(ui->tab_pbi_conf);
400  QTimer::singleShot(0,this, SLOT(on_actionLoad_Files_triggered()));
401  //Refresh the UI
402  refreshGUI("pbiconf");
403  delete dlg;
404}
405
406void MainGUI::on_actionLoad_Module_triggered(){
407  QString openDir = settings->value("moduledir");
408  if(!lastModuleDir.isEmpty()){ openDir = lastModuleDir; }
409  QString modSel = QFileDialog::getOpenFileName(this, tr("Select PBI Module Configuration"), openDir, tr("PBI Configuration (pbi.conf)") );
410  if(modSel.isEmpty()){return;} //action cancelled or closed
411  bool ok = MODULE.loadModule(modSel);
412  if(ok){ 
413    qDebug() << "Loaded module:"<<modSel;
414    pkgplist.clear();
415    line_module->setText(MODULE.basepath().replace(QDir::homePath(),"~")); 
416    lastModuleDir = MODULE.basepath();
417  }
418  //Move to the pbi.conf tab
419  ui->tabWidget->setCurrentWidget(ui->tab_pbi_conf);
420  QTimer::singleShot(0,this, SLOT(on_actionLoad_Files_triggered()));
421  //Refresh the UI
422  refreshGUI("pbiconf");
423}
424
425void MainGUI::on_actionLoad_Files_triggered(){
426  if(pkgplist.isEmpty()){
427    pkgplist = Backend::getPkgPList(MODULE.stringVal("PBI_ORIGIN"));
428  }
429 
430  //Generate the menu's appropriately
431  menu_bins.clear();
432  QStringList bins = pkgplist.filter("/bin/");
433    bins.append( pkgplist.filter("/sbin/") );
434  for(int i=0; i<bins.length(); i++){
435    menu_bins.addAction(bins[i].section("/",-1));
436  }
437  ui->push_xdg_exec->setEnabled(!menu_bins.isEmpty());
438}
439
440/*----------------------------------
441   MODULE EDITOR OPTIONS
442  -----------------------------------
443*/
444void MainGUI::slotModTabChanged(int newtab){
445  switch(newtab){
446    case 0:
447            refreshGUI("pbiconf"); break;
448    case 1:
449            refreshGUI("xdg"); break;
450    case 2:
451            refreshGUI("scripts"); break;
452    default:
453            refreshGUI("editor"); break; //do all the module editor tabs
454  }       
455}
456
457/*----------------------------------
458   PBI.CONF OPTIONS
459  -----------------------------------
460*/
461void MainGUI::on_push_change_makeport_clicked(){
462  QString portSel = getPortPackage();     
463  if(portSel.isEmpty()){return;}       
464
465  //Save the port info to the GUI
466  ui->line_makeport->setText(portSel);
467  ui->push_config_save->setEnabled(TRUE);
468}
469
470void MainGUI::on_tool_addportafter_clicked(){
471  //Prompt for a new port
472  QStringList portSel = getPackages();
473  if(portSel.isEmpty()){return;} //action cancelled or closed   
474  //Save the port info to the GUI
475  if(ui->list_portafter->count() == 1 && ui->list_portafter->currentText().isEmpty() ){ ui->list_portafter->clear(); }
476  for(int i=0; i<portSel.length(); i++){
477    ui->list_portafter->addItem(portSel[i].remove(settings->value("portsdir")+"/"));
478  }
479  ui->push_config_save->setEnabled(TRUE);
480}
481
482void MainGUI::on_tool_rmportafter_clicked(){
483  int index = ui->list_portafter->currentIndex();
484  if(index != -1){
485    ui->list_portafter->removeItem(index);
486  }
487  ui->push_config_save->setEnabled(TRUE);
488}
489
490void MainGUI::on_push_config_save_clicked(){
491  //Save the current settings to the backend structures
492  //Text Values
493  MODULE.setStringVal("PBI_ORIGIN", ui->line_makeport->text());
494  MODULE.setStringVal("PBI_PROGNAME", ui->line_progname->text());
495  MODULE.setStringVal("PBI_PROGWEB", ui->line_progweb->text());
496  MODULE.setStringVal("PBI_PROGAUTHOR", ui->line_progauthor->text());
497  MODULE.setStringVal("PBI_LICENSE", ui->line_config_license->text());
498  MODULE.setStringVal("PBI_TAGS", ui->line_repoTags->text());
499  MODULE.setStringVal("PBI_PROGTYPE", ui->line_repoType->text());
500  if(ui->text_description->toPlainText()==ui->text_description->whatsThis()){
501    MODULE.setStringVal("PBI_DESC", ""); //no change from the raw pkg description
502  }else{
503    MODULE.setStringVal("PBI_DESC", ui->text_description->toPlainText() ); //modified
504  }
505  MODULE.setStringVal("PBI_SHORTDESC", ui->line_summary->text());
506  //Combo Boxes
507  QStringList addports;
508  for(int i=0; i<ui->list_portafter->count(); i++){ addports << ui->list_portafter->itemText(i); }
509  MODULE.setListVal("PBI_OTHERPKGS", addports );
510  addports.clear();
511  for(int i=0; i<ui->combo_plugins->count(); i++){ addports << ui->combo_plugins->itemText(i); }
512  MODULE.setListVal("PBI_PLUGINS", addports );
513  addports.clear();
514  for(int i=0; i<ui->combo_screenshots->count(); i++){ addports << ui->combo_screenshots->itemText(i); }
515  MODULE.setListVal("PBI_SCREENSHOTS", addports );
516  addports.clear();
517  for(int i=0; i<ui->combo_similar->count(); i++){ addports << ui->combo_similar->itemText(i); }
518  MODULE.setListVal("PBI_RELATED", addports );
519
520 
521  //save the new settings to pbi.conf
522  bool ok = MODULE.saveConfig();
523  if(!ok){
524    //Display a warning that the file could not be saved
525    QMessageBox::warning(this,tr("EasyPBI Error"), tr("The PBI configuration file could not be saved. Please check your file permissions before trying again."));
526    //re-load the current PBI.conf into the backend
527    MODULE.loadConfig();
528  }else{
529    ui->push_config_save->setEnabled(false); //make sure the save button goes inactive once saved
530  }
531}
532
533void MainGUI::slotOptionChanged(QString tmp){
534  tmp.clear(); //just to remove compiler warning about unused variable
535  ui->push_config_save->setEnabled(TRUE);       
536}
537
538void MainGUI::slotSetRepoType(QAction* act){
539  ui->line_repoType->setText(act->text());
540}
541
542void MainGUI::on_tool_addplugin_clicked(){
543  //Prompt for a new port
544  QStringList portSel = getPackages();
545  if(portSel.isEmpty()){return;} //action cancelled or closed   
546  //Save the port info to the GUI
547  if(ui->combo_plugins->count() == 1 && ui->combo_plugins->currentText().isEmpty() ){ ui->combo_plugins->clear(); }
548  for(int i=0; i<portSel.length(); i++){
549    ui->combo_plugins->addItem(portSel[i]);
550  }
551  ui->push_config_save->setEnabled(true);
552}
553
554void MainGUI::on_tool_rmplugin_clicked(){
555  if(ui->combo_plugins->currentIndex() >= 0){
556    ui->combo_plugins->removeItem(ui->combo_plugins->currentIndex());
557    slotOptionChanged();
558  }
559}
560
561void MainGUI::on_tool_addscreenshot_clicked(){
562  QString url = QInputDialog::getText(this, tr("Screenshot URL"), tr("Screenshot URL:"));
563  if(url.isEmpty()){ return; }
564  if(ui->combo_screenshots->count() == 1 && ui->combo_screenshots->currentText().isEmpty() ){ ui->combo_screenshots->clear(); }
565  ui->combo_screenshots->addItem(url);
566  slotOptionChanged();
567}
568
569void MainGUI::on_tool_rmscreenshot_clicked(){
570  if(ui->combo_screenshots->currentIndex() >= 0){
571    ui->combo_screenshots->removeItem(ui->combo_screenshots->currentIndex());
572    slotOptionChanged();
573  }     
574}
575
576void MainGUI::on_tool_addsimilar_clicked(){
577  //Prompt for a new port
578  QStringList portSel = getPackages();
579  if(portSel.isEmpty()){return;} //action cancelled or closed   
580  //Save the port info to the GUI
581  if(ui->combo_similar->count() == 1 && ui->combo_similar->currentText().isEmpty() ){ ui->combo_similar->clear(); }
582  for(int i=0; i<portSel.length(); i++){
583    ui->combo_similar->addItem(portSel[i]);
584  }
585  ui->push_config_save->setEnabled(true);       
586}
587
588void MainGUI::on_tool_rmsimilar_clicked(){
589  if(ui->combo_similar->currentIndex() >= 0){
590    ui->combo_similar->removeItem(ui->combo_similar->currentIndex());
591    slotOptionChanged();
592  }
593}
594
595void MainGUI::on_tool_showicon_clicked(){
596  //Prompt the user to select a PNG icon file
597  QString iconpath = QFileDialog::getOpenFileName(this, tr("Find Icon File"), QDir::homePath(), tr("PNG Icon (*.png)"));
598  if(iconpath.isEmpty()){ return; }
599  MODULE.setAppIcon(iconpath); //save it to the module
600  ui->tool_showicon->setIcon( MODULE.appIcon() ); //Now reload the icon
601}
602
603/*------------------------------------------------
604   XDG EDITOR OPTIONS
605  -------------------------------------------------
606*/
607void MainGUI::slotXdgTypeChanged(){
608  XDGUPDATING=true;
609  //Update the file list appropriately 
610  if(ui->radio_xdg_desktop->isChecked()){
611    //update the files available
612    ui->list_xdg_files->clear();
613    ui->list_xdg_files->addItems(MODULE.listXdgDesktopFiles());
614    //Set the visibility
615        //Current file
616        ui->label_xdg_mimepatterns->setVisible(FALSE); ui->line_xdg_mimepatterns->setVisible(FALSE);
617        ui->label_xdg_menu->setVisible(false); ui->line_xdg_menu->setVisible(false); ui->push_xdg_menu->setVisible(false);
618  }else if(ui->radio_xdg_menu->isChecked()){
619    //update the files available
620    ui->list_xdg_files->clear();
621    ui->list_xdg_files->addItems(MODULE.listXdgMenuFiles());     
622    //Set the visibility
623        //Current file
624        ui->label_xdg_mimepatterns->setVisible(TRUE); ui->line_xdg_mimepatterns->setVisible(TRUE);
625        ui->label_xdg_menu->setVisible(true); ui->line_xdg_menu->setVisible(true); ui->push_xdg_menu->setVisible(true);
626  }
627  //Select the first file in the list if one is available
628  if( ui->list_xdg_files->count() > 0){ ui->list_xdg_files->setCurrentRow(0); }
629
630  //Menu categories
631  QString recMenu = ModuleUtils::recommendedXdgCategory(MODULE.stringVal("PBI_ORIGIN").section("/",0,0) );
632  QStringList cats = ModuleUtils::validXdgCategories();
633  //qDebug() << "App Menu Cat:" << recMenu << cats;
634  menu_validMenuCats.clear();
635  for(int i=0; i<cats.length(); i++){
636    if(recMenu==cats[i]){ //Add an icon showing the recommended menu category
637      menu_validMenuCats.addAction(Backend::icon("start"),cats[i]);     
638    }else{
639      menu_validMenuCats.addAction(cats[i]);
640    }
641  }
642  XDGUPDATING=false;
643  //Now update read the currently selected file
644  slotXdgFileChanged();
645}
646
647void MainGUI::slotXdgFileChanged(){     
648  if(XDGUPDATING){ return; }
649  bool clearUI =FALSE;
650  if(ui->list_xdg_files->currentRow() == -1){ clearUI=TRUE; }
651
652  //Get the selected file
653  QString file;
654  if( !clearUI ){ file = ui->list_xdg_files->currentItem()->text(); }
655  ui->push_xdg_remove->setEnabled(!clearUI);
656  if( clearUI || file.isEmpty() ){
657    //Clear the UI lines
658    ui->line_xdg_name->clear();
659    ui->line_xdg_exec->clear();
660    ui->line_xdg_menu->clear();
661    ui->line_xdg_mimepatterns->clear();
662    ui->check_xdg_terminal->setChecked(FALSE);
663    ui->check_xdg_nodisplay->setChecked(FALSE);
664    ui->check_xdg_requiresroot->setChecked(FALSE);
665    ui->push_xdg_savechanges->setEnabled(FALSE);
666    ui->push_xdg_savenew->setEnabled(FALSE);
667    //Now return
668    return; 
669  }
670  //Now setup the UI as appropriate
671  if(ui->radio_xdg_desktop->isChecked()){
672    //Load the file
673    MODULE.loadXdgDesktop(file);
674       
675  }else if(ui->radio_xdg_menu->isChecked()){
676    //Load the file
677    MODULE.loadXdgMenu(file);
678   
679    //Load the XDG-MIME file associations
680    QString mime = MODULE.xdgText("MimeType");
681    QStringList mimeavailable = MODULE.listMimeFiles();
682    bool found = FALSE;
683    for( int i=0; i<mimeavailable.length(); i++){
684      MODULE.loadMimeFile(mimeavailable[i]);
685      if(MODULE.mimeText("type") == mime){
686        found = TRUE;
687        break;
688      }
689    }
690    //qDebug() << "mimetype detected:" << mime;
691    if(found){
692      ui->line_xdg_mimepatterns->setText( MODULE.mimeText("pattern") ); 
693    }else{
694      MODULE.clearMimeData(); //Make sure we don't have any mime file loaded
695      ui->line_xdg_mimepatterns->clear();
696    }
697   
698  }else{
699    MODULE.clearXdgData(); //do nothing, unknown radio button selected (or none)
700  }
701  //update the file info on the GUI
702  ui->line_xdg_name->setText( MODULE.xdgText("Name") );
703  ui->line_xdg_exec->setText( ModuleUtils::pruneXdgLine(MODULE.xdgText("Exec")) );
704  ui->line_xdg_menu->setText( MODULE.xdgText("Categories") );
705  //comboboxes
706  QString icon = ModuleUtils::pruneXdgLine(MODULE.xdgText("Icon"));
707  if(icon.isEmpty() || icon.contains("%%PBI_APPDIR%%")){ ui->radio_xdg_modicon->setChecked(true); }
708  else{ ui->radio_xdg_customicon->setChecked(true); ui->line_xdg_customicon->setText(icon); }
709
710  //Checkboxes
711  ui->check_xdg_terminal->setChecked( MODULE.xdgEnabled("Terminal") );
712  ui->check_xdg_nodisplay->setChecked( MODULE.xdgEnabled("NoDisplay") );
713  ui->check_xdg_requiresroot->setChecked( ModuleUtils::xdgExecUsesRoot(MODULE.xdgText("Exec")) );
714   
715   
716  ui->push_xdg_savechanges->setEnabled(FALSE);
717  ui->push_xdg_savenew->setEnabled(FALSE);
718}
719
720void MainGUI::slotAddMenuCat(QAction* act){
721  //get the selected menu category
722  QString newcat = act->text();
723  //Read the current categories
724  QStringList oldcats = ui->line_xdg_menu->text().split(";", QString::SkipEmptyParts);
725  for(int i=0; i<oldcats.length(); i++){
726    oldcats[i] = oldcats[i].simplified();
727    if(oldcats[i] == newcat){return;} //category already in the list, do nothing
728  }
729  //Add the item
730  oldcats << newcat;
731  //Now replace the line onto the GUI
732  ui->line_xdg_menu->setText(oldcats.join("; "));
733}
734
735void MainGUI::slotAddBin(QAction* act){
736  //replace the current executable with the new one
737  ui->line_xdg_exec->setText(act->text().section("/",-1) );     
738}
739
740void MainGUI::on_push_xdg_remove_clicked(){
741  //Figure out if a file is selected
742  if(ui->list_xdg_files->currentItem()==0){ return; } //no item selected
743  QString desktopFile = ui->list_xdg_files->currentItem()->text();
744  if( desktopFile.isEmpty() ){ return; }
745  //Now remove the file
746  bool ok = FALSE;
747  if( ui->radio_xdg_desktop->isChecked() ){
748    ok = MODULE.removeXdgDesktop(desktopFile);
749  }else if( ui->radio_xdg_menu->isChecked() ){
750    //Check for a MIME type to remove as well
751    ui->line_xdg_mimepatterns->setText(""); //make sure we remove any MIME file
752    MODULE.loadXdgMenu(desktopFile); //load the file's mimetype
753    checkMime(); //perform the removal if appropriate
754    ok = MODULE.removeXdgMenu(desktopFile);
755  }
756  //Now inform the user if there was an error
757  if(!ok){
758    QMessageBox::warning(this, tr("EasyPBI Error"), tr("Could not remove the XDG entry.")+"\n"+tr("Check the file permissions and try again") );
759  }
760  //Now refresh the GUI
761  refreshGUI("xdg");
762 
763}
764
765void MainGUI::on_push_xdg_savechanges_clicked(){
766  //save the current UI settings to the module structure then save the file
767  bool ok = FALSE;
768  QString desktopFile = ui->list_xdg_files->currentItem()->text();
769  if(desktopFile.isEmpty()){ return; }
770  //Make sure the backend is currently set for this file
771  if( ui->radio_xdg_desktop->isChecked() ){ MODULE.loadXdgDesktop(desktopFile); }
772  else if(ui->radio_xdg_menu->isChecked() ){ MODULE.loadXdgMenu(desktopFile); }
773  //Save the values into the backend module structure
774  MODULE.setXdgText("Value", "1.0");
775  MODULE.setXdgText("Type", "Application");
776  MODULE.setXdgText("Name", ui->line_xdg_name->text());
777  MODULE.setXdgText("GenericName", ui->line_xdg_name->text().toLower());
778  MODULE.setXdgText("Exec", ModuleUtils::generateXdgExec(ui->line_xdg_exec->text(), ui->check_xdg_requiresroot->isChecked()) );
779  if(ui->radio_xdg_customicon->isChecked()){
780    MODULE.setXdgText("Icon", ModuleUtils::generateXdgPath(ui->line_xdg_customicon->text()) );
781  }else{
782    MODULE.setXdgText("Icon", ""); //use the built-in icon instead
783  }
784  MODULE.setXdgText("Path", ModuleUtils::generateXdgPath("") );
785  MODULE.setXdgEnabled("Terminal",ui->check_xdg_terminal->isChecked());
786  MODULE.setXdgEnabled("NoDisplay",ui->check_xdg_nodisplay->isChecked());
787  MODULE.setXdgEnabled("StartupNotify", true);
788  if( ui->radio_xdg_desktop->isChecked() ){
789    //clear the menu entry values
790    MODULE.setXdgText("Categories", "");
791    MODULE.setXdgText("MimeType", "");
792    //Now save the file
793    ok = MODULE.saveXdgDesktop(desktopFile);
794  }else if( ui->radio_xdg_menu->isChecked() ){
795    //Setup the menu entry values
796    MODULE.setXdgText("Categories", ui->line_xdg_menu->text());
797    //Setup the mime type associations as appropriate
798    checkMime();
799    //Now save the file
800    ok = MODULE.saveXdgMenu(desktopFile);   
801  }
802  //Now inform the user if there was an error
803  if(!ok){
804    QMessageBox::warning(this, tr("EasyPBI Error"), tr("Could not save the changes to the XDG entry.")+"\n"+tr("Check the file permissions and try again") );
805  }
806  //Now refresh the GUI
807  slotXdgFileChanged(); //only update the proper half of the tab
808}
809
810void MainGUI::on_push_xdg_savenew_clicked(){
811  //Get the filename we want to save
812  QString filename;
813  //Now check that the filename does not already exist
814  QStringList cFiles;
815  if(ui->radio_xdg_desktop->isChecked() ){
816    filename = ui->line_xdg_exec->text().section("/",-1);
817    cFiles = MODULE.listXdgDesktopFiles().replaceInStrings(".desktop","");
818  }else if(ui->radio_xdg_menu->isChecked() ){
819    filename = ui->line_xdg_exec->text().section("/",-1);
820    cFiles = MODULE.listXdgMenuFiles().replaceInStrings(".desktop","");
821  }
822  if(filename.isEmpty()){ return; }
823 
824  if(cFiles.indexOf(filename) != -1){
825    int num = 1;
826    while(cFiles.indexOf(filename+QString::number(num)) != -1){ num++; }
827    filename.append( QString::number(num) );
828  }
829  //save the current UI settings to the module structure then save the file
830  bool ok = FALSE;
831  if(filename.isEmpty()){ return; }
832  //Make sure the backend structure is currently empty
833  MODULE.clearXdgData();
834  //Save the values into the backend module structure
835  MODULE.setXdgText("Value", "1.0");
836  MODULE.setXdgText("Type", "Application");
837  MODULE.setXdgText("Name", ui->line_xdg_name->text());
838  MODULE.setXdgText("GenericName", ui->line_xdg_name->text().toLower());
839  MODULE.setXdgText("Exec", ModuleUtils::generateXdgExec(ui->line_xdg_exec->text(), ui->check_xdg_requiresroot->isChecked()) );
840  if(ui->radio_xdg_customicon->isChecked()){
841    MODULE.setXdgText("Icon", ModuleUtils::generateXdgPath(ui->line_xdg_customicon->text()) );
842  }else{
843    MODULE.setXdgText("Icon", ""); //use the built-in icon instead
844  }
845  MODULE.setXdgText("Path", ModuleUtils::generateXdgPath("") );
846  MODULE.setXdgEnabled("Terminal",ui->check_xdg_terminal->isChecked());
847  MODULE.setXdgEnabled("NoDisplay",ui->check_xdg_nodisplay->isChecked());
848  MODULE.setXdgEnabled("StartupNotify", true);
849  if( ui->radio_xdg_desktop->isChecked() ){
850    //clear the menu entry values
851    MODULE.setXdgText("Categories", "");
852    MODULE.setXdgText("MimeType", "");
853    //Now save the file
854    ok = MODULE.saveXdgDesktop(filename);
855  }else if( ui->radio_xdg_menu->isChecked() ){
856    //Setup the menu entry values
857    MODULE.setXdgText("Categories", ui->line_xdg_menu->text());
858    //Setup the mime type associations as appropriate
859    checkMime();
860    //Now save the file
861    ok = MODULE.saveXdgMenu(filename);   
862  }
863  //Now inform the user if there was an error
864  if(!ok){
865    QMessageBox::warning(this, tr("EasyPBI Error"), tr("Could not create the XDG entry.")+"\n"+tr("Check the file permissions and try again") );
866  }
867  //Now refresh the GUI
868  refreshGUI("xdg");
869}
870
871void MainGUI::on_push_xdg_clearentry_clicked(){
872  //Clear the UI
873        //reset the item selected to nothing
874        ui->list_xdg_files->setCurrentRow(-1);
875        //De-activate the "save" button
876        ui->push_xdg_savechanges->setEnabled(FALSE);
877        //Now clear the
878        slotXdgFileChanged();
879}
880
881void MainGUI::checkMime(){
882    //This function will check the UI for differences in the MIME patterns
883      // and update/create the MIME file appropriately
884      // The MENU mime type will also be appropriately set
885       
886    //Get the current/desired values
887    QString newPatterns = ui->line_xdg_mimepatterns->text().simplified();
888    QString cmimetype = MODULE.xdgText("MimeType"); //in the desktop/menu file
889       
890    //Determine the action necessary
891    int stat = 0; //do nothing by default
892    if( newPatterns.isEmpty() && !cmimetype.isEmpty() ){ stat = 1; } //remove old mime file
893    else if( !newPatterns.isEmpty() && !cmimetype.isEmpty() ){stat = 2; } //update mime file
894    else if( !newPatterns.isEmpty() && cmimetype.isEmpty() ){stat = 3; } //new mime file
895    qDebug() << "CheckMime:" << QString::number(stat);
896    //Now perform the actions as appropriate
897    MODULE.clearMimeData(); //Make sure this backend is currently empty   
898    QString fileName;
899    if(stat == 0){ return; } //no action needed
900    else if(stat == 1 || stat == 2){ //need to find current MIME file
901      QStringList MF = MODULE.listMimeFiles();
902      for(int i=0; i<MF.length(); i++){
903        MODULE.loadMimeFile(MF[i]);
904        if(MODULE.mimeText("type") == cmimetype){
905          if(stat == 1){ //remove old mime file
906            MODULE.removeMimeFile(MF[i]);
907            MODULE.clearMimeData();
908            MODULE.setXdgText("MimeType","");
909            return; //done now
910          }else{ //stat ==2, update mime file
911            //Check if there is anything that actually needs to be done
912            if( MODULE.mimeText("pattern") == newPatterns ){ return; } //nothing to change
913            fileName = MF[i]; //save this filename for later use
914          }
915          break; //stop here, the file was already found and loaded
916        }
917      }
918    }else{
919      QString bin = ui->line_xdg_exec->text().section(" ",0,0,QString::SectionSkipEmpty).simplified();
920      if(bin.isEmpty()){ return; } //should never hit this - but just to make sure
921      //Generate a new mimetype
922      cmimetype = "application/x-"+bin;
923      MODULE.setXdgText("MimeType", cmimetype);
924      //Generate a new filename for this mime file
925      fileName = bin+"-xdg.xml";
926    }
927    //Now need to save the current values into the file (new or old, depending on earlier)
928    MODULE.setMimeText("type", cmimetype);
929    MODULE.setMimeText("pattern", newPatterns);
930    //don't worry about xmlns - it will be auto generated if not set when creating the file, otherwise will use the current setting
931    MODULE.saveMimeFile(fileName);
932}
933
934void MainGUI::slotXDGOptionChanged(QString tmp){
935  tmp.clear(); //remove warning about unused variables
936  ui->line_xdg_customicon->setEnabled(ui->radio_xdg_customicon->isChecked());
937  ui->push_xdg_savechanges->setEnabled(ui->list_xdg_files->currentRow()>=0);
938  ui->push_xdg_savenew->setEnabled(TRUE);
939}
940
941/*------------------------------------------------
942   SCRIPTS EDITOR OPTIONS
943  -------------------------------------------------
944*/
945void MainGUI::slotScriptChanged(int index){
946  //Update the GUI appropriately
947    QStringList exist = MODULE.existingScripts();
948    if( exist.contains(ui->list_scripts_file->currentText()) ){
949      //Read and display the script
950      QStringList contents = MODULE.readScript(ui->list_scripts_file->currentText());
951      ui->text_scripts_edit->setPlainText(contents.join("\n"));
952      //Setup display items
953      ui->push_scripts_create->setVisible(FALSE);
954      ui->push_scripts_remove->setVisible(TRUE);
955      ui->push_scripts_save->setVisible(TRUE);
956      ui->text_scripts_edit->setVisible(TRUE);
957    }else{
958      //Setup display items
959      ui->push_scripts_create->setVisible(TRUE);
960      ui->push_scripts_remove->setVisible(FALSE);
961      ui->push_scripts_save->setVisible(FALSE);
962      ui->text_scripts_edit->setVisible(FALSE);
963    }
964    if(index == 0){ ui->push_scripts_create->setVisible(FALSE); }
965    ui->push_scripts_save->setEnabled(FALSE); //disable the save button until something changes
966}
967
968void MainGUI::on_push_scripts_create_clicked(){
969  //Setup display items
970  ui->push_scripts_create->setVisible(FALSE);
971  ui->push_scripts_remove->setVisible(FALSE);
972  ui->push_scripts_save->setVisible(TRUE);
973  ui->text_scripts_edit->setVisible(TRUE);
974  ui->text_scripts_edit->clear();
975  ui->push_scripts_save->setEnabled(FALSE); //disable the save button until something changes
976}
977
978void MainGUI::on_push_scripts_remove_clicked(){
979  //Get the current file
980  QString filename = ui->list_scripts_file->currentText();
981  //Remove the file
982  MODULE.removeScript(filename);
983  //refresh the UI
984  refreshGUI("scripts");
985}
986
987void MainGUI::on_push_scripts_save_clicked(){
988  //Get the current file text
989  QStringList contents = ui->text_scripts_edit->toPlainText().split("\n");
990  //get the current file
991  QString filename = ui->list_scripts_file->currentText();
992  //Save the file
993  bool ok = MODULE.writeScript(filename,contents);
994  //display a warning if error
995  if(!ok){
996    QMessageBox::warning(this,tr("Error Saving File"), tr("Could not save the script")+"\n"+tr("Please check the file permissions and try again") );
997  }
998  //Now refresh the UI
999  refreshGUI("scripts");
1000}
1001
1002void MainGUI::slotScriptModified(){
1003  ui->push_scripts_save->setEnabled(TRUE);     
1004}
Note: See TracBrowser for help on using the repository browser.