source: src-qt4/EasyPBI/mainGUI.cpp @ 1620346

9.1-release9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3releng/10.1
Last change on this file since 1620346 was 1620346, checked in by Kris Moore <kris@…>, 19 months ago

Initial import of PC-BSD /current/ SVN repo

  • Property mode set to 100644
File size: 58.6 KB
Line 
1#include "mainGUI.h"
2#include "ui_mainGUI.h"
3#include "modBuild.h"
4#include "backend.h"
5#include "newModuleDialog.h"
6#include "preferencesDialog.h"
7#include "aboutDialog.h"
8#include "portsDialog.h"
9
10MainGUI::MainGUI(QWidget *parent) :
11    QMainWindow(parent),
12    ui(new Ui::MainGUI)
13{
14        // NOTE: "plus"/"minus" icons are set in QtDesigner using the current theme
15        //      since none are available in the Qt Embedded resources
16       
17       //Setup Initial state of GUI objects and connect signal/slots
18       ui->setupUi(this);  //load the mainGUI.ui file
19        // Create the module class as necessary
20        currentModule = new ModBuild();
21        // Create the config class
22        settings = new Config();
23        //Setup the Menu items
24        ui->actionExit->setIcon(Backend::icon(""));
25        //Setup the pushbutton menu lists
26        menu_elOpts.addAction("binary");
27        menu_elOpts.addAction("linux");
28        menu_elOpts.addAction("keep");
29        menu_elOpts.addAction("replace");
30        menu_elOpts.addAction("nocrash");
31        //Setup Toolbar
32        ui->actionNew_Module->setIcon(Backend::icon("new"));
33        ui->actionLoad_Module->setIcon(Backend::icon("load"));
34        line_module = new QLineEdit(this);
35        line_module->setPlaceholderText(tr("No Module Loaded"));
36        line_module->setReadOnly(TRUE);
37        line_module->setFocusPolicy(Qt::NoFocus);
38        ui->toolBar->addWidget(line_module);
39        ui->toolBar->addSeparator();
40        radio_module_port = new QRadioButton(tr("FreeBSD Port"),this);
41        radio_module_port->setEnabled(FALSE);
42        ui->toolBar->addWidget(radio_module_port);
43        radio_module_local = new QRadioButton(tr("Local Sources"),this);
44        radio_module_local->setEnabled(FALSE);
45        ui->toolBar->addWidget(radio_module_local);
46        //Setup Module Editor
47        connect(ui->tabWidget, SIGNAL(currentChanged(int)),this,SLOT(slotModTabChanged(int)) ); //setup to refresh each tab once it is selected
48        // -- pbi.conf tab --
49        ui->push_change_progdir->setIcon(Backend::icon("load"));
50        ui->push_change_makeport->setIcon(Backend::icon("file"));
51        ui->push_addmakeopt->setIcon(Backend::icon("left"));
52        ui->push_addmakeopt->setMenu(&menu_addOpt);
53        connect(&menu_addOpt,SIGNAL(triggered(QAction*)),this,SLOT(slotAddMakeOption(QAction*)) );
54        ui->push_config_save->setIcon(Backend::icon("save"));
55        // -- resources tab --
56        ui->push_resources_savewrapper->setIcon(Backend::icon("save"));
57        connect(ui->listw_resources, SIGNAL(itemSelectionChanged()), this, SLOT(slotResourceChanged()) );
58        connect(ui->push_resources_savewrapper, SIGNAL(clicked()), this, SLOT(slotResourceScriptSaved()) );
59        // -- XDG entries tab --
60        connect(ui->radio_xdg_desktop,SIGNAL(clicked()),this,SLOT(slotXdgTypeChanged()) );
61        connect(ui->radio_xdg_menu,SIGNAL(clicked()),this,SLOT(slotXdgTypeChanged()) );
62        connect(ui->list_xdg_files,SIGNAL(itemSelectionChanged()), this, SLOT(slotXdgFileChanged()) );
63        ui->push_xdg_refresh->setIcon(Backend::icon("refresh"));
64        connect(ui->push_xdg_refresh, SIGNAL(clicked()), this, SLOT(slotXdgTypeChanged()) );
65        ui->push_xdg_exec->setIcon(Backend::icon("left"));
66        ui->push_xdg_exec->setMenu(&menu_bins);
67        connect(&menu_bins, SIGNAL(triggered(QAction*)), this, SLOT(slotAddBin(QAction*)) );
68        ui->push_xdg_savechanges->setIcon(Backend::icon("save"));
69        ui->push_xdg_menu->setIcon(Backend::icon("left"));
70        ui->push_xdg_menu->setMenu(&menu_validMenuCats);
71        connect(&menu_validMenuCats,SIGNAL(triggered(QAction*)),this,SLOT(slotAddMenuCat(QAction*)) );
72        ui->push_xdg_clearentry->setIcon(Backend::icon("file"));
73       
74        // -- Scripts tab --
75        ui->push_scripts_save->setIcon(Backend::icon("save"));
76        ui->push_scripts_create->setIcon(Backend::icon("new"));
77        ui->list_scripts_file->addItems(QStringList() << " ---"+tr("Installation Scripts")+"---" << "pre-portmake.sh" << "post-portmake.sh" << "pre-pbicreate.sh" << "pre-install.sh" << "post-install.sh" << "pre-remove.sh" );
78        connect(ui->list_scripts_file, SIGNAL(currentIndexChanged(int)), this, SLOT(slotScriptChanged(int)) );
79        // -- External links tab --
80        ui->push_el_file->setIcon(Backend::icon("left"));
81        ui->push_el_file->setMenu(&menu_el_bins);
82        connect(&menu_el_bins,SIGNAL(triggered(QAction*)),this,SLOT(slotELSetFile(QAction*)) );
83        ui->push_el_filetype->setIcon(Backend::icon("left"));
84        ui->push_el_filetype->setMenu(&menu_elOpts);
85        connect(&menu_elOpts,SIGNAL(triggered(QAction*)),this,SLOT(slotELSetType(QAction*)) );
86        //Setup PBI Builder
87        ui->push_build_stop->setIcon(Backend::icon("close"));
88        ui->push_build_save->setIcon(Backend::icon("save"));
89       
90      SetupDefaults(); //load program defaults
91      refreshGUI("all"); //make items visible/invisible as necessary
92     
93}
94
95MainGUI::~MainGUI()
96{
97  qDebug() << "Shutting down EasyPBI normally";
98}
99
100void MainGUI::slotSingleInstance(){
101  this->showNormal();
102  this->activateWindow();
103  this->raise();
104}
105
106void MainGUI::SetupDefaults(){
107    qDebug() << "Starting up EasyPBI (version "+settings->value("version")+")"; 
108    //Make sure that the program is not being started with root permissions
109    QString id = QProcessEnvironment::systemEnvironment().toStringList().filter("HOME=").join(" ").simplified();
110    if( id.contains("root") ){
111      qDebug() << "EasyPBI should not be run with root permissions! exiting.....";
112      exit(1);
113    }
114
115    //Load the current configuration settings
116    settings->readMachineArch(); //set the 64-bit flag as appropriate
117    //Scan for the external utilities needed to build PBI's
118    settings->scanForExternalUtilities();
119    //Load Preferences file if possible
120    settings->loadSettingsFile();
121    //create the EasyPBI directory structure if needed
122    if( !settings->checkDirectoryStructure() ){
123        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.") );
124        exit(1);
125    }
126    //Pop up a warning box if some external resources are not available
127    bool chkOK = (settings->check("isMakeportAvailable") && settings->check("iscreateAvailable") && settings->check("isSUavailable") );
128    if( !chkOK ){
129        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 preferences to correct this deficiency.") );
130    }
131    //Pop up a warning about a missing ports tree
132    if( !settings->check("isPortsAvailable") ){
133        QMessageBox::warning(this, tr("FreeBSD Ports Missing"), tr("The FreeBSD ports tree is missing from your system.")+"\n"+tr("Please open up the appropriate EasyPBI menu option to correct this deficiency.") );
134    }
135    //Set a couple more internal flags
136    PBI_BUILDING_NOW.clear();
137    PBI_BUILD_TERMINATED=FALSE;
138}
139
140bool MainGUI::isValidPort(QString pPath){
141  bool ok = FALSE;
142  if( QFile::exists(pPath) && QFile::exists(pPath+"/Makefile") && QFile::exists(pPath+"/distinfo") ){
143    ok = TRUE;
144  }
145  return ok;
146}
147
148void MainGUI::refreshGUI(QString item){
149  //Enable/disable the interface appropriately
150 
151  //Stupid check to make sure that a module is actually loaded
152  if( currentModule->path().isEmpty() ){ 
153    ui->actionPackage_Module->setEnabled(FALSE);
154    if(PBI_BUILDING_NOW.isEmpty() ){ui->toolBox->setEnabled(FALSE); return; }
155    else{ 
156      ui->toolBox->setItemEnabled(0,FALSE);
157      ui->toolBox->setItemEnabled(1,TRUE);
158      ui->toolBox->setCurrentIndex(1); 
159      item="pbibuild";
160    }
161  }else{ 
162    ui->toolBox->setEnabled(TRUE); 
163    ui->actionPackage_Module->setEnabled(TRUE); 
164  }
165  //Figure out the type of module that is loaded
166  bool isport = radio_module_port->isChecked();
167  //See if we should refresh everything (default) 
168  bool doall = ( (item == "all") || item.isEmpty() );
169  bool doeditor = (item == "editor"); //also add a flag to just refresh the editor
170  //Refresh the desired tab(s)
171  // ------PBI.CONF------
172  if( doall || doeditor || (item == "pbiconf")){
173    if(isport){
174        ui->line_progversion->setVisible(FALSE); ui->label_progversion->setVisible(FALSE);
175        ui->line_progdir->setVisible(FALSE); ui->push_change_progdir->setVisible(FALSE); ui->label_progdir->setVisible(FALSE);
176        ui->line_makeport->setVisible(TRUE); ui->push_change_makeport->setVisible(TRUE); ui->label_makeport->setVisible(TRUE);
177        ui->edit_makeopts->setVisible(TRUE); ui->push_addmakeopt->setVisible(TRUE); ui->label_makeopts->setVisible(TRUE);
178        ui->list_portbefore->setVisible(TRUE); ui->push_addportbefore->setVisible(TRUE); ui->push_rmportbefore->setVisible(TRUE);ui->label_portbefore->setVisible(TRUE);
179        ui->list_portafter->setVisible(TRUE); ui->push_addportafter->setVisible(TRUE); ui->push_rmportafter->setVisible(TRUE); ui->label_portafter->setVisible(TRUE);
180    }else{
181        ui->line_progversion->setVisible(TRUE); ui->label_progversion->setVisible(TRUE);
182        ui->line_progdir->setVisible(TRUE); ui->push_change_progdir->setVisible(TRUE); ui->label_progdir->setVisible(TRUE);
183        ui->line_makeport->setVisible(FALSE); ui->push_change_makeport->setVisible(FALSE); ui->label_makeport->setVisible(FALSE);
184        ui->edit_makeopts->setVisible(FALSE); ui->push_addmakeopt->setVisible(FALSE); ui->label_makeopts->setVisible(FALSE);
185        ui->list_portbefore->setVisible(FALSE); ui->push_addportbefore->setVisible(FALSE); ui->push_rmportbefore->setVisible(FALSE);ui->label_portbefore->setVisible(FALSE);
186        ui->list_portafter->setVisible(FALSE); ui->push_addportafter->setVisible(FALSE); ui->push_rmportafter->setVisible(FALSE); ui->label_portafter->setVisible(FALSE);
187    }
188    //Display the variables from the currentModule structure
189    // -- check boxes
190    QString chk = currentModule->readValue("requiresroot").toLower();
191    if( (chk=="true") || (chk=="yes") ){ ui->check_requiresroot->setChecked(TRUE); }
192    else{ ui->check_requiresroot->setChecked(FALSE); }
193    // -- line edits
194    ui->line_progname->setText(currentModule->readValue("progname"));
195    ui->line_progversion->setText(currentModule->readValue("progversion"));
196    ui->line_progweb->setText(currentModule->readValue("progweb"));
197    ui->line_progauthor->setText(currentModule->readValue("progauthor"));
198    ui->line_progdir->setText(currentModule->readValue("packagedir"));
199    ui->line_makeport->setText(currentModule->readValue("makeport"));
200    ui->edit_makeopts->setPlainText(currentModule->readValue("makeoptions"));
201    // -- combo boxes (lists)
202    ui->list_portbefore->clear(); ui->list_portafter->clear(); ui->list_progicon->clear();
203    ui->list_portbefore->addItems( currentModule->readValue("makeportbefore").split(" ") );
204    ui->list_portafter->addItems( currentModule->readValue("makeportafter").split(" ") );
205    QStringList icons = currentModule->currentIcons;
206    if(icons.length() > 0){
207      for(int i=0; i<icons.length(); i++){
208        ui->list_progicon->addItem(QIcon(currentModule->path()+"/resources/"+icons[i]),icons[i]);
209      }     
210      int cicon = icons.indexOf(currentModule->readValue("progicon"));
211      if( cicon == -1 ){ 
212              ui->list_progicon->addItem(currentModule->readValue("progicon")); 
213              cicon = icons.indexOf(currentModule->readValue("progicon"));
214      }
215      ui->list_progicon->setCurrentIndex(cicon);
216    }else{
217      ui->list_progicon->addItem(currentModule->readValue("progicon"));
218    }
219    menu_addOpt.clear();
220    QStringList opts = currentModule->readValue("portoptions").split(" ",QString::SkipEmptyParts);
221    if(!opts.isEmpty()){
222      for(int i=0; i<opts.length(); i++){
223        menu_addOpt.addAction(opts[i]);
224      }
225    }
226  }
227  // -----RESOURCES--------
228  if( doall || doeditor || (item == "resources")){
229    //Get the all the current files in the resources category and add them to the list
230    QStringList rs = currentModule->filesAvailable("resources");
231    //disconnect the signal/slot connection to make sure we don't get an extra phantom refresh
232    disconnect(ui->listw_resources, SIGNAL(itemSelectionChanged()), this, SLOT(slotResourceChanged()) );
233    //Update the Widget
234    ui->listw_resources->clear();
235    ui->listw_resources->addItems(rs);
236    //re-connect the signal/slot
237    connect(ui->listw_resources, SIGNAL(itemSelectionChanged()), this, SLOT(slotResourceChanged()) );
238    //Load the file into the viewers
239    slotResourceChanged();
240  }
241  //------XDG------
242  if( doall || doeditor || (item == "xdg")){
243    slotXdgTypeChanged();
244  }
245  //------SCRIPTS-----
246  if( doall || doeditor || (item == "scripts")){
247    //Update the list of available scripts and determine if one needs to be read
248    bool loadScript = FALSE;
249    QString path = currentModule->path()+"/scripts/";
250    int currentIndex = ui->list_scripts_file->currentIndex();
251    for(int i=1; i< ui->list_scripts_file->count(); i++){ //Skip the first item (is nothing)
252      if( QFile::exists( path+ui->list_scripts_file->itemText(i) ) ){
253        if(i == currentIndex){ loadScript = TRUE; }
254        ui->list_scripts_file->setItemIcon(i,Backend::icon("file"));
255      }else{
256        ui->list_scripts_file->setItemIcon(i,Backend::icon("close"));
257      }
258    }
259    //Update the GUI appropriately
260    if(loadScript){
261      //Read and display the script
262      QStringList contents = ModBuild::readFile(path+ui->list_scripts_file->currentText());
263      ui->text_scripts_edit->setPlainText(contents.join("\n"));
264      //Setup display items
265      ui->push_scripts_create->setVisible(FALSE);
266      ui->push_scripts_remove->setVisible(TRUE);
267      ui->push_scripts_save->setVisible(TRUE);
268      ui->text_scripts_edit->setVisible(TRUE);
269    }else{
270      //Setup display items
271      ui->push_scripts_create->setVisible(TRUE);
272      ui->push_scripts_remove->setVisible(FALSE);
273      ui->push_scripts_save->setVisible(FALSE);
274      ui->text_scripts_edit->setVisible(FALSE);
275    }
276    if(currentIndex == 0){ ui->push_scripts_create->setVisible(FALSE); }
277   
278  }
279  //------EXTERNAL-LINKS------
280  if( doall || doeditor || (item == "external-links")){
281    //nothing to make visible/invisible here
282    //Load the external-links file
283    ui->tree_el_view->clear();
284    QStringList cLinks = currentModule->externalLinks();
285    QStringList labels; labels << tr("File") << tr("Link To") << tr("File Type");
286    for( int i=0; i<cLinks.length(); i++ ){
287      QStringList link = cLinks[i].split("\t");
288      ui->tree_el_view->addTopLevelItem(new QTreeWidgetItem(link));
289    }
290    //Clear the input boxes
291    ui->line_el_file->clear();
292    ui->line_el_linkto->clear();
293    ui->line_el_filetype->clear();
294    //update the available binaries
295    menu_el_bins.clear();
296    QStringList cBins = currentModule->currentBins;
297    if(!cBins.isEmpty()){
298      for(int i=0; i<cBins.length(); i++){
299        menu_el_bins.addAction(cBins[i]);
300      } 
301    }
302  }
303  //------FREENAS PLUGINS-------
304  if( doall || doeditor || (item == "freenas")){
305    //nothing to make visible/invisible here
306  }
307  //------PBI BUILDER--------
308  if( doall || (item == "pbibuild")){
309    if(PBI_BUILDING_NOW.isEmpty()){
310      //only change things if there is nothing building at the moment
311      if(ui->text_build_log->toPlainText().isEmpty()){ ui->push_build_save->setEnabled(FALSE); }
312      else{ ui->push_build_save->setEnabled(TRUE); }
313    }
314    ui->push_build_start->setFocus();//make sure the focus starts out on the build button
315  }
316  //------OVERALL SETTINGS------
317  if( doall || doeditor ){
318    //Enable/disable the buttons that require the FreeBSD ports tree
319    if( settings->check("isportsavailable") ){
320      ui->push_change_makeport->setEnabled(TRUE);
321      ui->push_addportbefore->setEnabled(TRUE);
322      ui->push_addportafter->setEnabled(TRUE);
323    }else{
324      ui->push_change_makeport->setEnabled(FALSE);
325      ui->push_addportbefore->setEnabled(FALSE);
326      ui->push_addportafter->setEnabled(FALSE);
327    }
328    //Check for a 64-bit system to enable the 32-bit build option
329    if( settings->check("is64bit") && !currentModule->isLocalPBI ){ ui->check_build_32->setVisible(TRUE); }
330    else{ ui->check_build_32->setVisible(FALSE); ui->check_build_32->setChecked(FALSE); }
331    //Disable tabs that are not used when bulding local PBI's
332    if(currentModule->isLocalPBI){
333        ui->tabWidget->setTabEnabled(5,FALSE);
334    }else{
335        ui->tabWidget->setTabEnabled(5,TRUE);
336    }
337    //Set the default focus on the "load" button
338    this->setFocus();
339  }
340}
341/*----------------------------------
342   MENU OPTIONS
343  -----------------------------------
344*/
345void MainGUI::on_actionGet_Ports_triggered(){
346  portsDialog dlg(this,settings->value("progdir")+"/ports",settings->value("su_cmd") );
347  dlg.exec();
348}
349
350void MainGUI::on_actionExit_triggered(){
351  qDebug() << "Close EasyPBI requested";
352  this->close();
353}
354
355void MainGUI::on_actionPreferences_triggered(){
356  //Open up the preferences dialog
357  PreferencesDialog dlg(this);
358  //make the dialog modal and wait for it to close
359  dlg.exec(); 
360  //Now reload the saved settings
361  settings->loadSettingsFile();
362  //Now refresh the GUI
363  refreshGUI("all");
364}
365void MainGUI::on_actionPackage_Module_triggered(){
366   currentModule->compressModule();
367   QMessageBox::information(this,tr("Success"),tr("A copy of the current module has been successfully packaged  within the module directory.") );
368
369}
370
371void MainGUI::on_actionFreeBSD_Ports_triggered(){
372  QString port;
373  if(!line_module->text().isEmpty()){
374        //Get the currently selected port
375        port = currentModule->readValue("makeport");
376  }
377  QString target_url = "http://www.freshports.org/" + port;
378  qDebug() << "Opening URL:" << target_url; 
379  target_url.prepend("xdg-open ");
380  system(target_url.toUtf8()); 
381}
382
383void MainGUI::on_actionPBI_Modules_triggered(){
384  //Open the PC-BSD wiki to the module builders guide
385   QString target_url = "http://wiki.pcbsd.org/index.php/PBI_Module_Builder_Guide";
386   qDebug() << "Opening URL:" << target_url; 
387   target_url.prepend("xdg-open ");
388   system(target_url.toUtf8());
389}
390
391void MainGUI::on_actionAbout_EasyPBI_triggered(){
392  aboutDialog dlg(this,settings->value("version"));
393  dlg.exec();
394}
395
396
397/*----------------------------------
398   TOOLBAR OPTIONS
399  -----------------------------------
400*/
401void MainGUI::on_actionNew_Module_triggered(){
402  qDebug() << "New Module triggered";
403  //Create and run the new dialog
404  NewModuleDialog* dlg = new NewModuleDialog(this, settings->value("portsdir"));
405  dlg->setDefaultIconFile(settings->value("defaulticon"));
406  dlg->exec();
407  //Determine if the action was cancelled
408  if( dlg->isAccepted ){
409    //Now create the new module
410    QString modPath, modType, modBase, oldIconPath;
411    modType = dlg->moduleType;
412    modBase = dlg->moduleData;
413    oldIconPath = dlg->moduleIcon;
414    modPath = settings->value("moduledir")+"/"+modBase.section("/",-1).toLower();
415          //modPath ->full path, modType->"local"or "port", modBase->makeport or packagedir
416    bool ok = currentModule->createNewModule(modPath,modType,modBase);
417    if(!ok){
418      QMessageBox::warning(this,tr("EasyPBI: Permissions Error"), tr("Could not create PBI module. Please check the directory permissions and try again."));
419    }else{
420      //MODULE CREATED, NOW FILL IT APPROPRIATELY
421      //Icon
422      currentModule->addResource(FALSE, oldIconPath); //copy the icon file into the module
423      currentModule->writeValue("progicon", oldIconPath.section("/",-1) );
424      //Load Port info if appropriate
425      if(currentModule->isPortPBI){
426        radio_module_port->toggle();
427        //Use the port info if possible
428        if( settings->check("isportsAvailable") ){
429          currentModule->readPortInformation(settings->value("portsdir")+"/"+modBase);
430          //Now save the detected information into the module
431          currentModule->writeValue("progname", currentModule->readValue("portname"));
432          currentModule->writeValue("progweb", currentModule->readValue("portwebsite"));
433          currentModule->writeValue("progauthor", currentModule->readValue("portauthor"));
434          currentModule->writePBIconf();
435        }
436      }else if(currentModule->isLocalPBI){
437        radio_module_local->toggle();
438             
439      }
440      //Now let the UI reflect the new module
441      line_module->setText( currentModule->path().replace(QDir::homePath(),"~") );     
442    }
443  }
444  //Refresh the UI
445  refreshGUI("all");
446  delete dlg;
447}
448
449void MainGUI::on_actionLoad_Module_triggered(){
450  QString modSel = QFileDialog::getExistingDirectory(this, tr("Select Module"), settings->value("moduledir"));
451  if(modSel.isEmpty()){return;} //action cancelled or closed
452  bool ok = currentModule->loadModule(modSel);
453  if(ok){ 
454    qDebug() << "Loaded module:"<<modSel;         
455    line_module->setText(modSel.replace(QDir::homePath(),"~")); 
456    if(currentModule->isLocalPBI){ radio_module_local->toggle(); }
457    else{ 
458      radio_module_port->toggle(); //Port PBI
459      if( settings->check("isportsavailable") ){ 
460        currentModule->readPortInformation(settings->value("portsdir")+"/"+currentModule->readValue("makeport"));
461      }
462    }
463    refreshGUI("all");
464  }
465}
466
467/*----------------------------------
468   MODULE EDITOR OPTIONS
469  -----------------------------------
470*/
471void MainGUI::slotModTabChanged(int newtab){
472  switch(newtab){
473    case 0:
474            refreshGUI("pbiconf"); break;
475    case 1:
476            refreshGUI("resources"); break;
477    case 2:
478            refreshGUI("xdg"); break;
479    case 3:
480            refreshGUI("scripts"); break;
481    case 4:
482            refreshGUI("external-links"); break;
483    case 5:
484            refreshGUI("freenas"); break;
485    default:
486            refreshGUI("editor"); break; //do all the module editor tabs
487  }       
488}
489
490/*----------------------------------
491   PBI.CONF OPTIONS
492  -----------------------------------
493*/
494void MainGUI::on_push_change_makeport_clicked(){
495  if( !settings->check("isportsavailable") ){
496    //No ports tree available
497    QMessageBox::warning(this,tr("EasyPBI: No FreeBSD Ports"), tr("The FreeBSD Ports tree could not be found on your system. You may fetch the ports tree through the EasyPBI menu or manually set the path to the port tree in the EasyPBI preferences if it is installed in a non-standard location."));
498    return;
499  }
500  //Prompt for a new port
501  QString portSel = QFileDialog::getExistingDirectory(this, tr("Select Port"), settings->value("portsdir"));
502  if(portSel.isEmpty()){return;} //action cancelled or closed   
503  //Check if the port is valid
504  if( !isValidPort(portSel) ){
505    QMessageBox::warning(this,tr("EasyPBI: Invalid Port"), tr("The directory selected is not a valid FreeBSD port. Please select a port directory which contains the appropriate Makefile and distinfo."));
506    return;
507  }
508  //Save the port info to the GUI
509  ui->line_makeport->setText(portSel.remove(settings->value("portsdir")+"/"));
510}
511
512void MainGUI::on_push_change_progdir_clicked(){
513  //Prompt for a new directory
514  QString dirSel = QFileDialog::getExistingDirectory(this, tr("Select Package Directory"), QDir::homePath());
515  if(dirSel.isEmpty()){return;} //action cancelled or closed   
516  //Save the port info to the GUI
517  ui->line_progdir->setText(dirSel);
518}
519
520void MainGUI::slotAddMakeOption(QAction* act){
521  qDebug() << "Trying to add build option:" << act->text();
522  QString opt = act->text();
523  if(opt.isEmpty() ){ return; } //Do nothing if nothing selected
524  //Check whther the option is set or unset
525  QString typ = opt.section("_",0,0,QString::SectionSkipEmpty).toLower(); //get the type
526  opt = opt.section("_",1,50,QString::SectionSkipEmpty); //trim off the type of setting
527  QString chk = currentModule->readValue("makeport").section("/",-1);
528  bool isSet;
529  if(typ == "with"){chk.append("_SET"); isSet=TRUE;}
530  else if(typ=="without"){chk.append("_UNSET"); isSet=FALSE;}
531  else{ qDebug() << "Error: Unknown option type:"<<typ<<"option:"<<opt; return; }
532  //Now read the current option settings
533  QStringList curr = ui->edit_makeopts->toPlainText().split("\n"); //split according to lines
534  bool found = FALSE;
535  for(int i=0; i<curr.length(); i++){
536    if(curr[i].contains(chk) ){ //look for optionsNG framework
537      found = TRUE;         
538      QStringList cOpts = curr[i].split(" ",QString::SkipEmptyParts);
539      if( !cOpts.contains(opt) ){
540        //Not found, add it to the end of the list
541        cOpts << opt;
542        curr[i] = cOpts.join(" ");
543      }
544    }else if(curr[i].contains(opt)){ //look for legacy options framework
545      QStringList cOpts = curr[i].split(" ",QString::SkipEmptyParts);
546      int index = cOpts.indexOf(opt);
547      if(index != -1){ //option currently set somehow
548        found = TRUE; 
549        if(isSet){ //option should be set
550          if( cOpts[index].contains("WITH_"+opt) ){} //Already set
551          else if( cOpts[index].contains("WITHOUT_"+opt) ){ cOpts[index] = "WITH_"+opt+"=true"; }
552          else if( curr[i].contains(chk.replace("_SET","_UNSET")) ){ cOpts.removeAt(index); found=FALSE;} //Remove the inverse option if it is set
553        }else{ //options should be unset
554          if( cOpts[index].contains("WITHOUT_"+opt) ){} //Already set
555          else if( cOpts[index].contains("WITH_"+opt) ){ cOpts[index] = "WITHOUT_"+opt+"=true"; }
556          else if( curr[i].contains(chk.replace("_UNSET","_SET")) ){ cOpts.removeAt(index); found=FALSE;} //Remove the inverse option if it is set
557        }
558        curr[i] = cOpts.join(" "); //put the line back together
559      }
560    } //end checking different options frameworks
561  } // end loop over lines
562  if(!found){
563    //Append the option to the end on a new line
564    curr << chk+"= "+opt;
565  }
566  //Now put the new options list back onto the GUI
567  ui->edit_makeopts->setPlainText(curr.join("\n"));
568}
569
570void MainGUI::on_push_addportbefore_clicked(){
571  if( !settings->check("isportsavailable") ){
572    //No ports tree available
573    QMessageBox::warning(this,tr("EasyPBI: No FreeBSD Ports"), tr("The FreeBSD Ports tree could not be found on your system. You may fetch the ports tree through the EasyPBI menu or manually set the path to the port tree in the EasyPBI preferences if it is installed in a non-standard location."));
574  }
575  //Prompt for a new port
576  QString portSel = QFileDialog::getExistingDirectory(this, tr("Select Port"), settings->value("portsdir"));
577  if(portSel.isEmpty()){return;} //action cancelled or closed   
578  //Check if the port is valid
579  if( !isValidPort(portSel) ){
580    QMessageBox::warning(this,tr("EasyPBI: Invalid Port"), tr("The directory selected is not a valid FreeBSD port. Please select a port directory which contains the appropriate Makefile and distinfo files."));
581    return;
582  }
583  //Save the port info to the GUI
584  if(ui->list_portbefore->count() == 1 && ui->list_portbefore->currentText().isEmpty() ){ ui->list_portbefore->clear(); }
585  ui->list_portbefore->addItem(portSel.remove(settings->value("portsdir")+"/"));
586}
587
588void MainGUI::on_push_rmportbefore_clicked(){
589  int index = ui->list_portbefore->currentIndex();
590  if(index != -1){
591    ui->list_portbefore->removeItem(index);
592  }
593}
594
595void MainGUI::on_push_addportafter_clicked(){
596  if( !settings->check("isportsavailable") ){
597    //No ports tree available
598    QMessageBox::warning(this,tr("EasyPBI: No FreeBSD Ports"), tr("The FreeBSD Ports tree could not be found on your system. You may fetch the ports tree through the EasyPBI menu or manually set the path to the port tree in the EasyPBI preferences if it is installed in a non-standard location."));
599  }
600  //Prompt for a new port
601  QString portSel = QFileDialog::getExistingDirectory(this, tr("Select Port"), settings->value("portsdir"));
602  if(portSel.isEmpty()){return;} //action cancelled or closed   
603  //Check if the port is valid
604  if( !isValidPort(portSel) ){
605    QMessageBox::warning(this,tr("EasyPBI: Invalid Port"), tr("The directory selected is not a valid FreeBSD port. Please select a port directory which contains the appropriate Makefile and distinfo files."));
606    return;
607  }
608  //Save the port info to the GUI
609  if(ui->list_portafter->count() == 1 && ui->list_portafter->currentText().isEmpty() ){ ui->list_portafter->clear(); }
610  ui->list_portafter->addItem(portSel.remove(settings->value("portsdir")+"/"));
611}
612
613void MainGUI::on_push_rmportafter_clicked(){
614  int index = ui->list_portafter->currentIndex();
615  if(index != -1){
616    ui->list_portafter->removeItem(index);
617  }
618}
619
620void MainGUI::on_push_config_save_clicked(){
621  //Save the current settings to the backend structures
622    //global settings for all modules
623    currentModule->writeValue("progname",ui->line_progname->text());
624    currentModule->writeValue("progweb",ui->line_progweb->text());
625    currentModule->writeValue("progauthor",ui->line_progauthor->text());
626    currentModule->writeValue("progicon",ui->list_progicon->currentText());
627    if(ui->check_requiresroot->isChecked()){ currentModule->writeValue("requiresroot", "true"); }
628    else{ currentModule->writeValue("requiresroot","false"); }
629    //Module-dependant settings
630    bool newport = FALSE;
631    if( radio_module_port->isChecked() ){ //FreeBSD port module
632        if(currentModule->readValue("makeport") != ui->line_makeport->text()){ newport=TRUE; }
633        currentModule->writeValue("makeport",ui->line_makeport->text());
634        currentModule->writeValue("makeoptions",ui->edit_makeopts->toPlainText());
635        QString tmp;
636        for(int i=0; i < ui->list_portbefore->count(); i++){
637          tmp.append(" "+ui->list_portbefore->itemText(i) );
638        }
639        currentModule->writeValue("makeportbefore",tmp.simplified());
640        tmp.clear();
641        for(int i=0; i < ui->list_portafter->count(); i++){
642          tmp.append(" "+ui->list_portafter->itemText(i) );
643        }
644        currentModule->writeValue("makeportafter",tmp.simplified());
645       
646    }else{ //local sources module
647        currentModule->writeValue("packagedir",ui->line_progdir->text());
648        currentModule->writeValue("progversion",ui->line_progversion->text());
649    }
650  //save the new settings to pbi.conf
651  bool ok = currentModule->writePBIconf();
652  if(!ok){
653    //Display a warning that the file could not be saved
654    qDebug() << "Error: pbi.conf could not be written:" << currentModule->path()+"/pbi.conf";
655    QMessageBox::warning(this,tr("EasyPBI Error"), tr("The PBI configuration file could not be saved. Please check your file permissions before trying again."));
656  }else if(newport){
657    //Refresh the port information if the main port changed
658    currentModule->readPortInformation(settings->value("portsdir")+"/"+ui->line_makeport->text());
659    refreshGUI("pbiconf");
660  }
661}
662/*------------------------------------------------
663   RESOURCE EDITOR OPTIONS
664  -------------------------------------------------
665*/
666void MainGUI::slotResourceChanged(){
667  //Get the current file selected
668  QString cfile;
669  if(ui->listw_resources->currentRow() != -1){ cfile = ui->listw_resources->currentItem()->text(); }
670  if(cfile.isEmpty()){ //no item selected
671    ui->push_resources_savewrapper->setVisible(FALSE);
672    ui->text_resources_script->setVisible(FALSE);
673    ui->label_resources_description->setVisible(FALSE);
674    ui->label_resources_icon->setVisible(FALSE);
675         
676  }else{ //item selected
677    QString path = currentModule->path() + "/resources/";
678    if( cfile.endsWith(".png") || cfile.endsWith(".jpg") ){
679      //Image file, show full size
680      QPixmap img(path+cfile);
681      ui->label_resources_icon->setPixmap(img);
682      ui->label_resources_icon->setVisible(TRUE);
683      QString desc = QString::number(img.width()) +" x "+QString::number(img.height())+" "+cfile.section(".",-1).toUpper();
684      ui->label_resources_description->setText(desc);
685      ui->label_resources_description->setVisible(TRUE);
686      //hide the other widgets
687      ui->push_resources_savewrapper->setVisible(FALSE);
688      ui->text_resources_script->setVisible(FALSE);
689    }else{
690      ui->push_resources_savewrapper->setVisible(TRUE);
691      QStringList contents = ModBuild::readFile(path+cfile);
692      ui->text_resources_script->clear();
693      ui->text_resources_script->setText(contents.join("\n"));
694      ui->text_resources_script->setVisible(TRUE);
695      //hide the other widgets
696      ui->label_resources_description->setVisible(FALSE);
697      ui->label_resources_icon->setVisible(FALSE);
698    }
699  }       
700 
701}
702
703void MainGUI::on_push_resources_add_clicked(){
704  //Get the desired file
705  QStringList iFiles = QFileDialog::getOpenFileNames(this, tr("Select Resources"), settings->value("icondir") );
706  //Check that there were file selected
707  if(iFiles.isEmpty()){ return; }
708  //Now add these files to the module
709  for(int i=0; i<iFiles.length(); i++){
710    currentModule->addResource(FALSE,iFiles[i]);
711  }
712  //Now update the GUI
713  refreshGUI("resources");
714}
715
716void MainGUI::on_push_resources_remove_clicked(){
717  //Get the currently selected resource
718  QString cfile;
719  if(ui->listw_resources->currentRow() != -1){ cfile = ui->listw_resources->currentItem()->text(); }
720  //Check that there is something selected 
721  if(cfile.isEmpty()){ return; }
722  //Remove the resource
723  if(currentModule->removeResource(cfile)){
724      qDebug() << "Removed Resource:" << cfile;
725  }else{
726      qDebug() << "Error: Could not remove resource:"<<cfile;
727  }
728  //Refresh the GUI
729  refreshGUI("resources");
730}
731
732void MainGUI::on_push_resources_mkwrapper_clicked(){
733  //Get the desired filename for the wrapper script
734  bool ok;
735  QString cFile = QInputDialog::getText(this, tr("New Wrapper Script"), tr("Filename")+":", QLineEdit::Normal, "",&ok);
736  //Check for a valid input
737  if(!ok || cFile.isEmpty()){ return; }
738  //Now create the new file
739  currentModule->addResource(TRUE,cFile);
740  //Refresh the GUI
741  refreshGUI("resources");
742}
743
744void MainGUI::slotResourceScriptSaved(){
745  //get the current file and path
746  QString cfile;
747  if(ui->listw_resources->currentRow() != -1){ cfile = ui->listw_resources->currentItem()->text(); }
748  if(cfile.isEmpty()){ return; } // do nothing if no file selected
749  QString filePath = currentModule->path() + "/resources/" + cfile;
750  //Read the current text for the resource
751  QStringList contents = ui->text_resources_script->toPlainText().split("\n");
752  //overwrite the resource with the new contents
753  ModBuild::createFile(filePath,contents);
754}
755/*------------------------------------------------
756   XDG EDITOR OPTIONS
757  -------------------------------------------------
758*/
759void MainGUI::slotXdgTypeChanged(){
760  //Update the file list appropriately
761  if(ui->radio_xdg_desktop->isChecked()){
762    //update the files available
763    ui->list_xdg_files->clear();
764    ui->list_xdg_files->addItems(currentModule->filesAvailable("xdg-desktop"));
765    //Set the visibility
766        //Current file
767        ui->label_xdg_name->setVisible(TRUE); ui->line_xdg_name->setVisible(TRUE);
768        ui->label_xdg_exec->setVisible(TRUE); ui->line_xdg_exec->setVisible(TRUE); ui->push_xdg_exec->setVisible(TRUE);
769        ui->label_xdg_icon->setVisible(TRUE); ui->list_xdg_icon->setVisible(TRUE);
770        ui->label_xdg_menu->setVisible(FALSE); ui->line_xdg_menu->setVisible(FALSE); ui->push_xdg_menu->setVisible(FALSE);
771        ui->check_xdg_nodisplay->setVisible(TRUE);
772        ui->check_xdg_terminal->setVisible(TRUE);
773        ui->label_xdg_mimepatterns->setVisible(FALSE); ui->line_xdg_mimepatterns->setVisible(FALSE);
774       
775  }else if(ui->radio_xdg_menu->isChecked()){
776    //update the files available
777    ui->list_xdg_files->clear();
778    ui->list_xdg_files->addItems(currentModule->filesAvailable("xdg-menu"));     
779    //Set the visibility
780        //Current file
781        ui->label_xdg_name->setVisible(TRUE); ui->line_xdg_name->setVisible(TRUE);
782        ui->label_xdg_exec->setVisible(TRUE); ui->line_xdg_exec->setVisible(TRUE); ui->push_xdg_exec->setVisible(TRUE);
783        ui->label_xdg_icon->setVisible(TRUE); ui->list_xdg_icon->setVisible(TRUE);
784        ui->label_xdg_menu->setVisible(TRUE); ui->line_xdg_menu->setVisible(TRUE); ui->push_xdg_menu->setVisible(TRUE);
785        ui->check_xdg_nodisplay->setVisible(TRUE);
786        ui->check_xdg_terminal->setVisible(TRUE);
787        ui->label_xdg_mimepatterns->setVisible(TRUE); ui->line_xdg_mimepatterns->setVisible(TRUE);
788       
789  }
790  //Select the first file in the list if one is available
791  if( ui->list_xdg_files->count() > 0){ ui->list_xdg_files->setCurrentRow(0); }
792  //Update the program icon list for new entries
793  //QStringList icons = currentModule->currentIcons;
794
795  //Update the buttons that only need a refresh when the type changes (such as menu's)
796  //Available binaries pushbuttons
797  menu_bins.clear();
798  QStringList cBins = currentModule->currentBins;
799  if(!cBins.isEmpty()){
800    for(int i=0; i<cBins.length(); i++){
801      menu_bins.addAction(cBins[i]);
802      //menu_binsnew.addAction(cBins[i]);
803    } 
804  }
805  //Menu categories
806  QString recMenu = currentModule->readValue("portmenucategory");
807  QStringList cats = currentModule->validMenuCategories;
808  menu_validMenuCats.clear();
809  for(int i=0; i<cats.length(); i++){
810    if(recMenu==cats[i]){ //Add an icon showing the recommended menu category
811      menu_validMenuCats.addAction(Backend::icon("start"),cats[i]);     
812    }else{
813      menu_validMenuCats.addAction(cats[i]);
814    }
815  }
816  //Now update read the currently selected file
817  slotXdgFileChanged();
818}
819
820void MainGUI::slotXdgFileChanged(){     
821  bool clearUI =FALSE;
822  if(ui->list_xdg_files->currentRow() == -1){ clearUI=TRUE; }
823
824  //Reset the icon list
825  ui->list_xdg_icon->clear();
826  QStringList icons = currentModule->currentIcons;
827  if(icons.length() > 0){
828      for(int i=0; i<icons.length(); i++){
829        ui->list_xdg_icon->addItem(QIcon(currentModule->path()+"/resources/"+icons[i]),icons[i]);
830      }     
831  }
832  //Get the selected file
833  QString file;
834  if( !clearUI ){ file = ui->list_xdg_files->currentItem()->text(); }
835  if( clearUI || file.isEmpty() ){
836    //Clear the UI lines
837    ui->line_xdg_name->clear();
838    ui->line_xdg_exec->clear();
839    ui->line_xdg_menu->clear();
840    ui->line_xdg_mimepatterns->clear();
841    ui->check_xdg_terminal->setChecked(FALSE);
842    ui->check_xdg_nodisplay->setChecked(FALSE);
843    ui->push_xdg_savechanges->setEnabled(FALSE);
844    //Make sure we don't have any of the structures loaded from previously
845    currentModule->loadDesktop("");
846    currentModule->loadMenu("");
847    currentModule->loadMime("");
848    //Now return
849    return; 
850  }
851  ui->push_xdg_savechanges->setEnabled(TRUE);
852  //Now setup the UI as appropriate
853  if(ui->radio_xdg_desktop->isChecked()){
854    //Load the file
855    currentModule->loadDesktop(file);
856    //update the file info on the GUI
857    ui->line_xdg_name->setText( currentModule->readValue("desktopname") );
858    ui->line_xdg_exec->setText( currentModule->readValue("desktopexec") ); 
859    //comboboxes
860    int cicon = icons.indexOf(currentModule->readValue("desktopicon"));
861    if( cicon == -1 ){ 
862      ui->list_xdg_icon->addItem(currentModule->readValue("desktopicon")); 
863      cicon = icons.indexOf(currentModule->readValue("desktopicon"));
864    }
865    ui->list_xdg_icon->setCurrentIndex(cicon);
866
867    //Checkboxes
868    QString chk = currentModule->readValue("desktopterminal").toLower();
869    if( (chk == "true") || (chk=="yes") ){ ui->check_xdg_terminal->setChecked(TRUE); }
870    else{ ui->check_xdg_terminal->setChecked(FALSE); }
871    chk = currentModule->readValue("desktopnodisplay").toLower();
872    if( (chk == "true") || (chk=="yes") ){ ui->check_xdg_nodisplay->setChecked(TRUE); }
873    else{ ui->check_xdg_nodisplay->setChecked(FALSE); }
874       
875  }else if(ui->radio_xdg_menu->isChecked()){
876    //Load the file
877    currentModule->loadMenu(file);
878    //update the file info on the GUI
879    ui->line_xdg_name->setText( currentModule->readValue("menuname") );
880    ui->line_xdg_exec->setText( currentModule->readValue("menuexec") ); 
881    ui->line_xdg_menu->setText( currentModule->readValue("menucategories") );
882    //comboboxes
883          //icons
884    int cicon = icons.indexOf(currentModule->readValue("menuicon"));
885    if( cicon == -1 ){ 
886      ui->list_xdg_icon->addItem(currentModule->readValue("menuicon")); 
887      cicon = icons.indexOf(currentModule->readValue("menuicon"));
888    }
889    ui->list_xdg_icon->setCurrentIndex(cicon);
890   
891    //Checkboxes
892    QString chk = currentModule->readValue("menuterminal").toLower();
893    if( (chk == "true") || (chk=="yes") ){ ui->check_xdg_terminal->setChecked(TRUE); }
894    else{ ui->check_xdg_terminal->setChecked(FALSE); }
895    chk = currentModule->readValue("menunodisplay").toLower();
896    if( (chk == "true") || (chk=="yes") ){ ui->check_xdg_nodisplay->setChecked(TRUE); }
897    else{ ui->check_xdg_nodisplay->setChecked(FALSE); }
898   
899    //Load the XDG-MIME file associations
900    QString mime = currentModule->readValue("menumimetype");
901    QStringList mimeavailable = currentModule->filesAvailable("xdg-mime");
902    bool found = FALSE;
903    for( int i=0; i<mimeavailable.length(); i++){
904      currentModule->loadMime(mimeavailable[i]);
905      if(currentModule->readValue("mimetype") == mime){
906        found = TRUE;
907        break;
908      }
909    }
910    //qDebug() << "mimetype detected:" << mime;
911    if(found){
912      ui->line_xdg_mimepatterns->setText( currentModule->readValue("mimepatterns") ); 
913    }else{
914      currentModule->loadMime(""); //Make sure we don't have any mime file loaded
915      ui->line_xdg_mimepatterns->clear();
916    }
917   
918  }else{
919    //do nothing, unknown radio button selected (or none)
920  }
921}
922
923void MainGUI::slotAddMenuCat(QAction* act){
924  //get the selected menu category
925  QString newcat = act->text();
926  //Read the current categories
927  QStringList oldcats = ui->line_xdg_menu->text().split(";", QString::SkipEmptyParts);
928  for(int i=0; i<oldcats.length(); i++){
929    oldcats[i] = oldcats[i].simplified();
930    if(oldcats[i] == newcat){return;} //category already in the list, do nothing
931  }
932  //Add the item
933  oldcats << newcat;
934  //Now replace the line onto the GUI
935  ui->line_xdg_menu->setText(oldcats.join("; "));
936}
937
938void MainGUI::slotAddBin(QAction* act){
939  //replace the current executable with the new one
940  ui->line_xdg_exec->setText(act->text().section("/",-1) );     
941}
942
943void MainGUI::on_push_xdg_remove_clicked(){
944  //Figure out if a file is selected
945  if( ui->list_xdg_files->currentItem()->text().isEmpty() ){ return; }
946  //Now remove the file
947  bool ok = FALSE;
948  if( ui->radio_xdg_desktop->isChecked() ){
949    ok = currentModule->removeDesktop();
950  }else if( ui->radio_xdg_menu->isChecked() ){
951    ok = currentModule->removeMenu();
952  }
953  //Now inform the user if there was an error
954  if(!ok){
955    QMessageBox::warning(this, tr("EasyPBI Error"), tr("Could not remove the XDG entry.")+"\n"+tr("Check the file permissions and try again") );
956  }
957  //Now refresh the GUI
958  refreshGUI("xdg");
959 
960}
961
962void MainGUI::on_push_xdg_savechanges_clicked(){
963  //save the current UI settings to the module structure then save the file
964  bool ok = FALSE;
965  if( ui->radio_xdg_desktop->isChecked() ){
966    currentModule->writeValue("desktopname",ui->line_xdg_name->text());
967    currentModule->writeValue("desktopgenericname",ui->line_xdg_name->text().toLower());
968    currentModule->writeValue("desktopexec",ui->line_xdg_exec->text());
969    currentModule->writeValue("desktopicon",ui->list_xdg_icon->currentText());
970    QString checked = "false";
971    if(ui->check_xdg_terminal->isChecked()){ checked="true"; }
972    currentModule->writeValue("desktopterminal",checked);
973    checked = "false";
974    if(ui->check_xdg_nodisplay->isChecked()){ checked="true"; }
975    currentModule->writeValue("desktopnodisplay",checked);
976    //Now save the file
977    ok = currentModule->writeDesktop();
978   
979  }else if( ui->radio_xdg_menu->isChecked() ){
980    currentModule->writeValue("menuname",ui->line_xdg_name->text());
981    currentModule->writeValue("menugenericname",ui->line_xdg_name->text().toLower());
982    currentModule->writeValue("menuexec",ui->line_xdg_exec->text());
983    currentModule->writeValue("menuicon",ui->list_xdg_icon->currentText());
984    currentModule->writeValue("menucategories", ui->line_xdg_menu->text());
985    QString checked = "false";
986    if(ui->check_xdg_terminal->isChecked()){ checked="true"; }
987    currentModule->writeValue("menuterminal",checked);
988    checked = "false";
989    if(ui->check_xdg_nodisplay->isChecked()){ checked="true"; }
990    currentModule->writeValue("menunodisplay",checked);
991    //Setup the mime type associations as appropriate
992    checkMime();
993    //Now save the file
994    ok = currentModule->writeMenu();   
995  }
996  //Now inform the user if there was an error
997  if(!ok){
998    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") );
999  }
1000  //Now refresh the GUI
1001  //refreshGUI("xdg"); //refresh the entire tab
1002  slotXdgFileChanged(); //only update the proper half of the tab
1003}
1004
1005void MainGUI::on_push_xdg_savenew_clicked(){
1006  //Get the filename we want to save
1007  QString filename;
1008  //Now check that the filename does not already exist
1009  QStringList cFiles;
1010  if(ui->radio_xdg_desktop->isChecked() ){
1011    filename = ui->line_xdg_exec->text();
1012    cFiles = currentModule->filesAvailable("xdg-desktop").replaceInStrings(".desktop","");
1013  }else if(ui->radio_xdg_menu->isChecked() ){
1014    filename = ui->line_xdg_exec->text();
1015    cFiles = currentModule->filesAvailable("xdg-menu").replaceInStrings(".desktop","");
1016  }
1017  if(filename.isEmpty()){ return;}
1018 
1019  if(cFiles.indexOf(filename) != -1){
1020    int num = 1;
1021    while(cFiles.indexOf(filename+QString::number(num)) != -1){ num++; }
1022    filename.append( QString::number(num) );
1023  }
1024  //save the current UI settings to the module structure then save the file
1025  bool ok = FALSE;
1026  if( ui->radio_xdg_desktop->isChecked() ){
1027    currentModule->loadDesktop(filename+".desktop"); //get the new file ready
1028    currentModule->writeValue("desktopname",ui->line_xdg_name->text());
1029    currentModule->writeValue("desktopgenericname",ui->line_xdg_name->text().toLower());
1030    currentModule->writeValue("desktopexec",ui->line_xdg_exec->text());
1031    currentModule->writeValue("desktopicon",ui->list_xdg_icon->currentText());
1032    QString checked = "false";
1033    if(ui->check_xdg_terminal->isChecked()){ checked="true"; }
1034    currentModule->writeValue("desktopterminal",checked);
1035    checked = "false";
1036    if(ui->check_xdg_nodisplay->isChecked()){ checked="true"; }
1037    currentModule->writeValue("desktopnodisplay",checked);
1038    //Now save the file
1039    ok = currentModule->writeDesktop();
1040   
1041  }else if( ui->radio_xdg_menu->isChecked() ){
1042    currentModule->loadMenu(filename+".desktop"); //get the new file ready
1043    //Update the MIME associations
1044    checkMime();
1045    //Save the MENU values
1046    currentModule->writeValue("menuname",ui->line_xdg_name->text());
1047    currentModule->writeValue("menugenericname",ui->line_xdg_name->text().toLower());
1048    currentModule->writeValue("menuexec",ui->line_xdg_exec->text());
1049    currentModule->writeValue("menuicon",ui->list_xdg_icon->currentText());
1050    currentModule->writeValue("menucategories", ui->line_xdg_menu->text());
1051    QString checked = "false";
1052    if(ui->check_xdg_terminal->isChecked()){ checked="true"; }
1053    currentModule->writeValue("menuterminal",checked);
1054    checked = "false";
1055    if(ui->check_xdg_nodisplay->isChecked()){ checked="true"; }
1056    currentModule->writeValue("menunodisplay",checked);
1057    //Now save the file
1058    ok = currentModule->writeMenu();   
1059  }
1060  //Now inform the user if there was an error
1061  if(!ok){
1062    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") );
1063  }
1064  //Now refresh the GUI
1065  refreshGUI("xdg");
1066}
1067
1068void MainGUI::on_push_xdg_clearentry_clicked(){
1069  //Clear the UI
1070        //reset the item selected to nothing
1071        ui->list_xdg_files->setCurrentRow(-1);
1072        //De-activate the "save" button
1073        ui->push_xdg_savechanges->setEnabled(FALSE);
1074        //Now clear the
1075        slotXdgFileChanged();
1076}
1077
1078void MainGUI::checkMime(){
1079    //This function will check the UI for differences in the MIME patterns
1080      // and update/create the MIME file appropriately
1081      // The MENU mime type will also be appropriately set
1082       
1083    QString menumimetype = currentModule->readValue("menumimetype");
1084    QString menumimepat = ui->line_xdg_mimepatterns->text();
1085    QString cmimetype = currentModule->readValue("mimetype");
1086    QString cmimepat = currentModule->readValue("mimepatterns");
1087    if( menumimepat != cmimepat ){ //something different about the mime patterns
1088        //  ---- Change the MIME file as well ----
1089          //Delete MIME file
1090        if(menumimepat.isEmpty()){
1091          currentModule->removeMime();
1092          currentModule->writeValue("menumimetype",""); //set MENU value
1093               
1094          //Create new MIME file
1095        }else if( cmimetype.isEmpty() || (ui->line_xdg_exec->text() != currentModule->readValue("menuexec")) ){
1096          QString exec = ui->line_xdg_exec->text().simplified();
1097          menumimetype = "application/x-"+exec;
1098          QString newfile = exec+"-xdg.xml";
1099          currentModule->loadMime(newfile); //setup structure
1100          currentModule->writeValue("mimetype",menumimetype); //set mime type
1101          currentModule->writeValue("mimepatterns",menumimepat); //set mime patterns
1102          currentModule->writeMime(); //save the MIME file (using default mime info)
1103               
1104          currentModule->writeValue("menumimetype",menumimetype); //set MENU value
1105               
1106          //Overwrite existing MIME file
1107        }else{
1108          currentModule->writeValue("mimepatterns", menumimepat); //overwrite mime patterns
1109          currentModule->writeMime(); //overwrite the MIME file
1110               
1111          currentModule->writeValue("menumimetype",cmimetype); //set MENU value
1112        }
1113    }
1114}
1115
1116/*------------------------------------------------
1117   SCRIPTS EDITOR OPTIONS
1118  -------------------------------------------------
1119*/
1120void MainGUI::slotScriptChanged(int index){
1121  index=0; //just to remove the warning about unused variables
1122  refreshGUI("scripts");
1123}
1124
1125void MainGUI::on_push_scripts_create_clicked(){
1126  //Setup display items
1127  ui->push_scripts_create->setVisible(FALSE);
1128  ui->push_scripts_remove->setVisible(FALSE);
1129  ui->push_scripts_save->setVisible(TRUE);
1130  ui->text_scripts_edit->setVisible(TRUE);
1131  ui->text_scripts_edit->clear();
1132}
1133
1134void MainGUI::on_push_scripts_remove_clicked(){
1135  //Get the current file
1136  QString filename = ui->list_scripts_file->currentText();
1137  //Remove the file
1138  QDir dir(currentModule->path()+"/scripts");
1139  dir.remove(filename);
1140  //refresh the UI
1141  refreshGUI("scripts");
1142}
1143
1144void MainGUI::on_push_scripts_save_clicked(){
1145  //Get the current file text
1146  QStringList contents = ui->text_scripts_edit->toPlainText().split("\n");
1147  //get the current file
1148  QString filename = currentModule->path() + "/scripts/"+ui->list_scripts_file->currentText();
1149  //Save the file
1150  bool ok = ModBuild::createFile(filename,contents);
1151  //display a warning if error
1152  if(!ok){
1153    QMessageBox::warning(this,tr("Error Saving File"), tr("Could not save the script")+"\n"+tr("Please check the file permissions and try again") );
1154  }
1155  //Now refresh the UI
1156  refreshGUI("scripts");
1157}
1158/*------------------------------------------------
1159   EXTERNAL-LINKS EDITOR OPTIONS
1160  -------------------------------------------------
1161*/
1162void MainGUI::on_push_el_add_clicked(){
1163  //Read the user inputs
1164  QString file = ui->line_el_file->text();
1165  QString linkto = ui->line_el_linkto->text();
1166  QString opts = ui->line_el_filetype->text();
1167  //check for valid inputs
1168  if( file.isEmpty() || linkto.isEmpty() || opts.isEmpty() ){ return; }
1169  //Add the link
1170  currentModule->addExternalLink(file, linkto, opts.split(",") );
1171  //Save the file
1172  currentModule->writeExternalLinks();
1173  //Refresh the UI
1174  refreshGUI("external-links");
1175}
1176
1177void MainGUI::on_push_el_remove_clicked(){
1178  //Get the currently selected link
1179  QTreeWidgetItem *line = ui->tree_el_view->currentItem();
1180  if(line->columnCount() != 3){ return; }
1181  QString file = line->text(0);
1182  QString linkto = line->text(1);
1183  //Remove the link
1184  currentModule->removeExternalLink(file,linkto);
1185  //Save the file
1186  currentModule->writeExternalLinks();
1187  //Refresh the UI
1188  refreshGUI("external-links");
1189}
1190
1191void MainGUI::slotELSetFile(QAction* act){
1192  //get the selected file and set it in the UI
1193  ui->line_el_file->setText( act->text() );
1194  ui->line_el_linkto->setText( act->text() );
1195}
1196
1197void MainGUI::slotELSetType(QAction* act){
1198  //Get the current types
1199  QStringList types = ui->line_el_filetype->text().split(",", QString::SkipEmptyParts);
1200  //get the new type
1201  QString ntype  = act->text();
1202  //Now properly add the type as appropriate
1203  bool ok = FALSE;
1204  for(int i=0; i<types.length(); i++){
1205    //Check for special cases
1206    if( (types[i] == "keep") && (ntype=="replace") ){
1207      types[i] = ntype;
1208      ok = TRUE;
1209      break;
1210    }else if( (types[i] == "replace") && (ntype=="keep") ){
1211      types[i] = ntype;
1212      ok = TRUE;
1213      break;
1214    }else if( (types[i]=="binary") && (ntype=="linux") ){
1215      types[i] = ntype;
1216      ok = TRUE;
1217      break;
1218    }else if( (types[i]=="linux") && (ntype=="binary") ){
1219      types[i] = ntype;
1220      ok = TRUE;
1221      break;
1222    }else if( types[i] == ntype ){
1223      ok=TRUE;
1224      break;
1225    }
1226  }
1227  if(!ok){ types << ntype; } //append the type to the list
1228  //Add the new types to the UI
1229  ui->line_el_filetype->setText( types.join(",") );
1230}
1231/*------------------------------------------------
1232   FREENAS PLUGINS EDITOR OPTIONS
1233  -------------------------------------------------
1234*/
1235
1236
1237/*------------------------------------------------
1238   PBI BUILDER OPTIONS
1239  -------------------------------------------------
1240*/
1241void MainGUI::on_push_build_start_clicked(){
1242  //Check GUI to make sure settings are set before running
1243  bool gostatus = TRUE;
1244  QString outdir = settings->value("pbidir");
1245  if (outdir.isEmpty() ){gostatus=FALSE;}
1246  //QString sigfile = "";ui->linePBIDigSigFile->text(); //this one can be empty
1247  QString modDir = currentModule->path();
1248  if(modDir.isEmpty()){gostatus=FALSE;}
1249  if(!gostatus){
1250    QMessageBox::warning(this,tr("Error"),tr("Invalid PBI Settings"));
1251    return;
1252  }
1253 
1254  //Generate the PBI build command
1255  QString cmd;
1256  // -- PBI from ports
1257  if(radio_module_port->isChecked()){
1258    //Check that the ports tree is available
1259    if( !settings->check("isportsavailable") ){ 
1260      qDebug() << "Cannot build a PBI from ports without the FreeBSD ports tree available";
1261      return;
1262    }
1263    //Setup the pbi_makeport command from GUI settings
1264    cmd = settings->value("pbi_makeport");
1265    if(ui->check_build_32->isChecked()){ cmd += " -32"; }
1266    cmd += " -c " + modDir;
1267    if(settings->value("portsdir") != "/usr/ports"){ cmd += " -d " + settings->value("portsdir"); }
1268    cmd += " -o " + outdir;
1269    cmd += " --delbuild";
1270    if( settings->check("usetmpfs") ){ cmd += " --tmpfs"; }
1271    if( settings->check("usecache") ){ 
1272      cmd += " --pkgdir " + settings->value("cachedir");
1273      //Remove known "bad" packages (ones that routinely cause failures)
1274      QDir cDir( settings->value("cachedir") );
1275      QStringList filters = settings->list("skippkgs");
1276      QStringList badFiles = cDir.entryList(filters, QDir::Files | QDir:: NoDotAndDotDot);
1277      for(int i=0; i<badFiles.length(); i++){ cDir.remove(badFiles[i]); }
1278    }
1279    if( settings->check("usesignature") && QFile::exists(settings->value("sigfile")) ){ cmd += " --sign " + settings->value("sigfile"); }
1280   
1281  // -- PBI from local directory
1282  }else if(radio_module_local->isChecked() ){
1283        //get the base command
1284        cmd = settings->value("pbi_create");
1285        //Setup the ports options if non-standard port location
1286        if(settings->value("portsdir") != "/usr/ports"){ cmd += " -d " + settings->value("portsdir"); }
1287        //Setup the output directory
1288        cmd += " -o "+outdir;
1289        //Load the module
1290        cmd += " -c "+modDir;
1291        //Sign the PBI
1292        if( settings->check("usesignature") && QFile::exists(settings->value("sigfile")) ){ cmd += " --sign " + settings->value("sigfile"); }
1293        //Now setup the directory to package
1294        cmd += " "+ currentModule->readValue("packagedir");
1295  }
1296  //Display the command created in hte terminal
1297  qDebug() << "Build PBI command created:"<<cmd;
1298 
1299  //Receive User verification before beginning build process due to:
1300  //  -- long time required, internet connection required, root permissions required
1301  QMessageBox verify(this);
1302  verify.setText(tr("Are you sure you wish to start the PBI build?"));
1303  verify.setInformativeText(tr("This requires an active internet connection and root permissions. The time required to build a PBI varies depending upon system specifications and ports to be compiled."));
1304  verify.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1305  verify.setDefaultButton(QMessageBox::Yes);
1306  int ret = verify.exec();
1307  if(ret != QMessageBox::Yes){return;}
1308
1309  //Add the necessary glue to the command to run the pbi build
1310  cmd.prepend(settings->value("su_cmd")+" \"");
1311  cmd.append("\"");
1312  qDebug() << "Actual command used:" << cmd;
1313
1314  //Setup the displays
1315  ui->push_build_stop->setEnabled(TRUE);
1316  ui->push_build_save->setEnabled(FALSE);
1317  ui->check_build_32->setEnabled(FALSE);
1318  ui->push_build_start->setEnabled(FALSE); //disable the button so they do not start more than 1 build at a time
1319  ui->text_build_log->clear(); //clear the display in case this is not the first run
1320  ui->line_build_module->setText(currentModule->path());
1321  ui->line_build_outputdir->setText(settings->value("pbidir"));
1322  //Setup Process connections
1323  p = new QProcess(this);
1324  p->setProcessChannelMode(QProcess::MergedChannels);
1325  p->setProcessEnvironment( QProcessEnvironment::systemEnvironment() );
1326  connect(p,SIGNAL(readyReadStandardOutput()),this,SLOT(slotUpdatePBIBuild()) );
1327  connect(p,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotPBIbuildFinished(int,QProcess::ExitStatus)) );
1328  connect(p,SIGNAL(error(QProcess::ProcessError)),this,SLOT(slotBuildError(QProcess::ProcessError)) );
1329  //Setup the flag for the finishing checks
1330  PBI_BUILDING_NOW=outdir+":::"+currentModule->readValue("progname");
1331  //Start the Process
1332  qDebug() << "Starting the PBI build process...";
1333  ui->toolBox->setItemText(0,tr("PBI Builder (Working)"));
1334  p->start(cmd);
1335}
1336
1337void MainGUI::on_push_build_stop_clicked(){
1338  slotKillPBIBuild();
1339}
1340
1341void MainGUI::on_push_build_save_clicked(){
1342  //Have user select a filename/location to save the log
1343  QString filename = QFileDialog::getSaveFileName(this,tr("Save Log"),settings->value("progdir")+"/build.log",tr("Log Files")+" (*.log *.txt)");
1344  if(filename.isEmpty()){return;} //User cancelled the process
1345  //Open the file (as new)
1346  QFile *file = new QFile(filename);
1347  file->open(QIODevice::WriteOnly);
1348  //Save the log into the file
1349  file->write(ui->text_build_log->toPlainText().toUtf8());
1350  file->close();
1351}
1352
1353void MainGUI::slotUpdatePBIBuild(){
1354  QString tmp = p->readAllStandardOutput();
1355  if( tmp.startsWith("\n") ){tmp.remove(0,0);} //remove newline at the beginning (too much whitespace in log)
1356  if( tmp.endsWith("\n") ){tmp.chop(1);} //remove newline at the end (already accounted for by appending)
1357  if(!tmp.isEmpty()){ ui->text_build_log->append( tmp ); }
1358  //qDebug() << "Update output: " << tmp;
1359}
1360
1361void MainGUI::slotPBIbuildFinished(int exitCode,QProcess::ExitStatus exitStatus){
1362  //Check to see if the PBI process finished successfully
1363  qDebug() << "PBI build process Finished" << exitStatus << exitCode;
1364  //Check that the new PBI exists
1365  QDir outdir( PBI_BUILDING_NOW.section(":::",0,0) );
1366  QString pbiname= PBI_BUILDING_NOW.section(":::",1,1).toLower().remove(" ");
1367  QFileInfoList fL = outdir.entryInfoList( QStringList() << pbiname+"*.pbi" ,QDir::Files | QDir::NoSymLinks);
1368  bool success = FALSE;
1369  for(int i=0; i<fL.length(); i++){
1370          qint64 msdiff = QDateTime::currentMSecsSinceEpoch() - fL[i].created().toMSecsSinceEpoch();
1371          if(msdiff < 30000){ success = true; break; } //if less than a 30sec since creation of file - success
1372  }
1373 
1374  if(exitCode == 0 && success){
1375      QMessageBox::information(this,tr("PBI Build Success"),tr("The PBI finished building successfully"));
1376  }else if(exitCode == 0 && PBI_BUILD_TERMINATED){
1377      //The user killed the process - No Message
1378  }else{
1379    QMessageBox::warning(this,tr("PBI Build Failure"),tr("The PBI failed to build.")+"\n"+tr("Please check the build log to find the cause of the failure and adjust the module accordingly"));
1380  }
1381  ui->push_build_start->setEnabled(TRUE);
1382  ui->push_build_save->setEnabled(TRUE);
1383  ui->push_build_stop->setEnabled(FALSE);
1384  ui->check_build_32->setEnabled(TRUE);
1385  p->close();
1386  PBI_BUILDING_NOW.clear();
1387  PBI_BUILD_TERMINATED=FALSE;
1388  ui->toolBox->setItemText(0,tr("PBI Builder (Finished)"));
1389  delete p;
1390}
1391
1392void MainGUI::slotKillPBIBuild(){
1393  if( p->state()==QProcess::Running ){
1394    //qDebug() << "Process PID:" << p->pid();
1395    PBI_BUILD_TERMINATED=TRUE;   
1396    p->terminate();
1397    ui->text_build_log->append("---PBI Build Terminated---");
1398  }
1399}
1400
1401void MainGUI::slotBuildError(QProcess::ProcessError error){
1402  qDebug() << "QProcess PBI Build error#" << error;
1403}
Note: See TracBrowser for help on using the repository browser.