source: src-qt4/EasyPBI/mainGUI.cpp @ 0c42827

releng/10.0.1releng/10.0.2releng/10.0.3
Last change on this file since 0c42827 was 0c42827, checked in by Ken Moore <ken@…>, 7 months ago

Update EasyPBI to 2.3:
Changes Include:
Add ability to build from ports directly again.
Add legacy port-build options to the GUI.
Add item to show current package compile-time options.
Add ability to create a new module from either ports/packages.
Fix a bug in the default wrapper script for 10.x PBI's (container path is /usr/local/ now when running)

  • Property mode set to 100644
File size: 59.9 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        //Setup the pushbutton menu lists
25        QStringList tmp = ModuleUtils::validExternalLinkTypes();
26        for(int i=0; i<tmp.length(); i++){ menu_elOpts.addAction(tmp[i]); }
27        tmp = ModuleUtils::validRepoTypes();
28        for(int i=0; i<tmp.length(); i++){ menu_validRepoTypes.addAction(tmp[i]); }
29        //Setup Toolbar
30        ui->actionNew_Module->setIcon(Backend::icon("new"));
31        ui->actionLoad_Module->setIcon(Backend::icon("load"));
32        line_module = new QLineEdit(this);
33        line_module->setPlaceholderText(tr("No Module Loaded"));
34        line_module->setReadOnly(TRUE);
35        line_module->setFocusPolicy(Qt::NoFocus);
36        ui->toolBar->addWidget(line_module);
37        ui->toolBar->addSeparator();
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        ui->tool_repoCat->setIcon(Backend::icon("left"));
47          ui->tool_repoCat->setMenu(&menu_validRepoCats);
48          connect(&menu_validRepoCats, SIGNAL(triggered(QAction*)), this, SLOT(slotSetRepoCat(QAction*)) );
49        ui->tool_config_setmkopt->setIcon(Backend::icon("left"));
50          ui->tool_config_setmkopt->setMenu(&menu_portopts);
51          connect(&menu_portopts, SIGNAL(triggered(QAction*)), this, SLOT(slotSetPortOpt(QAction*)) );
52        // -- resources tab --
53        ui->push_resources_savewrapper->setIcon(Backend::icon("save"));
54        connect(ui->listw_resources, SIGNAL(itemSelectionChanged()), this, SLOT(slotResourceChanged()) );
55        connect(ui->push_resources_savewrapper, SIGNAL(clicked()), this, SLOT(slotResourceScriptSaved()) );
56        // -- XDG entries tab --
57        connect(ui->radio_xdg_desktop,SIGNAL(clicked()),this,SLOT(slotXdgTypeChanged()) );
58        connect(ui->radio_xdg_menu,SIGNAL(clicked()),this,SLOT(slotXdgTypeChanged()) );
59        connect(ui->list_xdg_files,SIGNAL(itemSelectionChanged()), this, SLOT(slotXdgFileChanged()) );
60        ui->push_xdg_refresh->setIcon(Backend::icon("refresh"));
61        connect(ui->push_xdg_refresh, SIGNAL(clicked()), this, SLOT(slotXdgTypeChanged()) );
62        ui->push_xdg_exec->setIcon(Backend::icon("left"));
63        //ui->push_xdg_exec->setMenu(&menu_bins);
64        ui->push_xdg_exec->setEnabled(false);
65        //connect(&menu_bins, SIGNAL(triggered(QAction*)), this, SLOT(slotAddBin(QAction*)) );
66        ui->push_xdg_savechanges->setIcon(Backend::icon("save"));
67        ui->push_xdg_menu->setIcon(Backend::icon("left"));
68        ui->push_xdg_menu->setMenu(&menu_validMenuCats);
69        connect(&menu_validMenuCats,SIGNAL(triggered(QAction*)),this,SLOT(slotAddMenuCat(QAction*)) );
70        ui->push_xdg_clearentry->setIcon(Backend::icon("file"));
71       
72        // -- Scripts tab --
73        ui->push_scripts_save->setIcon(Backend::icon("save"));
74        ui->push_scripts_create->setIcon(Backend::icon("new"));
75        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" );
76        connect(ui->list_scripts_file, SIGNAL(currentIndexChanged(int)), this, SLOT(slotScriptChanged(int)) );
77        // -- External links tab --
78        ui->push_el_file->setIcon(Backend::icon("left"));
79        //ui->push_el_file->setMenu(&menu_el_bins);
80        ui->push_el_file->setEnabled(false);
81        //connect(&menu_el_bins,SIGNAL(triggered(QAction*)),this,SLOT(slotELSetFile(QAction*)) );
82        ui->push_el_filetype->setIcon(Backend::icon("left"));
83        ui->push_el_filetype->setMenu(&menu_elOpts);
84        connect(&menu_elOpts,SIGNAL(triggered(QAction*)),this,SLOT(slotELSetType(QAction*)) );
85        //Setup PBI Builder
86        ui->push_build_stop->setIcon(Backend::icon("close"));
87        ui->push_build_save->setIcon(Backend::icon("save"));
88       
89      SetupDefaults(); //load program defaults
90      refreshGUI("all"); //make items visible/invisible as necessary
91
92      //Change output palette (white on black)
93      QPalette palette = ui->text_build_log->palette();
94      palette.setColor(QPalette::Base, Qt::black);
95      palette.setColor(QPalette::Text, Qt::white);
96      ui->text_build_log->setPalette(palette);
97     
98      //Connect "option changed" signals to the respective slot
99      // PBI tab
100      connect(ui->line_progname,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
101      connect(ui->line_progauthor,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
102      connect(ui->line_progversion,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
103      connect(ui->line_progweb,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
104      connect(ui->line_config_license,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
105      connect(ui->line_makeport,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
106      connect(ui->list_progicon,SIGNAL(currentIndexChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
107      connect(ui->line_repoTags,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
108      connect(ui->line_repoType,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
109      connect(ui->line_repoCat,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
110      connect(ui->line_repoIconURL,SIGNAL(textChanged(QString)),this,SLOT(slotOptionChanged(QString)) );
111      connect(ui->spin_repoBuildKey,SIGNAL(valueChanged(QString)),this,SLOT(slotOptionChanged()) );
112      connect(ui->spin_repoPriority,SIGNAL(valueChanged(QString)),this,SLOT(slotOptionChanged()) );
113      connect(ui->spin_repoRevision,SIGNAL(valueChanged(QString)),this,SLOT(slotOptionChanged()) );
114      connect(ui->check_requiresroot, SIGNAL(clicked()),this,SLOT(slotOptionChanged()) );
115      connect(ui->check_config_nopkg, SIGNAL(clicked()),this,SLOT(slotOptionChanged()) );
116      connect(ui->check_config_notmpfs, SIGNAL(clicked()),this,SLOT(slotOptionChanged()) );
117      connect(ui->text_config_makeopts, SIGNAL(textChanged()), this, SLOT(slotOptionChanged()) );
118      connect(ui->group_config_overrides, SIGNAL(clicked()), this, SLOT(updateConfigVisibility()) );
119      connect(ui->group_config_repo, SIGNAL(clicked()), this, SLOT(updateConfigVisibility()) );
120      connect(ui->group_config_repomgmt, SIGNAL(clicked()), this, SLOT(updateConfigVisibility()) );
121      connect(ui->group_config_ports, SIGNAL(clicked()), this, SLOT(updateConfigVisibility()) );
122      // Resources tab
123      connect(ui->text_resources_script,SIGNAL(textChanged()),this,SLOT(slotResourceScriptChanged()) );
124      // XDG tab
125      connect(ui->line_xdg_name,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
126      connect(ui->line_xdg_mimepatterns,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
127      connect(ui->line_xdg_exec,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
128      connect(ui->line_xdg_menu,SIGNAL(textChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
129      connect(ui->check_xdg_nodisplay,SIGNAL(clicked()),this,SLOT(slotXDGOptionChanged()) );
130      connect(ui->check_xdg_requiresroot,SIGNAL(clicked()),this,SLOT(slotXDGOptionChanged()) );
131      connect(ui->check_xdg_terminal,SIGNAL(clicked()),this,SLOT(slotXDGOptionChanged()) );
132      connect(ui->list_xdg_icon,SIGNAL(currentIndexChanged(QString)),this,SLOT(slotXDGOptionChanged(QString)) );
133      // Scripts tab
134      connect(ui->text_scripts_edit,SIGNAL(textChanged()),this,SLOT(slotScriptModified()) );
135       
136}
137
138MainGUI::~MainGUI()
139{
140  qDebug() << "Shutting down EasyPBI normally";
141}
142
143void MainGUI::loadModule(QString confFile){
144  //Load a module that was specified on the CLI
145  if(confFile.isEmpty() || !QFile::exists(confFile) ){return;} //invalid file
146  bool ok = MODULE.loadModule(confFile);
147  if(ok){ 
148    qDebug() << "Loaded module:"<<confFile;
149    line_module->setText(MODULE.basepath().replace(QDir::homePath(),"~")); 
150    lastModuleDir = MODULE.basepath();
151  }
152  //Move to the pbi.conf tab
153  ui->tabWidget->setCurrentWidget(ui->tab_pbi_conf);
154  //Refresh the UI
155  refreshGUI("pbiconf");
156}
157
158void MainGUI::slotSingleInstance(){
159  this->showNormal();
160  this->activateWindow();
161  this->raise();
162}
163
164void MainGUI::SetupDefaults(){
165    qDebug() << "Starting up EasyPBI (version "+settings->value("version")+")"; 
166    //Make sure that the program is not being started with root permissions
167    QString id = QProcessEnvironment::systemEnvironment().toStringList().filter("HOME=").join(" ").simplified();
168    if( id.contains("root") ){
169      qDebug() << "EasyPBI should not be run with root permissions! exiting.....";
170      exit(1);
171    }
172
173    //Load the current configuration settings
174    settings->readMachineArch(); //set the 64-bit flag as appropriate
175    //Scan for the external utilities needed to build PBI's
176    settings->scanForExternalUtilities();
177    //Load Preferences file if possible
178    settings->loadSettingsFile();
179    //create the EasyPBI directory structure if needed
180    if( !settings->checkDirectoryStructure() ){
181        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.") );
182        exit(1);
183    }
184    //Pop up a warning box if some external resources are not available
185    bool chkOK = (settings->check("isMakeportAvailable") && settings->check("iscreateAvailable") && settings->check("isSUavailable") );
186    if( !chkOK ){
187        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.") );
188    }
189    //Set a couple more internal flags
190    PBI_BUILDING_NOW.clear();
191    PBI_BUILD_TERMINATED=FALSE;
192   
193    updateConfigVisibility(); //on first run, always need to do this manually
194}
195
196void MainGUI::updateConfigVisibility(){
197  //Update the group visibility for the pbi.conf tab
198  ui->frame_pkgFix->setVisible(ui->group_config_overrides->isChecked());
199  ui->frame_repoInfo->setVisible(ui->group_config_repo->isChecked());
200  ui->frame_repoMgmt->setVisible(ui->group_config_repomgmt->isChecked());
201  ui->frame_ports->setVisible(ui->group_config_ports->isChecked());
202}
203
204void MainGUI::refreshGUI(QString item){
205  //Enable/disable the interface appropriately
206 
207  //Stupid check to make sure that a module is actually loaded
208  if( MODULE.basepath().isEmpty() ){ 
209    ui->actionPackage_Module->setEnabled(FALSE);
210    ui->actionRefresh_Module->setEnabled(FALSE);
211    ui->tabWidget->setEnabled(false);
212    return;
213  }else{ 
214    ui->actionPackage_Module->setEnabled(TRUE); 
215    ui->actionRefresh_Module->setEnabled(TRUE);
216    ui->tabWidget->setEnabled(true);
217  }
218  //See if we should refresh everything (default) 
219  bool doall = ( (item == "all") || item.isEmpty() );
220  bool doeditor = (item == "editor"); //also add a flag to just refresh the editor
221  //Refresh the desired tab(s)
222  // ------PBI.CONF------
223  if( doall || doeditor || (item == "pbiconf")){
224    //Update options visibility
225    updateConfigVisibility();
226    //Now reset the options to the current module values
227    MODULE.loadConfig();
228    // -- check boxes
229    ui->check_requiresroot->setChecked( MODULE.isEnabled("PBI_REQUIRESROOT") );
230    ui->check_config_nopkg->setChecked( MODULE.isEnabled("PBI_AB_NOPKGBUILD") );
231    ui->check_config_notmpfs->setChecked( MODULE.isEnabled("PBI_AB_NOTMPFS") );
232    // -- Text Values
233    ui->line_progname->setText( MODULE.text("PBI_PROGNAME") );
234    ui->line_progversion->setText( MODULE.text("PBI_PROGVERSION") );
235    ui->line_progweb->setText( MODULE.text("PBI_PROGWEB") );
236    ui->line_progauthor->setText( MODULE.text("PBI_PROGAUTHOR") );
237    ui->line_makeport->setText( MODULE.text("PBI_MAKEPORT") );
238    ui->line_config_license->setText( MODULE.text("PBI_LICENSE") );
239    ui->line_repoTags->setText( MODULE.text("PBI_TAGS") );
240    ui->line_repoCat->setText( MODULE.text("PBI_CATEGORY") );
241    ui->line_repoIconURL->setText( MODULE.text("PBI_ICONURL") );
242    ui->line_repoType->setText( MODULE.text("PBI_PROGTYPE") );
243    // -- Combo Boxes (filled with individual items from text)
244    ui->list_portafter->clear();
245    ui->list_portafter->addItems( MODULE.text("PBI_MKPORTAFTER").split("\n") );
246    ui->list_config_mkportbefore->clear();
247    ui->list_config_mkportbefore->addItems(MODULE.text("PBI_MKPORTBEFORE").split("\n") );
248    // -- Integer Values
249    ui->spin_repoBuildKey->setValue( MODULE.number("PBI_BUILDKEY") );
250    ui->spin_repoPriority->setValue( MODULE.number("PBI_AB_PRIORITY") );
251    ui->spin_repoRevision->setValue( MODULE.number("PBI_PROGREVISION") );
252    // -- Text Boxes
253    ui->text_config_makeopts->clear();
254    ui->text_config_makeopts->setPlainText(MODULE.text("PBI_MAKEOPTS"));
255    // -- Combo Boxes (Select the proper item only)
256    QStringList icons = MODULE.existingResources().filter(".png");
257    ui->list_progicon->clear();
258    if(icons.length() > 0){
259      for(int i=0; i<icons.length(); i++){
260        ui->list_progicon->addItem(QIcon(MODULE.basepath()+"/resources/"+icons[i]),icons[i]);
261      }     
262      int cicon = icons.indexOf(MODULE.text("PBI_PROGICON"));
263      if( cicon == -1 ){ 
264              ui->list_progicon->addItem(MODULE.text("PBI_PROGICON")); 
265              cicon = icons.indexOf(MODULE.text("PBI_PROGICON"));
266      }
267      ui->list_progicon->setCurrentIndex(cicon);
268    }else{
269      ui->list_progicon->addItem( MODULE.text("PBI_PROGICON") );
270    }
271    //Update the available/recommended repo categories
272    menu_validRepoCats.clear();
273    QStringList tmp = ModuleUtils::validRepoCategories();
274    QString recCat = ModuleUtils::recommendedRepoCategory(MODULE.text("PBI_MAKEPORT").section("/",0,0,QString::SectionSkipEmpty) );
275    for(int i=0; i<tmp.length(); i++){
276      if(recCat == tmp[i]){ menu_validRepoCats.addAction(QIcon(Backend::icon("start")), tmp[i]); }
277      else{ menu_validRepoCats.addAction(tmp[i]); }
278    }
279    //Now update the available port build options;
280    menu_portopts.clear();
281    QStringList opts = Backend::getPortOpts(settings->value("portsdir")+"/"+MODULE.text("PBI_MAKEPORT"));
282    for(int i=0; i<opts.length(); i++){
283      QAction *act = new QAction(this);
284        if(opts[i].section(":::",1,1)=="off"){ act->setText( QString(tr("Enable %1")).arg(opts[i].section(":::",0,0)) ); }
285        else{ act->setText( QString(tr("Disable %1")).arg(opts[i].section(":::",0,0)) ); }
286        act->setToolTip(opts[i].section(":::",2,2));
287        act->setWhatsThis(opts[i].section(":::",0,1).replace(":::","="));
288      menu_portopts.addAction(act);
289    }
290    ui->tool_config_setmkopt->setEnabled(!menu_portopts.isEmpty());
291    //Now disable the save button
292    ui->push_config_save->setEnabled(FALSE);  //disable the save button until something changes
293    //Load the current package information and display it on the UI
294    QStringList pkgInfo = Backend::getPkgInfo(MODULE.text("PBI_MAKEPORT"));
295    qDebug() << "pkg info:" << pkgInfo;
296    if(pkgInfo.length() >= 4){
297      if(ui->line_progname->text().isEmpty()){ ui->line_progname->setText( pkgInfo[0] ); }
298      ui->line_progversion->setPlaceholderText(pkgInfo[1]);
299      ui->line_progweb->setPlaceholderText(pkgInfo[2]);
300      ui->line_config_license->setPlaceholderText(pkgInfo[3]);
301    }else{
302      ui->line_progversion->setPlaceholderText("");
303      ui->line_progweb->setPlaceholderText("");
304      ui->line_config_license->setPlaceholderText("");
305    }
306    pkgInfo = Backend::getPkgOpts(MODULE.text("PBI_MAKEPORT"));
307    qDebug() << "pkg opts:" << pkgInfo;
308    ui->combo_config_pkgopts->clear();
309    if(!pkgInfo.isEmpty()){ ui->combo_config_pkgopts->addItems(pkgInfo); }
310  }
311  // -----RESOURCES--------
312  if( doall || doeditor || (item == "resources")){
313    //Get the all the current files in the resources category and add them to the list
314    QStringList rs = MODULE.existingResources(); //currentModule->filesAvailable("resources");
315    //disconnect the signal/slot connection to make sure we don't get an extra phantom refresh
316    disconnect(ui->listw_resources, SIGNAL(itemSelectionChanged()), this, SLOT(slotResourceChanged()) );
317    //Update the Widget
318    ui->listw_resources->clear();
319    ui->listw_resources->addItems(rs);
320    //re-connect the signal/slot
321    connect(ui->listw_resources, SIGNAL(itemSelectionChanged()), this, SLOT(slotResourceChanged()) );
322    //Load the file into the viewers
323    slotResourceChanged();
324  }
325  //------XDG------
326  if( doall || doeditor || (item == "xdg")){
327    slotXdgTypeChanged();
328  }
329  //------SCRIPTS-----
330  if( doall || doeditor || (item == "scripts")  ){
331    //Update the list of available scripts
332    QStringList exist = MODULE.existingScripts();
333    QStringList valid = MODULE.validScripts();
334    QString current="junk";
335    if(ui->list_scripts_file->count() > 0){
336        current = ui->list_scripts_file->currentText(); //get the current item before clearing it
337    }
338    ui->list_scripts_file->clear();
339    ui->list_scripts_file->addItem("-- Installation Scripts --");
340    int index = 0;
341    for(int i=0; i<valid.length(); i++){
342      if(exist.contains(valid[i])){ 
343         exist.removeAll(valid[i]); 
344         ui->list_scripts_file->addItem(Backend::icon("file"), valid[i]);
345      }else{ ui->list_scripts_file->addItem(Backend::icon("close"), valid[i]); }
346      if(valid[i] == current){ index = i+1; }
347    }
348    //Now add the rest of the existing scripts (that are no longer valid)
349    for(int i=0; i<exist.length(); i++){
350      ui->list_scripts_file->addItem(Backend::icon("delete"), exist[i]);
351      if(exist[i] == current){ index = valid.length()+i+1; }
352    }
353    //Now reset to the appropriate item (will automatically load appropriately)
354    ui->list_scripts_file->setCurrentIndex(index);
355  }
356  //------EXTERNAL-LINKS------
357  if( doall || doeditor || (item == "external-links")){
358    //nothing to make visible/invisible here
359    //Load the external-links file
360    ui->tree_el_view->clear();
361    //QStringList cLinks = currentModule->externalLinks();
362    QStringList files, links, types;
363    MODULE.loadExternalLinks(files,links, types);
364    //QStringList labels; labels << tr("File") << tr("Link To") << tr("File Type");
365    for( int i=0; i<files.length(); i++ ){
366      QStringList link; link << files[i] << links[i] << types[i];
367      ui->tree_el_view->addTopLevelItem(new QTreeWidgetItem(link));
368    }
369    //Clear the input boxes
370    ui->line_el_file->clear();
371    ui->line_el_linkto->clear();
372    ui->line_el_filetype->clear();
373    //update the available binaries
374    /*menu_el_bins.clear();
375    QStringList cBins; //Not setup yet in the package framework
376    if(!cBins.isEmpty()){
377      for(int i=0; i<cBins.length(); i++){
378        menu_el_bins.addAction(cBins[i]);
379      }
380    }*/
381  }
382  //------FREENAS PLUGINS-------
383  if( doall || doeditor || (item == "freenas")){
384    //nothing to make visible/invisible here
385  }
386  //------PBI BUILDER--------
387  if( doall || (item == "pbibuild")){
388    if(PBI_BUILDING_NOW.isEmpty()){
389      //only change things if there is nothing building at the moment
390      ui->push_build_stop->setEnabled(false);
391      if(ui->text_build_log->toPlainText().isEmpty()){ ui->push_build_save->setEnabled(FALSE); }
392      else{ ui->push_build_save->setEnabled(TRUE); }
393    }else{
394      ui->push_build_stop->setEnabled(true);
395    }
396   
397    ui->push_build_start->setFocus();//make sure the focus starts out on the build button
398  }
399  //------OVERALL SETTINGS------
400  if( doall || doeditor ){
401    //Check for a 64-bit system to enable the 32-bit build option
402    //if( settings->check("is64bit") ){ ui->check_build_32->setVisible(TRUE); }
403    //else{ ui->check_build_32->setVisible(FALSE); ui->check_build_32->setChecked(FALSE); }
404   
405    //Set the default focus on the "load" button
406    this->setFocus();
407  }
408}
409
410QString MainGUI::getPortPackage(){
411  QString portSel;
412  if( settings->check("isportsavailable") && ui->check_config_nopkg->isChecked()){
413    //Prompt for a new port
414    portSel = QFileDialog::getExistingDirectory(this, tr("Select Port"), settings->value("portsdir")); 
415  }else{
416    //Prompt for a package
417    pkgSelect dlg(this);
418    dlg.exec();
419    if(dlg.selected){ portSel = dlg.portSelected; };
420  }
421  return portSel;
422}
423
424/*----------------------------------
425   MENU OPTIONS
426  -----------------------------------
427*/
428
429void MainGUI::on_actionExit_triggered(){
430  qDebug() << "Close EasyPBI requested";
431  this->close();
432}
433
434void MainGUI::on_actionPreferences_triggered(){
435  //Open up the preferences dialog
436  PreferencesDialog dlg(this);
437  //make the dialog modal and wait for it to close
438  dlg.exec(); 
439  //Re-check for system commands
440  settings->scanForExternalUtilities();
441  //Now reload the saved settings
442  settings->loadSettingsFile();
443  //Now refresh the GUI
444  refreshGUI("all");
445}
446
447void MainGUI::on_actionPackage_Module_triggered(){
448   ModuleUtils::compressModule(MODULE.basepath()); //currentModule->compressModule();
449   QMessageBox::information(this,tr("Success"),tr("A copy of the current module has been successfully packaged  within the module directory.") );
450
451}
452
453void MainGUI::on_actionRefresh_Module_triggered(){
454  QString modSel = MODULE.basepath(); //currentModule->path(); //re-load the current module
455  bool ok = MODULE.loadModule(modSel+"/pbi.conf"); 
456  if(ok){ 
457    qDebug() << "Loaded module:"<<modSel;         
458    line_module->setText(modSel.replace(QDir::homePath(),"~"));
459    refreshGUI("all");
460  }
461}
462
463void MainGUI::on_actionFreeBSD_Ports_triggered(){
464  QString port;
465  if(!line_module->text().isEmpty()){
466        //Get the currently selected port
467        port = MODULE.text("PBI_MAKEPORT");
468  }
469  QString target_url = "http://www.freshports.org/" + port;
470  qDebug() << "Opening URL:" << target_url; 
471  target_url.prepend("xdg-open ");
472  system(target_url.toUtf8()); 
473}
474
475void MainGUI::on_actionPBI_Modules_triggered(){
476  //Open the PC-BSD wiki to the module builders guide
477   QString target_url = "http://wiki.pcbsd.org/index.php/PBI_Module_Builder_Guide/10.0";
478   qDebug() << "Opening URL:" << target_url; 
479   target_url.prepend("xdg-open ");
480   system(target_url.toUtf8());
481}
482
483void MainGUI::on_actionAbout_EasyPBI_triggered(){
484  aboutDialog dlg(this,settings->value("version"));
485  dlg.exec();
486}
487
488
489/*----------------------------------
490   TOOLBAR OPTIONS
491  -----------------------------------
492*/
493void MainGUI::on_actionNew_Module_triggered(){
494  qDebug() << "New Module triggered";
495  //Create and run the new dialog
496  QString pDir = "";
497  if(settings->check("isportsavailable")){ pDir = settings->value("portsdir"); }
498  NewModuleDialog* dlg = new NewModuleDialog(this, pDir);
499  dlg->setDefaultIconFile(settings->value("defaulticon"));
500  dlg->exec();
501  //Determine if the action was cancelled
502  if( dlg->isAccepted ){
503    //Now create the new module
504    QString modPath, modBase, oldIconPath;
505    modBase = dlg->moduleData; //port cat/name
506    oldIconPath = dlg->moduleIcon; //PNG icon to use for the program
507    modPath = settings->value("moduledir"); //base directory to create modules in
508    MODULE = ModuleUtils::newModule(modPath, modBase, oldIconPath);
509    if(MODULE.basepath().isEmpty()){
510      QMessageBox::warning(this,tr("EasyPBI: Permissions Error"), tr("Could not create PBI module. Please check the directory permissions and try again."));
511    }else{
512      line_module->setText( MODULE.basepath().replace(QDir::homePath(), "~") );
513      if(dlg->isPort){
514        //A couple additional conveniances for port builds
515        MODULE.setEnabled("PBI_AB_NOPKGBUILD",true);
516        MODULE.saveConfig();
517        ui->group_config_ports->setChecked(true);
518      }
519    }
520  }
521  //Move to the pbi.conf tab
522  ui->tabWidget->setCurrentWidget(ui->tab_pbi_conf);
523  //Refresh the UI
524  refreshGUI("pbiconf");
525  delete dlg;
526}
527
528void MainGUI::on_actionLoad_Module_triggered(){
529  QString openDir = settings->value("moduledir");
530  if(!lastModuleDir.isEmpty()){ openDir = lastModuleDir; }
531  QString modSel = QFileDialog::getOpenFileName(this, tr("Select PBI Module Configuration"), openDir, tr("PBI Configuration (pbi.conf)") );
532  if(modSel.isEmpty()){return;} //action cancelled or closed
533  bool ok = MODULE.loadModule(modSel);
534  if(ok){ 
535    qDebug() << "Loaded module:"<<modSel;
536    line_module->setText(MODULE.basepath().replace(QDir::homePath(),"~")); 
537    lastModuleDir = MODULE.basepath();
538  }
539  //Move to the pbi.conf tab
540  ui->tabWidget->setCurrentWidget(ui->tab_pbi_conf);
541  //Refresh the UI
542  refreshGUI("pbiconf");
543}
544
545/*----------------------------------
546   MODULE EDITOR OPTIONS
547  -----------------------------------
548*/
549void MainGUI::slotModTabChanged(int newtab){
550  switch(newtab){
551    case 0:
552            refreshGUI("pbibuild"); break;
553    case 1:
554            refreshGUI("pbiconf"); break;
555    case 2:
556            refreshGUI("resources"); break;
557    case 3:
558            refreshGUI("xdg"); break;
559    case 4:
560            refreshGUI("scripts"); break;
561    case 5:
562            refreshGUI("external-links"); break;
563    case 6:
564            refreshGUI("freenas"); break;
565    default:
566            refreshGUI("editor"); break; //do all the module editor tabs
567  }       
568}
569
570/*----------------------------------
571   PBI.CONF OPTIONS
572  -----------------------------------
573*/
574void MainGUI::on_push_change_makeport_clicked(){
575  QString portSel = getPortPackage();     
576  if(portSel.isEmpty()){return;}       
577
578  //Save the port info to the GUI
579  ui->line_makeport->setText(portSel);
580  ui->push_config_save->setEnabled(TRUE);
581}
582
583void MainGUI::on_tool_addportafter_clicked(){
584  //Prompt for a new port
585  QString portSel = getPortPackage();
586  if(portSel.isEmpty()){return;} //action cancelled or closed   
587  //Save the port info to the GUI
588  if(ui->list_portafter->count() == 1 && ui->list_portafter->currentText().isEmpty() ){ ui->list_portafter->clear(); }
589  ui->list_portafter->addItem(portSel.remove(settings->value("portsdir")+"/"));
590  ui->push_config_save->setEnabled(TRUE);
591}
592
593void MainGUI::on_tool_rmportafter_clicked(){
594  int index = ui->list_portafter->currentIndex();
595  if(index != -1){
596    ui->list_portafter->removeItem(index);
597  }
598  ui->push_config_save->setEnabled(TRUE);
599}
600
601void MainGUI::on_tool_config_addportbefore_clicked(){
602  QString portSel = getPortPackage();
603  if(portSel.isEmpty()){return;} //action cancelled or closed   
604  //Save the port info to the GUI
605  if(ui->list_config_mkportbefore->count() == 1 && ui->list_config_mkportbefore->currentText().isEmpty() ){ ui->list_config_mkportbefore->clear(); }
606  ui->list_config_mkportbefore->addItem(portSel.remove(settings->value("portsdir")+"/"));
607  ui->push_config_save->setEnabled(TRUE);
608}
609
610void MainGUI::on_tool_config_rmportbefore_clicked(){
611  int index = ui->list_config_mkportbefore->currentIndex();
612  if(index != -1){
613    ui->list_config_mkportbefore->removeItem(index);
614  }
615  ui->push_config_save->setEnabled(TRUE);
616}
617
618void MainGUI::on_push_config_save_clicked(){
619  //Save the current settings to the backend structures
620  //Text Values
621  MODULE.setText("PBI_MAKEPORT", ui->line_makeport->text());
622  MODULE.setText("PBI_PROGNAME", ui->line_progname->text());
623  MODULE.setText("PBI_PROGVERSION", ui->line_progversion->text());
624  MODULE.setText("PBI_PROGWEB", ui->line_progweb->text());
625  MODULE.setText("PBI_PROGAUTHOR", ui->line_progauthor->text());
626  MODULE.setText("PBI_LICENSE", ui->line_config_license->text());
627  MODULE.setText("PBI_TAGS", ui->line_repoTags->text());
628  MODULE.setText("PBI_CATEGORY", ui->line_repoCat->text());
629  MODULE.setText("PBI_ICONURL", ui->line_repoIconURL->text());
630  MODULE.setText("PBI_PROGTYPE", ui->line_repoType->text());
631  //True/False values
632  MODULE.setEnabled("PBI_REQUIRESROOT", ui->check_requiresroot->isChecked());
633  MODULE.setEnabled("PBI_AB_NOPKGBUILD", ui->check_config_nopkg->isChecked());
634  MODULE.setEnabled("PBI_AB_NOTMPFS", ui->check_config_notmpfs->isChecked());
635  //Combo Boxes
636  QStringList addports;
637  for(int i=0; i<ui->list_portafter->count(); i++){ addports << ui->list_portafter->itemText(i); }
638  MODULE.setText("PBI_MKPORTAFTER", addports.join("\n") );
639  addports.clear();
640  for(int i=0; i<ui->list_config_mkportbefore->count(); i++){ addports << ui->list_config_mkportbefore->itemText(i); }
641  MODULE.setText("PBI_MKPORTBEFORE", addports.join("\n") );
642  MODULE.setText("PBI_PROGICON", ui->list_progicon->currentText() );
643  //Number values
644  MODULE.setNumber("PBI_BUILDKEY", ui->spin_repoBuildKey->value() );
645  MODULE.setNumber("PBI_AB_PRIORITY", ui->spin_repoPriority->value() );
646  MODULE.setNumber("PBI_PROGREVISION", ui->spin_repoRevision->value() );
647  //Text Values
648  MODULE.setText("PBI_MAKEOPTS", ui->text_config_makeopts->toPlainText());
649 
650  //save the new settings to pbi.conf
651  bool ok = MODULE.saveConfig();
652  if(!ok){
653    //Display a warning that the file could not be saved
654    QMessageBox::warning(this,tr("EasyPBI Error"), tr("The PBI configuration file could not be saved. Please check your file permissions before trying again."));
655    //re-load the current PBI.conf into the backend
656    MODULE.loadConfig();
657  }else{
658    ui->push_config_save->setEnabled(false); //make sure the save button goes inactive once saved
659  }
660}
661
662void MainGUI::slotOptionChanged(QString tmp){
663  tmp.clear(); //just to remove compiler warning about unused variable
664  ui->push_config_save->setEnabled(TRUE);       
665}
666
667void MainGUI::slotSetRepoType(QAction* act){
668  ui->line_repoType->setText(act->text());
669}
670
671void MainGUI::slotSetRepoCat(QAction* act){
672  ui->line_repoCat->setText(act->text());
673}
674
675void MainGUI::slotSetPortOpt(QAction* act){
676  QString opt = act->whatsThis();
677  QStringList cOpts = ui->text_config_makeopts->toPlainText().split("\n");
678  QString header;
679  if(opt.endsWith("=off")){
680    //This needs to be enabled
681    header = MODULE.text("PBI_MAKEPORT").section("/",-1) + "_SET=";
682  }else{
683    //This needs to be disabled
684    header = MODULE.text("PBI_MAKEPORT").section("/",-1) + "_UNSET=";
685  }
686  bool added = false;
687  for(int i=0; i<cOpts.length(); i++){
688    if(cOpts[i].startsWith(header)){ 
689      if( !cOpts[i].contains(opt.section("=",0,0)) ){
690        //Not already set, so set it
691        cOpts[i].append(" "+opt.section("=",0,0)); 
692      }
693      added=true; 
694      break;
695    }
696  }
697  if(!added){ cOpts << header+opt.section("=",0,0); }
698  ui->text_config_makeopts->clear();
699  cOpts.removeAll(""); //Remove empty lines
700  ui->text_config_makeopts->setPlainText( cOpts.join("\n") );
701}
702/*------------------------------------------------
703   RESOURCE EDITOR OPTIONS
704  -------------------------------------------------
705*/
706void MainGUI::slotResourceChanged(){
707  //Get the current file selected
708  QString cfile;
709  if(ui->listw_resources->currentRow() != -1){ cfile = ui->listw_resources->currentItem()->text(); }
710  if(cfile.isEmpty()){ //no item selected
711    ui->push_resources_savewrapper->setVisible(FALSE);
712    ui->text_resources_script->setVisible(FALSE);
713    ui->label_resources_description->setVisible(FALSE);
714    ui->label_resources_icon->setVisible(FALSE);
715         
716  }else{ //item selected
717    QString path = MODULE.basepath() + "/resources/";
718    if( cfile.endsWith(".png") || cfile.endsWith(".jpg") ){
719      //Image file, show full size
720      QPixmap img(path+cfile);
721      ui->label_resources_icon->setPixmap(img);
722      ui->label_resources_icon->setVisible(TRUE);
723      QString desc = QString::number(img.width()) +" x "+QString::number(img.height())+" "+cfile.section(".",-1).toUpper();
724      ui->label_resources_description->setText(desc);
725      ui->label_resources_description->setVisible(TRUE);
726      //hide the other widgets
727      ui->push_resources_savewrapper->setVisible(FALSE);
728      ui->text_resources_script->setVisible(FALSE);
729    }else{
730      ui->push_resources_savewrapper->setVisible(TRUE);
731      QStringList contents = PBIModule::readFile(path+cfile);
732      ui->text_resources_script->clear();
733      ui->text_resources_script->setText(contents.join("\n"));
734      ui->text_resources_script->setVisible(TRUE);
735      //hide the other widgets
736      ui->label_resources_description->setVisible(FALSE);
737      ui->label_resources_icon->setVisible(FALSE);
738    }
739  }
740  ui->push_resources_savewrapper->setEnabled(FALSE);
741 
742}
743
744void MainGUI::on_push_resources_add_clicked(){
745  //Get the desired file
746  QStringList iFiles = QFileDialog::getOpenFileNames(this, tr("Select Resources"), settings->value("icondir") );
747  //Check that there were file selected
748  if(iFiles.isEmpty()){ return; }
749  //Now add these files to the module
750  for(int i=0; i<iFiles.length(); i++){
751    MODULE.addResource(iFiles[i]);
752  }
753  //Now update the GUI
754  refreshGUI("resources");
755}
756
757void MainGUI::on_push_resources_remove_clicked(){
758  //Get the currently selected resource
759  QString cfile;
760  if(ui->listw_resources->currentRow() != -1){ cfile = ui->listw_resources->currentItem()->text(); }
761  //Check that there is something selected 
762  if(cfile.isEmpty()){ return; }
763  //Remove the resource
764  if(MODULE.removeResource(cfile)){
765      qDebug() << "Removed Resource:" << cfile;
766  }else{
767      qDebug() << "Error: Could not remove resource:"<<cfile;
768  }
769  //Refresh the GUI
770  refreshGUI("resources");
771}
772
773void MainGUI::on_push_resources_mkwrapper_clicked(){
774  //Get the desired filename for the wrapper script
775  bool ok;
776  QString cFile = QInputDialog::getText(this, tr("New Wrapper Script"), tr("Filename")+":", QLineEdit::Normal, "",&ok);
777  //Check for a valid input
778  if(!ok || cFile.isEmpty()){ return; }
779  if(!cFile.endsWith(".sh")){ cFile.append(".sh"); }
780  //Now create the new file
781  MODULE.createFile(MODULE.basepath()+"/resources/bin/"+cFile, ModuleUtils::generateWrapperScriptTemplate());
782  //Refresh the GUI
783  refreshGUI("resources");
784}
785
786void MainGUI::slotResourceScriptSaved(){
787  //get the current file and path
788  QString cfile;
789  if(ui->listw_resources->currentRow() != -1){ cfile = ui->listw_resources->currentItem()->text(); }
790  if(cfile.isEmpty()){ return; } // do nothing if no file selected
791  //Read the current text for the resource
792  QStringList contents = ui->text_resources_script->toPlainText().split("\n");
793  //overwrite the resource with the new contents
794  MODULE.writeScript(cfile,contents);
795  ui->push_resources_savewrapper->setEnabled(FALSE);
796}
797
798void MainGUI::slotResourceScriptChanged(){
799  ui->push_resources_savewrapper->setEnabled(TRUE);     
800}
801/*------------------------------------------------
802   XDG EDITOR OPTIONS
803  -------------------------------------------------
804*/
805void MainGUI::slotXdgTypeChanged(){
806  XDGUPDATING=true;
807  //Update the file list appropriately 
808  if(ui->radio_xdg_desktop->isChecked()){
809    //update the files available
810    ui->list_xdg_files->clear();
811    ui->list_xdg_files->addItems(MODULE.listXdgDesktopFiles());
812    //Set the visibility
813        //Current file
814        ui->label_xdg_name->setVisible(TRUE); ui->line_xdg_name->setVisible(TRUE);
815        ui->label_xdg_exec->setVisible(TRUE); ui->line_xdg_exec->setVisible(TRUE); ui->push_xdg_exec->setVisible(TRUE);
816        ui->label_xdg_icon->setVisible(TRUE); ui->list_xdg_icon->setVisible(TRUE);
817        ui->label_xdg_menu->setVisible(FALSE); ui->line_xdg_menu->setVisible(FALSE); ui->push_xdg_menu->setVisible(FALSE);
818        ui->check_xdg_nodisplay->setVisible(TRUE);
819        ui->check_xdg_terminal->setVisible(TRUE);
820        ui->label_xdg_mimepatterns->setVisible(FALSE); ui->line_xdg_mimepatterns->setVisible(FALSE);
821       
822  }else if(ui->radio_xdg_menu->isChecked()){
823    //update the files available
824    ui->list_xdg_files->clear();
825    ui->list_xdg_files->addItems(MODULE.listXdgMenuFiles());     
826    //Set the visibility
827        //Current file
828        ui->label_xdg_name->setVisible(TRUE); ui->line_xdg_name->setVisible(TRUE);
829        ui->label_xdg_exec->setVisible(TRUE); ui->line_xdg_exec->setVisible(TRUE); ui->push_xdg_exec->setVisible(TRUE);
830        ui->label_xdg_icon->setVisible(TRUE); ui->list_xdg_icon->setVisible(TRUE);
831        ui->label_xdg_menu->setVisible(TRUE); ui->line_xdg_menu->setVisible(TRUE); ui->push_xdg_menu->setVisible(TRUE);
832        ui->check_xdg_nodisplay->setVisible(TRUE);
833        ui->check_xdg_terminal->setVisible(TRUE);
834        ui->label_xdg_mimepatterns->setVisible(TRUE); ui->line_xdg_mimepatterns->setVisible(TRUE);
835       
836  }
837  //Select the first file in the list if one is available
838  if( ui->list_xdg_files->count() > 0){ ui->list_xdg_files->setCurrentRow(0); }
839  //Update the program icon list for new entries
840  ui->list_xdg_icon->clear();
841  QStringList icons = MODULE.existingResources().filter(".png");
842  if(icons.length() > 0){
843      for(int i=0; i<icons.length(); i++){
844        ui->list_xdg_icon->addItem(QIcon(MODULE.basepath()+"/resources/"+icons[i]),icons[i]);
845      }     
846  }
847
848  //Update the buttons that only need a refresh when the type changes (such as menu's)
849  //Available binaries pushbuttons
850  /*menu_bins.clear();
851  QStringList cBins; //not re-implemented yet
852  if(!cBins.isEmpty()){
853    for(int i=0; i<cBins.length(); i++){
854      menu_bins.addAction(cBins[i]);
855    }
856  }*/
857  //Menu categories
858  QString recMenu = ModuleUtils::recommendedXdgCategory(MODULE.text("PBI_MAKEPORT").section("/",0,0) );
859  QStringList cats = ModuleUtils::validXdgCategories();
860  menu_validMenuCats.clear();
861  for(int i=0; i<cats.length(); i++){
862    if(recMenu==cats[i]){ //Add an icon showing the recommended menu category
863      menu_validMenuCats.addAction(Backend::icon("start"),cats[i]);     
864    }else{
865      menu_validMenuCats.addAction(cats[i]);
866    }
867  }
868  XDGUPDATING=false;
869  //Now update read the currently selected file
870  slotXdgFileChanged();
871}
872
873void MainGUI::slotXdgFileChanged(){     
874  if(XDGUPDATING){ return; }
875  bool clearUI =FALSE;
876  if(ui->list_xdg_files->currentRow() == -1){ clearUI=TRUE; }
877
878  //Reset the icon list
879  ui->list_xdg_icon->clear();
880  QStringList icons = MODULE.existingResources().filter(".png");
881  if(icons.length() > 0){
882      for(int i=0; i<icons.length(); i++){
883        ui->list_xdg_icon->addItem(QIcon(MODULE.basepath()+"/resources/"+icons[i]),icons[i]);
884      }     
885  }
886  //Get the selected file
887  QString file;
888  if( !clearUI ){ file = ui->list_xdg_files->currentItem()->text(); }
889  if( clearUI || file.isEmpty() ){
890    //Clear the UI lines
891    ui->line_xdg_name->clear();
892    ui->line_xdg_exec->clear();
893    ui->line_xdg_menu->clear();
894    ui->line_xdg_mimepatterns->clear();
895    ui->check_xdg_terminal->setChecked(FALSE);
896    ui->check_xdg_nodisplay->setChecked(FALSE);
897    ui->check_requiresroot->setChecked(FALSE);
898    ui->push_xdg_savechanges->setEnabled(FALSE);
899    ui->push_xdg_savenew->setEnabled(FALSE);
900    //Now return
901    return; 
902  }
903  //Now setup the UI as appropriate
904  if(ui->radio_xdg_desktop->isChecked()){
905    //Load the file
906    MODULE.loadXdgDesktop(file);
907       
908  }else if(ui->radio_xdg_menu->isChecked()){
909    //Load the file
910    MODULE.loadXdgMenu(file);
911   
912    //Load the XDG-MIME file associations
913    QString mime = MODULE.xdgText("MimeType");
914    QStringList mimeavailable = MODULE.listMimeFiles();
915    bool found = FALSE;
916    for( int i=0; i<mimeavailable.length(); i++){
917      MODULE.loadMimeFile(mimeavailable[i]);
918      if(MODULE.mimeText("type") == mime){
919        found = TRUE;
920        break;
921      }
922    }
923    //qDebug() << "mimetype detected:" << mime;
924    if(found){
925      ui->line_xdg_mimepatterns->setText( MODULE.mimeText("pattern") ); 
926    }else{
927      MODULE.clearMimeData(); //Make sure we don't have any mime file loaded
928      ui->line_xdg_mimepatterns->clear();
929    }
930   
931  }else{
932    MODULE.clearXdgData(); //do nothing, unknown radio button selected (or none)
933  }
934  //update the file info on the GUI
935  ui->line_xdg_name->setText( MODULE.xdgText("Name") );
936  ui->line_xdg_exec->setText( ModuleUtils::pruneXdgLine(MODULE.xdgText("Exec")) );
937  ui->line_xdg_menu->setText( MODULE.xdgText("Categories") );
938  //comboboxes
939  QString icon = ModuleUtils::pruneXdgLine(MODULE.xdgText("Icon"));
940  int cicon = icons.indexOf(icon);
941  if( cicon == -1 ){ 
942    ui->list_xdg_icon->addItem(icon); 
943    cicon = icons.indexOf(icon);
944  }
945  ui->list_xdg_icon->setCurrentIndex(cicon);
946
947  //Checkboxes
948  ui->check_xdg_terminal->setChecked( MODULE.xdgEnabled("Terminal") );
949  ui->check_xdg_nodisplay->setChecked( MODULE.xdgEnabled("NoDisplay") );
950  ui->check_xdg_requiresroot->setChecked( ModuleUtils::xdgExecUsesRoot(MODULE.xdgText("Exec")) );
951   
952   
953  ui->push_xdg_savechanges->setEnabled(FALSE);
954  ui->push_xdg_savenew->setEnabled(FALSE);
955}
956
957void MainGUI::slotAddMenuCat(QAction* act){
958  //get the selected menu category
959  QString newcat = act->text();
960  //Read the current categories
961  QStringList oldcats = ui->line_xdg_menu->text().split(";", QString::SkipEmptyParts);
962  for(int i=0; i<oldcats.length(); i++){
963    oldcats[i] = oldcats[i].simplified();
964    if(oldcats[i] == newcat){return;} //category already in the list, do nothing
965  }
966  //Add the item
967  oldcats << newcat;
968  //Now replace the line onto the GUI
969  ui->line_xdg_menu->setText(oldcats.join("; "));
970}
971
972void MainGUI::slotAddBin(QAction* act){
973  //replace the current executable with the new one
974  ui->line_xdg_exec->setText(act->text().section("/",-1) );     
975}
976
977void MainGUI::on_push_xdg_remove_clicked(){
978  //Figure out if a file is selected
979  QString desktopFile = ui->list_xdg_files->currentItem()->text();
980  if( desktopFile.isEmpty() ){ return; }
981  //Now remove the file
982  bool ok = FALSE;
983  if( ui->radio_xdg_desktop->isChecked() ){
984    ok = MODULE.removeXdgDesktop(desktopFile);
985  }else if( ui->radio_xdg_menu->isChecked() ){
986    //Check for a MIME type to remove as well
987    ui->line_xdg_mimepatterns->setText(""); //make sure we remove any MIME file
988    MODULE.loadXdgMenu(desktopFile); //load the file's mimetype
989    checkMime(); //perform the removal if appropriate
990    ok = MODULE.removeXdgMenu(desktopFile);
991  }
992  //Now inform the user if there was an error
993  if(!ok){
994    QMessageBox::warning(this, tr("EasyPBI Error"), tr("Could not remove the XDG entry.")+"\n"+tr("Check the file permissions and try again") );
995  }
996  //Now refresh the GUI
997  refreshGUI("xdg");
998 
999}
1000
1001void MainGUI::on_push_xdg_savechanges_clicked(){
1002  //save the current UI settings to the module structure then save the file
1003  bool ok = FALSE;
1004  QString desktopFile = ui->list_xdg_files->currentItem()->text();
1005  if(desktopFile.isEmpty()){ return; }
1006  //Make sure the backend is currently set for this file
1007  if( ui->radio_xdg_desktop->isChecked() ){ MODULE.loadXdgDesktop(desktopFile); }
1008  else if(ui->radio_xdg_menu->isChecked() ){ MODULE.loadXdgMenu(desktopFile); }
1009  //Save the values into the backend module structure
1010  MODULE.setXdgText("Value", "1.0");
1011  MODULE.setXdgText("Type", "Application");
1012  MODULE.setXdgText("Name", ui->line_xdg_name->text());
1013  MODULE.setXdgText("GenericName", ui->line_xdg_name->text().toLower());
1014  MODULE.setXdgText("Exec", ModuleUtils::generateXdgExec(ui->line_xdg_exec->text(), ui->check_xdg_requiresroot->isChecked()) );
1015  MODULE.setXdgText("Icon", ModuleUtils::generateXdgPath(ui->list_xdg_icon->currentText()) );
1016  MODULE.setXdgText("Path", ModuleUtils::generateXdgPath("") );
1017  MODULE.setXdgEnabled("Terminal",ui->check_xdg_terminal->isChecked());
1018  MODULE.setXdgEnabled("NoDisplay",ui->check_xdg_nodisplay->isChecked());
1019  MODULE.setXdgEnabled("StartupNotify", true);
1020  if( ui->radio_xdg_desktop->isChecked() ){
1021    //clear the menu entry values
1022    MODULE.setXdgText("Categories", "");
1023    MODULE.setXdgText("MimeType", "");
1024    //Now save the file
1025    ok = MODULE.saveXdgDesktop(desktopFile);
1026  }else if( ui->radio_xdg_menu->isChecked() ){
1027    //Setup the menu entry values
1028    MODULE.setXdgText("Categories", ui->line_xdg_menu->text());
1029    //Setup the mime type associations as appropriate
1030    checkMime();
1031    //Now save the file
1032    ok = MODULE.saveXdgMenu(desktopFile);   
1033  }
1034  //Now inform the user if there was an error
1035  if(!ok){
1036    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") );
1037  }
1038  //Now refresh the GUI
1039  slotXdgFileChanged(); //only update the proper half of the tab
1040}
1041
1042void MainGUI::on_push_xdg_savenew_clicked(){
1043  //Get the filename we want to save
1044  QString filename;
1045  //Now check that the filename does not already exist
1046  QStringList cFiles;
1047  if(ui->radio_xdg_desktop->isChecked() ){
1048    filename = ui->line_xdg_exec->text().section("/",-1);
1049    cFiles = MODULE.listXdgDesktopFiles().replaceInStrings(".desktop","");
1050  }else if(ui->radio_xdg_menu->isChecked() ){
1051    filename = ui->line_xdg_exec->text().section("/",-1);
1052    cFiles = MODULE.listXdgMenuFiles().replaceInStrings(".desktop","");
1053  }
1054  if(filename.isEmpty()){ return; }
1055 
1056  if(cFiles.indexOf(filename) != -1){
1057    int num = 1;
1058    while(cFiles.indexOf(filename+QString::number(num)) != -1){ num++; }
1059    filename.append( QString::number(num) );
1060  }
1061  //save the current UI settings to the module structure then save the file
1062  bool ok = FALSE;
1063  if(filename.isEmpty()){ return; }
1064  //Make sure the backend structure is currently empty
1065  MODULE.clearXdgData();
1066  //Save the values into the backend module structure
1067  MODULE.setXdgText("Value", "1.0");
1068  MODULE.setXdgText("Type", "Application");
1069  MODULE.setXdgText("Name", ui->line_xdg_name->text());
1070  MODULE.setXdgText("GenericName", ui->line_xdg_name->text().toLower());
1071  MODULE.setXdgText("Exec", ModuleUtils::generateXdgExec(ui->line_xdg_exec->text(), ui->check_xdg_requiresroot->isChecked()) );
1072  MODULE.setXdgText("Icon", ModuleUtils::generateXdgPath(ui->list_xdg_icon->currentText()) );
1073  MODULE.setXdgText("Path", ModuleUtils::generateXdgPath("") );
1074  MODULE.setXdgEnabled("Terminal",ui->check_xdg_terminal->isChecked());
1075  MODULE.setXdgEnabled("NoDisplay",ui->check_xdg_nodisplay->isChecked());
1076  MODULE.setXdgEnabled("StartupNotify", true);
1077  if( ui->radio_xdg_desktop->isChecked() ){
1078    //clear the menu entry values
1079    MODULE.setXdgText("Categories", "");
1080    MODULE.setXdgText("MimeType", "");
1081    //Now save the file
1082    ok = MODULE.saveXdgDesktop(filename);
1083  }else if( ui->radio_xdg_menu->isChecked() ){
1084    //Setup the menu entry values
1085    MODULE.setXdgText("Categories", ui->line_xdg_menu->text());
1086    //Setup the mime type associations as appropriate
1087    checkMime();
1088    //Now save the file
1089    ok = MODULE.saveXdgMenu(filename);   
1090  }
1091  //Now inform the user if there was an error
1092  if(!ok){
1093    QMessageBox::warning(this, tr("EasyPBI Error"), tr("Could not create the XDG entry.")+"\n"+tr("Check the file permissions and try again") );
1094  }
1095  //Now refresh the GUI
1096  refreshGUI("xdg");
1097}
1098
1099void MainGUI::on_push_xdg_clearentry_clicked(){
1100  //Clear the UI
1101        //reset the item selected to nothing
1102        ui->list_xdg_files->setCurrentRow(-1);
1103        //De-activate the "save" button
1104        ui->push_xdg_savechanges->setEnabled(FALSE);
1105        //Now clear the
1106        slotXdgFileChanged();
1107}
1108
1109void MainGUI::checkMime(){
1110    //This function will check the UI for differences in the MIME patterns
1111      // and update/create the MIME file appropriately
1112      // The MENU mime type will also be appropriately set
1113       
1114    //Get the current/desired values
1115    QString newPatterns = ui->line_xdg_mimepatterns->text().simplified();
1116    QString cmimetype = MODULE.xdgText("MimeType"); //in the desktop/menu file
1117       
1118    //Determine the action necessary
1119    int stat = 0; //do nothing by default
1120    if( newPatterns.isEmpty() && !cmimetype.isEmpty() ){ stat = 1; } //remove old mime file
1121    else if( !newPatterns.isEmpty() && !cmimetype.isEmpty() ){stat = 2; } //update mime file
1122    else if( !newPatterns.isEmpty() && cmimetype.isEmpty() ){stat = 3; } //new mime file
1123    qDebug() << "CheckMime:" << QString::number(stat);
1124    //Now perform the actions as appropriate
1125    MODULE.clearMimeData(); //Make sure this backend is currently empty   
1126    QString fileName;
1127    if(stat == 0){ return; } //no action needed
1128    else if(stat == 1 || stat == 2){ //need to find current MIME file
1129      QStringList MF = MODULE.listMimeFiles();
1130      for(int i=0; i<MF.length(); i++){
1131        MODULE.loadMimeFile(MF[i]);
1132        if(MODULE.mimeText("type") == cmimetype){
1133          if(stat == 1){ //remove old mime file
1134            MODULE.removeMimeFile(MF[i]);
1135            MODULE.clearMimeData();
1136            MODULE.setXdgText("MimeType","");
1137            return; //done now
1138          }else{ //stat ==2, update mime file
1139            //Check if there is anything that actually needs to be done
1140            if( MODULE.mimeText("pattern") == newPatterns ){ return; } //nothing to change
1141            fileName = MF[i]; //save this filename for later use
1142          }
1143          break; //stop here, the file was already found and loaded
1144        }
1145      }
1146    }else{
1147      QString bin = ui->line_xdg_exec->text().section(" ",0,0,QString::SectionSkipEmpty).simplified();
1148      if(bin.isEmpty()){ return; } //should never hit this - but just to make sure
1149      //Generate a new mimetype
1150      cmimetype = "application/x-"+bin;
1151      MODULE.setXdgText("MimeType", cmimetype);
1152      //Generate a new filename for this mime file
1153      fileName = bin+"-xdg.xml";
1154    }
1155    //Now need to save the current values into the file (new or old, depending on earlier)
1156    MODULE.setMimeText("type", cmimetype);
1157    MODULE.setMimeText("pattern", newPatterns);
1158    //don't worry about xmlns - it will be auto generated if not set when creating the file, otherwise will use the current setting
1159    MODULE.saveMimeFile(fileName);
1160}
1161
1162void MainGUI::slotXDGOptionChanged(QString tmp){
1163  tmp.clear(); //remove warning about unused variables
1164  ui->push_xdg_savechanges->setEnabled(TRUE);
1165  ui->push_xdg_savenew->setEnabled(TRUE);
1166}
1167
1168/*------------------------------------------------
1169   SCRIPTS EDITOR OPTIONS
1170  -------------------------------------------------
1171*/
1172void MainGUI::slotScriptChanged(int index){
1173  //Update the GUI appropriately
1174    QStringList exist = MODULE.existingScripts();
1175    if( exist.contains(ui->list_scripts_file->currentText()) ){
1176      //Read and display the script
1177      QStringList contents = MODULE.readScript(ui->list_scripts_file->currentText());
1178      ui->text_scripts_edit->setPlainText(contents.join("\n"));
1179      //Setup display items
1180      ui->push_scripts_create->setVisible(FALSE);
1181      ui->push_scripts_remove->setVisible(TRUE);
1182      ui->push_scripts_save->setVisible(TRUE);
1183      ui->text_scripts_edit->setVisible(TRUE);
1184    }else{
1185      //Setup display items
1186      ui->push_scripts_create->setVisible(TRUE);
1187      ui->push_scripts_remove->setVisible(FALSE);
1188      ui->push_scripts_save->setVisible(FALSE);
1189      ui->text_scripts_edit->setVisible(FALSE);
1190    }
1191    if(index == 0){ ui->push_scripts_create->setVisible(FALSE); }
1192    ui->push_scripts_save->setEnabled(FALSE); //disable the save button until something changes
1193}
1194
1195void MainGUI::on_push_scripts_create_clicked(){
1196  //Setup display items
1197  ui->push_scripts_create->setVisible(FALSE);
1198  ui->push_scripts_remove->setVisible(FALSE);
1199  ui->push_scripts_save->setVisible(TRUE);
1200  ui->text_scripts_edit->setVisible(TRUE);
1201  ui->text_scripts_edit->clear();
1202  ui->push_scripts_save->setEnabled(FALSE); //disable the save button until something changes
1203}
1204
1205void MainGUI::on_push_scripts_remove_clicked(){
1206  //Get the current file
1207  QString filename = ui->list_scripts_file->currentText();
1208  //Remove the file
1209  MODULE.removeScript(filename);
1210  //refresh the UI
1211  refreshGUI("scripts");
1212}
1213
1214void MainGUI::on_push_scripts_save_clicked(){
1215  //Get the current file text
1216  QStringList contents = ui->text_scripts_edit->toPlainText().split("\n");
1217  //get the current file
1218  QString filename = ui->list_scripts_file->currentText();
1219  //Save the file
1220  bool ok = MODULE.writeScript(filename,contents);
1221  //display a warning if error
1222  if(!ok){
1223    QMessageBox::warning(this,tr("Error Saving File"), tr("Could not save the script")+"\n"+tr("Please check the file permissions and try again") );
1224  }
1225  //Now refresh the UI
1226  refreshGUI("scripts");
1227}
1228
1229void MainGUI::slotScriptModified(){
1230  ui->push_scripts_save->setEnabled(TRUE);     
1231}
1232/*------------------------------------------------
1233   EXTERNAL-LINKS EDITOR OPTIONS
1234  -------------------------------------------------
1235*/
1236void MainGUI::on_push_el_add_clicked(){
1237  //Read the user inputs
1238  QString file = ui->line_el_file->text();
1239  QString linkto = ui->line_el_linkto->text();
1240  QString opts = ui->line_el_filetype->text();
1241  //check for valid inputs
1242  if( file.isEmpty() || linkto.isEmpty() || opts.isEmpty() ){ return; }
1243  QStringList bins, links, types;
1244  MODULE.loadExternalLinks(bins,links,types);
1245  //Check for an identical link to just update
1246  bool found = false;
1247  for(int i=0; i<bins.length(); i++){
1248    if(bins[i] == file && links[i]==linkto){
1249      types[i] = opts;
1250      found = true;
1251      break;
1252    }
1253  }
1254  if(!found){
1255    bins << file; links << linkto; types << opts;
1256  }
1257  MODULE.saveExternalLinks(bins,links,types);
1258  //Refresh the UI
1259  refreshGUI("external-links");
1260}
1261
1262void MainGUI::on_push_el_remove_clicked(){
1263  //Get the currently selected link
1264  QTreeWidgetItem *line = ui->tree_el_view->currentItem();
1265  if(line->columnCount() != 3){ return; }
1266  QString file = line->text(0);
1267  QString linkto = line->text(1);
1268  //check for valid inputs
1269  if( file.isEmpty() || linkto.isEmpty() ){ return; }
1270  QStringList bins, links, types;
1271  MODULE.loadExternalLinks(bins,links,types);
1272  //Check for an identical link to remove
1273  for(int i=0; i<bins.length(); i++){
1274    if(bins[i] == file && links[i]==linkto){
1275      bins.removeAt(i); links.removeAt(i); types.removeAt(i);
1276      break;
1277    }
1278  }
1279  MODULE.saveExternalLinks(bins,links,types);
1280  //Refresh the UI
1281  refreshGUI("external-links");
1282}
1283
1284void MainGUI::slotELSetFile(QAction* act){
1285  //get the selected file and set it in the UI
1286  ui->line_el_file->setText( act->text() );
1287  ui->line_el_linkto->setText( act->text() );
1288}
1289
1290void MainGUI::slotELSetType(QAction* act){
1291  //Get the current types
1292  QStringList types = ui->line_el_filetype->text().split(",", QString::SkipEmptyParts);
1293  //get the new type
1294  QString ntype  = act->text();
1295  //Now properly add the type as appropriate
1296  bool ok = FALSE;
1297  for(int i=0; i<types.length(); i++){
1298    //Check for special cases
1299    if( (types[i] == "keep") && (ntype=="replace") ){
1300      types[i] = ntype;
1301      ok = TRUE;
1302      break;
1303    }else if( (types[i] == "replace") && (ntype=="keep") ){
1304      types[i] = ntype;
1305      ok = TRUE;
1306      break;
1307    }else if( (types[i]=="binary") && (ntype=="linux") ){
1308      types[i] = ntype;
1309      ok = TRUE;
1310      break;
1311    }else if( (types[i]=="linux") && (ntype=="binary") ){
1312      types[i] = ntype;
1313      ok = TRUE;
1314      break;
1315    }else if( types[i] == ntype ){
1316      ok=TRUE;
1317      break;
1318    }
1319  }
1320  if(!ok){ types << ntype; } //append the type to the list
1321  //Add the new types to the UI
1322  ui->line_el_filetype->setText( types.join(",") );
1323}
1324
1325/*------------------------------------------------
1326   PBI BUILDER OPTIONS
1327  -------------------------------------------------
1328*/
1329void MainGUI::on_push_build_start_clicked(){
1330  //Check GUI to make sure settings are set before running
1331  bool gostatus = TRUE;
1332  QString outdir = settings->value("pbidir");
1333  if (outdir.isEmpty() ){gostatus=FALSE;}
1334  QString modDir = MODULE.basepath();
1335  if(modDir.isEmpty()){gostatus=FALSE;}
1336  if(!gostatus){
1337    QMessageBox::warning(this,tr("Error"),tr("Invalid PBI Settings"));
1338    return;
1339  }
1340 
1341  //Generate the PBI build command
1342  QString sigFile;
1343  if( settings->check("usesignature") && QFile::exists(settings->value("sigfile")) ){ sigFile = settings->value("sigfile"); }
1344  QString cmd = ModuleUtils::generatePbiBuildCmd(MODULE.basepath(), outdir, sigFile, !MODULE.isEnabled("PBI_AB_NOPKGBUILD") );
1345  //Display the command created in hte terminal
1346  qDebug() << "Build PBI command created:"<<cmd;
1347 
1348  //Receive User verification before beginning build process due to:
1349  //  -- long time required, internet connection required, root permissions required
1350  QMessageBox verify(this);
1351  verify.setText(tr("Are you sure you wish to start the PBI build?"));
1352  verify.setInformativeText(tr("This requires an active internet connection and administrator privileges."));
1353  verify.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1354  verify.setDefaultButton(QMessageBox::Yes);
1355  int ret = verify.exec();
1356  if(ret != QMessageBox::Yes){return;}
1357
1358  //Add the necessary glue to the command to run the pbi build
1359  cmd.prepend(settings->value("su_cmd")+" \"");
1360  cmd.append("\"");
1361  qDebug() << "Actual command used:" << cmd;
1362
1363  //Setup the displays
1364  ui->push_build_stop->setEnabled(TRUE);
1365  ui->push_build_save->setEnabled(FALSE);
1366  ui->push_build_start->setEnabled(FALSE); //disable the button so they do not start more than 1 build at a time
1367  ui->text_build_log->clear(); //clear the display in case this is not the first run
1368  ui->line_build_module->setText( MODULE.basepath().replace(QDir::homePath(), "~") );
1369  ui->line_build_outputdir->setText(settings->value("pbidir"));
1370  //Setup Process connections
1371  p = new QProcess(this);
1372  p->setProcessChannelMode(QProcess::MergedChannels);
1373  QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
1374  env.remove("LD_LIBRARY_PATH");
1375  p->setProcessEnvironment( env );
1376  p->setWorkingDirectory(QDir::homePath());
1377  connect(p,SIGNAL(readyReadStandardOutput()),this,SLOT(slotUpdatePBIBuild()) );
1378  connect(p,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotPBIbuildFinished(int,QProcess::ExitStatus)) );
1379  connect(p,SIGNAL(error(QProcess::ProcessError)),this,SLOT(slotBuildError(QProcess::ProcessError)) );
1380  //Setup the flag for the finishing checks
1381  PBI_BUILDING_NOW=outdir+":::"+MODULE.text("PBI_PROGNAME").remove(" ").toLower();
1382  //Start the Process
1383  qDebug() << "Starting the PBI build process...";
1384  ui->tabWidget->setTabText(0,tr("Build PBI (Running)"));
1385  p->start(cmd);
1386}
1387
1388void MainGUI::on_push_build_stop_clicked(){
1389  slotKillPBIBuild();
1390}
1391
1392void MainGUI::on_push_build_save_clicked(){
1393  //Have user select a filename/location to save the log
1394  QString filename = QFileDialog::getSaveFileName(this,tr("Save Log"),settings->value("progdir")+"/build.log",tr("Log Files")+" (*.log *.txt)");
1395  if(filename.isEmpty()){return;} //User cancelled the process
1396  //Open the file (as new)
1397  QFile *file = new QFile(filename);
1398  file->open(QIODevice::WriteOnly);
1399  //Save the log into the file
1400  file->write(ui->text_build_log->toPlainText().toUtf8());
1401  file->close();
1402}
1403
1404void MainGUI::slotUpdatePBIBuild(){
1405  QString tmp = p->readAllStandardOutput();
1406  if( tmp.startsWith("\n") ){tmp.remove(0,0);} //remove newline at the beginning (too much whitespace in log)
1407  if( tmp.endsWith("\n") ){tmp.chop(1);} //remove newline at the end (already accounted for by appending)
1408  //clear the display  if it is starting a new port compilation (prevent the log getting too large)
1409  if(tmp.toLower().startsWith("compiling port: ")){ ui->text_build_log->clear(); }
1410  if(!tmp.isEmpty()){ ui->text_build_log->append( tmp ); }
1411  //qDebug() << "Update output: " << tmp;
1412}
1413
1414void MainGUI::slotPBIbuildFinished(int exitCode,QProcess::ExitStatus exitStatus){
1415  //Make sure that the QProcess is actually finished
1416  if( p->state() !=  QProcess::NotRunning ){
1417    qDebug() << "QProcess finished signal, but the process is still running";
1418    return;
1419  }
1420       
1421  //Check to see if the PBI process finished successfully
1422  qDebug() << "PBI build process Finished" << exitStatus << exitCode;
1423  //Check that the new PBI exists
1424  QDir outdir( PBI_BUILDING_NOW.section(":::",0,0) );
1425  QString pbiname= PBI_BUILDING_NOW.section(":::",1,1).toLower().remove(" ");
1426  QFileInfoList fL = outdir.entryInfoList( QStringList() << pbiname+"*.pbi" ,QDir::Files | QDir::NoSymLinks);
1427  bool success = FALSE;
1428  for(int i=0; i<fL.length(); i++){
1429          qint64 msdiff = QDateTime::currentMSecsSinceEpoch() - fL[i].created().toMSecsSinceEpoch();
1430          if(msdiff < 30000){ success = true; break; } //if less than a 30sec since creation of file - success
1431  }
1432 
1433  if(exitCode == 0 && success){
1434      QMessageBox::information(this,tr("PBI Build Success"),tr("The PBI finished building successfully"));
1435  }else if(exitCode == 0 && PBI_BUILD_TERMINATED){
1436      //The user killed the process - No Message
1437  }else{
1438    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"));
1439  }
1440  ui->push_build_start->setEnabled(TRUE);
1441  ui->push_build_save->setEnabled(TRUE);
1442  ui->push_build_stop->setEnabled(FALSE);
1443  p->close();
1444  PBI_BUILDING_NOW.clear();
1445  PBI_BUILD_TERMINATED=FALSE;
1446  ui->tabWidget->setTabText(0,tr("Build PBI (Done)"));
1447  delete p;
1448}
1449
1450void MainGUI::slotKillPBIBuild(){
1451  if( p->state()==QProcess::Running ){
1452    //qDebug() << "Process PID:" << p->pid();
1453    PBI_BUILD_TERMINATED=TRUE;   
1454    p->terminate();
1455    ui->text_build_log->append("---PBI Build Terminated---");
1456  }
1457}
1458
1459void MainGUI::slotBuildError(QProcess::ProcessError error){
1460  qDebug() << "QProcess PBI Build error#" << error;
1461}
Note: See TracBrowser for help on using the repository browser.