source: src-qt4/pc-pkgmanager/mainWin.cpp @ 395de4d

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 395de4d was 395de4d, checked in by Ken Moore <ken@…>, 9 months ago

Fix compilation of pc-pkgmanager on 10.x

  • Property mode set to 100644
File size: 42.6 KB
Line 
1/****************************************************************************
2** ui.h extension file, included from the uic-generated form implementation.
3**
4** If you want to add, delete, or rename functions or slots, use
5** Qt Designer to update this file, preserving your code.
6**
7** You should not define a constructor or destructor in this file.
8** Instead, write your code in functions called init() and destroy().
9** These will automatically be called by the form's constructor and
10** destructor.
11*****************************************************************************/
12#include <fcntl.h>
13#include <QDateTime>
14#include <QDebug>
15#include <QDir>
16#include <QProcess>
17#include <QProgressDialog>
18#include <QSocketNotifier>
19#include <QString>
20#include <QTextStream>
21#include <pcbsd-utils.h>
22#include <pcbsd-ui.h>
23#include <QSettings>
24#include "mainWin.h"
25#include "../config.h"
26
27void mainWin::ProgramInit(QString ch)
28{
29  // Set any warden directories
30  lastError="";
31  wDir = ch;
32       
33  //Grab the username
34  //username = QString::fromLocal8Bit(getenv("LOGNAME"));
35  connect(pushUpdatePkgs, SIGNAL(clicked()), this, SLOT(slotUpdatePkgsClicked()));
36  connect(pushClose, SIGNAL(clicked()), this, SLOT(slotCloseClicked()));
37  connect(pushCloseAdv, SIGNAL(clicked()), this, SLOT(slotCloseAdvClicked()));
38  connect(buttonRescanPkgs, SIGNAL(clicked()), this, SLOT(slotRescanPkgsClicked()));
39  connect(pushPkgApply, SIGNAL( clicked() ), this, SLOT( slotApplyClicked() ) );
40  connect(action_Quit, SIGNAL( triggered(bool) ), this, SLOT( slotCloseClicked() ) );
41  connect(tool_search, SIGNAL( clicked() ), this, SLOT( slotSearchPackages() ) );
42  connect(line_search, SIGNAL( returnPressed()), this, SLOT( slotSearchPackages()) );
43       
44  // Setup the action group
45  viewGroup = new QActionGroup(this);
46  viewGroup->addAction(action_Basic);
47  viewGroup->addAction(action_Advanced);
48
49  treeMetaPkgs->setContextMenuPolicy(Qt::CustomContextMenu);
50  connect(treeMetaPkgs, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotMetaRightClick()) );
51
52  QSettings settings("PC-BSD", "PackageManager");
53  QString curMode = settings.value("view/mode").toString();
54  if ( curMode == "Advanced" )
55  {
56     stackedPkgView->setCurrentIndex(1);
57     action_Basic->setChecked(false);
58     action_Advanced->setChecked(true);
59  }
60
61  // If we are running on a chroot, only do advanced mode
62  if ( !wDir.isEmpty() )
63  {
64     stackedPkgView->setCurrentIndex(1);
65     action_Basic->setChecked(false);
66     action_Basic->setEnabled(false);
67     action_Advanced->setChecked(true);
68     action_Advanced->setEnabled(false);
69  } else {
70    // Connect our view modes only when not running via in a chroot
71    connect(action_Basic, SIGNAL( triggered(bool) ), this, SLOT( slotViewChanged() ) );
72    connect(action_Advanced, SIGNAL( triggered(bool) ), this, SLOT( slotViewChanged() ) );
73  }
74
75  initMetaWidget();
76}
77
78void mainWin::slotViewChanged()
79{
80  QString mode;
81  if ( action_Basic->isChecked() ) {
82    stackedPkgView->setCurrentIndex(0);
83    mode="Basic";
84  } else {
85    mode="Advanced";
86    stackedPkgView->setCurrentIndex(1);
87  }
88
89  // Save the mode as the default at next open
90  QSettings settings("PC-BSD", "PackageManager");
91  settings.setValue("view/mode", mode);
92
93  // Changed view, lets refresh
94  initMetaWidget();
95}
96
97void mainWin::slotRescanPkgsClicked()
98{
99  // Check for pkg updates
100  checkMPKGUpdates();
101}
102
103void mainWin::slotApplyClicked() {
104  // Running in basic mode
105  if ( stackedPkgView->currentIndex() == 0 )
106  {
107     saveMetaPkgs();   
108  } else {
109     // Running in advanced mode
110     applyNGChanges();
111  }
112
113}
114
115void mainWin::slotSearchPackages(){
116  QString pkgSearch = line_search->text();
117  if(pkgSearch.isEmpty()){ return; }
118  qDebug() << "Search for package:" <<pkgSearch;
119  //Get the pointer to the proper treewidget
120  QTreeWidget *TW = treeNGPkgs;
121  if( stackedPkgView->currentIndex() == 0 ){ TW = treeMetaPkgs; }
122  //Make sure the tree widget is not empty
123  if(TW->topLevelItemCount() < 2){ return; }
124  //Get the currently selected item
125  QTreeWidgetItem *CI = TW->currentItem();
126  bool found=false; bool atTop=false;
127  if(CI == 0){ atTop=true; }
128  //Now search the tree, starting at that item
129  found = performSearch(pkgSearch, TW, CI);
130  if(!found && !atTop){
131    //Ask whether to restart the search at the top
132    if(QMessageBox::Yes == QMessageBox::question(this,tr("No Search Results"),tr("Do you want to continue the search from the top?"),QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ){
133      //Restart the search from the top
134      found = performSearch(pkgSearch, TW, 0);
135    }
136  }
137  if(!found){
138    QMessageBox::information(this, tr("No Search Results"), tr("No packages could be found with that search term. Please adjust it and try again.") );
139  }
140  qDebug() << " - Search Finished";
141}
142
143bool mainWin::performSearch(QString pkgSearch, QTreeWidget *TW, QTreeWidgetItem *SI){
144  //Start Iterating over the tree
145  bool found=false;
146  bool started = false;
147  //if(SI==0){ started = true; }
148  for(int p=0; (p<TW->topLevelItemCount()) && !found; p++){
149    //Check the actual item itself
150    QTreeWidgetItem *CI = TW->topLevelItem(p);
151    if(started && CI->text(0).contains(pkgSearch, Qt::CaseInsensitive)){
152      TW->setCurrentItem(CI);
153      TW->scrollToItem(CI);
154      found=true;         
155    }else{   
156      found = searchChildren(pkgSearch, TW, CI, started, SI);
157    }
158  }
159  return found;
160}
161
162bool mainWin::searchChildren(QString srch, QTreeWidget *TW, QTreeWidgetItem *CI, bool &started, QTreeWidgetItem *SI){
163  //This is a recursive function for searching all the children of a particular item
164  // TW - TreeWidget pointer
165  // CI - Current TreeWidget Item (to search the children of)
166  // SI - Start Item (Try to start searching right after this item - optional)
167  // bool started - Start Item found and search has been started (optional input/output)
168       
169  //qDebug() << "Search Children of:" << CI->text(0) << srch << started;
170  //Check for the start position
171  int start = -1;
172  if(SI == 0 || SI == CI){
173    //No search item to start at
174    start = 0;
175    started = true;
176  }else if( !started){
177    QTreeWidgetItem *PI = SI;
178      while( (start == -1) && (PI!=0) ){
179        start = CI->indexOfChild(PI);
180        PI = PI->parent(); //look up one more layer to make sure it is not a child of one of these items
181      }
182  }else{ start = 0; } //start with the first child
183  //Now quit if the start item is not found here
184  if(start == -1){ started = false; return false; }
185 
186  //Now start searching
187  bool found = false;
188  for(int i=start; (i<CI->childCount()) && !found ; i++){
189    if(started){
190      //Check this item
191      if(CI->child(i)->text(0).contains(srch, Qt::CaseInsensitive)){
192        TW->setCurrentItem(CI->child(i));
193        TW->scrollToItem(CI->child(i));
194        found=true;
195        break;
196      }
197    }else if( SI == CI->child(i) ){
198      started = true; //but don't look at this item, continue on to the next one (or children)
199    }
200    if(found){ break; }
201    else if(CI->child(i)->childCount() > 0){
202      //recursively search this items children
203      found = searchChildren(srch, TW, CI->child(i), started, SI); 
204    }
205  }
206  return found;
207}
208
209void mainWin::checkMPKGUpdates() {
210
211  QString line, tmp, name, pkgname, pkgover, pkgnver;
212  QStringList up, listPkgs;
213  bool haveUpdates = false;
214  int totPkgs=0;
215  buttonRescanPkgs->setEnabled(false);
216  pushUpdatePkgs->setEnabled(false);
217  listViewUpdatesPkgs->clear();
218  groupUpdatesPkgs->setTitle(tr("Checking for updates"));
219
220  QProcess p;
221  if ( wDir.isEmpty() )
222     p.start(QString("pc-updatemanager"), QStringList() << "pkgcheck");
223  else
224     p.start(QString("chroot"), QStringList() << wDir << "pc-updatemanager" << "pkgcheck");
225  while(p.state() == QProcess::Starting || p.state() == QProcess::Running)
226     QCoreApplication::processEvents();
227
228  while (p.canReadLine()) {
229    line = p.readLine().simplified();
230    qDebug() << line;
231    if ( line.indexOf("Upgrading") == 0 ) {
232      tmp = line;
233      pkgname = tmp.section(" ", 1, 1);
234      pkgname.replace(":", "");
235      pkgover = tmp.section(" ", 2, 2);
236      pkgnver = tmp.section(" ", 4, 4);
237      QTreeWidgetItem *myItem = new QTreeWidgetItem(QStringList() << pkgname << pkgover << pkgnver);
238      listViewUpdatesPkgs->addTopLevelItem(myItem);
239      haveUpdates = true;
240      totPkgs++;
241    } // End of upgrading section
242    if ( line.indexOf("Reinstalling") == 0 ) {
243      tmp = line;
244      pkgname = tmp.section(" ", 1, 1);
245      pkgover = pkgname.section("-", -1);
246      pkgname.truncate(pkgname.lastIndexOf("-"));
247      pkgnver = tmp.section(" ", 2);
248      QTreeWidgetItem *myItem = new QTreeWidgetItem(QStringList() << pkgname << pkgover << pkgnver);
249      listViewUpdatesPkgs->addTopLevelItem(myItem);
250      haveUpdates = true;
251      totPkgs++;
252    }
253  }
254
255  buttonRescanPkgs->setEnabled(true);
256  pushUpdatePkgs->setEnabled(haveUpdates);
257  if ( totPkgs > 0 ) {
258    tabUpdates->setTabText(1, tr("Package Updates (%1)").arg(totPkgs));
259    groupUpdatesPkgs->setTitle(tr("Available updates"));
260  } else {
261    tabUpdates->setTabText(1, tr("Package Updates"));
262    groupUpdatesPkgs->setTitle(tr("No available updates"));
263  }
264 
265}
266
267void mainWin::slotSingleInstance() {
268   this->hide();
269   this->showNormal();
270   this->activateWindow();
271   this->raise();
272}
273
274void mainWin::slotCloseClicked() {
275   close();
276}
277
278void mainWin::slotUpdatePkgsClicked() {
279  dPackages = false;
280  uPackages = false;
281
282  // Init the pkg process
283  prepPkgProcess();
284
285  // Create our runlist of package commands
286  QStringList pCmds;
287
288  if ( wDir.isEmpty() )
289    pCmds << "pc-updatemanager" << "pkgupdate";
290  else
291    pCmds << "chroot" << wDir << "pc-updatemanager" << "pkgupdate";
292
293  // Setup our runList
294  pkgCmdList << pCmds;
295
296  // Start the updating now
297  startPkgProcess();
298
299  textStatus->setText(tr("Starting package updates..."));
300
301}
302
303QString mainWin::getConflictDetailText() {
304
305  QStringList ConList = ConflictList.split(" ");
306  QStringList tmpDeps;
307  QString retText;
308
309  for (int i = 0; i < ConList.size(); ++i) {
310    QProcess p;
311    tmpDeps.clear();
312
313    if ( wDir.isEmpty() )
314      p.start("pkg", QStringList() << "rquery" << "%rn-%rv" << ConList.at(i));
315    else
316      p.start("chroot", QStringList() << wDir << "pkg" "rquery" << "%rn-%rv" << ConList.at(i) );
317
318    if(p.waitForFinished()) {
319      while (p.canReadLine()) {
320        tmpDeps << p.readLine().simplified();
321      }
322    }
323    retText+= ConList.at(i) + " " + tr("required by:") + "\n" + tmpDeps.join(" ");
324  }
325
326  return retText;
327}
328
329void mainWin::prepPkgProcess() {
330  pkgCmdList.clear();
331  textDisplayOut->clear();
332  pkgHasFailed=false;
333}
334
335void mainWin::startPkgProcess() {
336
337  if ( pkgCmdList.isEmpty() )
338    return;
339  if ( pkgCmdList.at(0).at(0).isEmpty() )
340     return; 
341
342  // Get the command name
343  QString cmd;
344  cmd = pkgCmdList.at(0).at(0);
345
346  // Get any optional flags
347  QStringList flags;
348  for (int i = 0; i < pkgCmdList.at(0).size(); ++i) {
349     if ( i == 0 )
350       continue;
351     flags << pkgCmdList.at(0).at(i);
352  } 
353
354  qDebug() << cmd + " " + flags.join(" ");
355 
356  // Setup the first process
357  uProc = new QProcess();
358  QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
359  env.insert("PCFETCHGUI", "YES");
360  uProc->setProcessEnvironment(env);
361  uProc->setProcessChannelMode(QProcess::MergedChannels);
362
363  // Connect the slots
364  connect( uProc, SIGNAL(readyReadStandardOutput()), this, SLOT(slotReadPkgOutput()) );
365  connect( uProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotPkgDone()) );
366
367  uProc->start(cmd, flags);
368
369  stackedTop->setCurrentIndex(1);
370
371  progressUpdate->setRange(0, 0 );
372  progressUpdate->setValue(0);
373
374}
375
376void mainWin::slotReadPkgOutput() {
377   QString line, tmp, cur, tot, fname;
378   int curItem, totItem;
379   bool ok;
380
381   while (uProc->canReadLine()) {
382     line = uProc->readLine().simplified();
383     qDebug() << line;
384
385     // Empty line? We can skip it
386     if ( line.isEmpty() )
387        continue;
388
389     tmp = line;
390     tmp.truncate(50);
391
392     // Flags we can parse out and not show the user
393
394     // Check if we have crashed into a conflict and ask the user what to do
395     if ( line.indexOf("PKGCONFLICTS: ") == 0 ) {
396        tmp = line; 
397        tmp.replace("PKGCONFLICTS: ", "");
398        ConflictList = tmp;
399        continue;
400     }
401     if ( line.indexOf("PKGREPLY: ") == 0 ) {
402        QString ans;
403        tmp = line; 
404        tmp.replace("PKGREPLY: ", "");
405        QMessageBox msgBox;
406        msgBox.setText(tr("The following packages are causing conflicts with the selected changes and can be automatically removed. Continue?") + "\n" + ConflictList);
407        msgBox.setStandardButtons(QMessageBox::Yes|QMessageBox::No);
408        msgBox.setDetailedText(getConflictDetailText());
409        msgBox.setDefaultButton(QMessageBox::No);
410        if ( msgBox.exec() == QMessageBox::Yes) {
411          // We will try to fix conflicts
412          ans="yes";
413        } else {
414          // We will fail :(
415          QMessageBox::warning(this, tr("Package Conflicts"),
416          tr("You may need to manually fix the conflicts before trying again."),
417          QMessageBox::Ok,
418          QMessageBox::Ok);
419          ans="no";
420        }
421
422        QFile pkgTrig( tmp );
423        if ( pkgTrig.open( QIODevice::WriteOnly ) ) {
424           QTextStream streamTrig( &pkgTrig );
425           streamTrig << ans;
426           pkgTrig.close();
427        }
428        continue;
429     }
430
431     if ( line.indexOf("FETCH: ") == 0 ) { 
432        progressUpdate->setValue(progressUpdate->value() + 1); 
433        tmp = line; 
434        tmp = tmp.remove(0, tmp.lastIndexOf("/") + 1); 
435        progressUpdate->setRange(0, 0);
436        progressUpdate->setValue(0);
437        curFileText = tr("Downloading: %1").arg(tmp); 
438        textStatus->setText(tr("Downloading: %1").arg(tmp)); 
439        continue;
440     } 
441     if ( line.indexOf("FETCHDONE") == 0 )
442        continue;
443
444     if ( line.indexOf("SIZE: ") == 0 ) {
445          bool ok, ok2;
446          line.replace("SIZE: ", "");
447          line.replace("DOWNLOADED: ", "");
448          line.replace("SPEED: ", "");
449          line.section(" ", 0, 0).toInt(&ok);
450          line.section(" ", 1, 1).toInt(&ok2);
451   
452          if ( ok && ok2 ) {
453            QString unit;
454            int tot = line.section(" ", 0, 0).toInt(&ok);
455            int cur = line.section(" ", 1, 1).toInt(&ok2);
456            QString percent = QString::number( (float)(cur * 100)/tot );
457            QString speed = line.section(" ", 2, 3);
458
459            // Get the MB downloaded / total
460            if ( tot > 2048 ) {
461              unit="MB";
462              tot = tot / 1024;
463              cur = cur / 1024;
464            } else {
465              unit="KB";
466            }
467
468            QString ProgressString=QString("(%1" + unit + " of %2" + unit + " at %3)").arg(cur).arg(tot).arg(speed);
469            progressUpdate->setRange(0, tot);
470            progressUpdate->setValue(cur);
471            textStatus->setText(curFileText + " " + ProgressString); 
472         }
473         continue;
474     }
475
476
477     // Now show output on GUI
478     textDisplayOut->insertPlainText(line + "\n");
479     textDisplayOut->moveCursor(QTextCursor::End);
480
481
482     // Any other flags to look for?
483     /////////////////////////////////////////////////////
484     if ( line.indexOf("to be downloaded") != -1 ) {
485       textStatus->setText(tr("Downloading packages..."));
486       curUpdate = 0;
487       progressUpdate->setValue(0);
488       continue;
489     }
490     if ( line.indexOf("Checking integrity") == 0 ) {
491       textStatus->setText(line);
492       uPackages = true;
493       dPackages = false;
494       curUpdate = 0;
495       progressUpdate->setValue(0);
496       progressUpdate->setRange(0, 0);
497       progressUpdate->setValue(0);
498       continue;
499     }
500     
501     if ( uPackages ) {
502       if ( line.indexOf("[") == 0 ) {
503         tmp=line.section("]", 1, 1);
504         textStatus->setText(tmp);
505         tmp=line.section("/", 0, 0).replace("[", "");
506         tmp.toInt(&ok);
507         if (ok)  {
508           curItem=tmp.toInt(&ok);
509           tmp=line.section("/", 1, 1).section("]", 0, 0);
510           tmp.toInt(&ok);
511           if (ok)  {
512             totItem=tmp.toInt(&ok);
513             progressUpdate->setRange(0, totItem);
514             progressUpdate->setValue(curItem);
515           }
516
517         }
518       }
519       continue;
520     }
521
522   } // end of while
523}
524
525void mainWin::slotPkgDone() {
526
527  if ( uProc->exitCode() != 0 )
528    pkgHasFailed=true;
529
530  // Run the next command on the stack if necessary
531  if (  pkgCmdList.size() > 1 ) {
532        pkgCmdList.removeAt(0); 
533        startPkgProcess();     
534        return;
535  }
536
537  // Nothing left to run! Lets wrap up
538  QFile sysTrig( SYSTRIGGER );
539  if ( sysTrig.open( QIODevice::WriteOnly ) ) {
540    QTextStream streamTrig( &sysTrig );
541     streamTrig << "INSTALLFINISHED: ";
542  }
543
544  if ( pkgHasFailed ) {
545    QFile file( "/tmp/pkg-output.log" );
546    if ( file.open( QIODevice::WriteOnly ) ) {
547       QTextStream stream( &file );
548       stream << textDisplayOut->toPlainText();
549       file.close();
550    }
551    QMessageBox::warning(this, tr("Failed!"), tr("The package commands failed. A copy of the output was saved to /tmp/pkg-output.log"));
552  } else
553    QMessageBox::warning(this, tr("Finished!"), tr("Package changes complete!" ));
554
555  // Clear out the old commands
556  pkgCmdList.clear();
557
558  // Switch back to our main display
559  stackedTop->setCurrentIndex(0);
560 
561  // Re-init the meta-widget
562  initMetaWidget();
563
564}
565
566/*****************************************
567Code for package stuff
568******************************************/
569
570void mainWin::initMetaWidget()
571{
572  qDebug() << "Starting metaWidget...";
573  groupInfo->setVisible(false);
574  //Make sure the search box is disabled at startup
575  tool_search->setEnabled(false);
576
577  // Running in basic mode
578  if ( stackedPkgView->currentIndex() == 0 )
579  {
580    populateMetaPkgs();
581    // Connect our slots
582  } else {
583    // Running in advanced mode
584    populateNGPkgs();
585  }
586}
587
588void mainWin::populateNGPkgs()
589{
590  pushPkgApply->setEnabled(false);
591  treeNGPkgs->clear();
592  tmpPkgList.clear();
593  new QTreeWidgetItem(treeNGPkgs, QStringList() << tr("Loading... Please wait...") );
594
595  if ( ! pkgList.isEmpty() ) {
596        disconnect(treeNGPkgs, SIGNAL(itemChanged(QTreeWidgetItem *, int)), 0, 0);
597        disconnect(treeNGPkgs, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), 0, 0);
598  }
599  pkgList.clear();
600  selPkgList.clear();
601
602  // Start the process to get meta-pkg info
603  getNGProc = new QProcess();
604  qDebug() << "Searching for pkgs...";
605  connect( getNGProc, SIGNAL(readyReadStandardOutput()), this, SLOT(slotGetNGPackageDataOutput()) );
606  connect( getNGProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotGetNGInstalledPkgs()) );
607  getNGProc->setProcessChannelMode(QProcess::MergedChannels);
608  if ( wDir.isEmpty() )
609    getNGProc->start(QString("pkg"), QStringList() << "rquery" << "-a" << "%o:::%n-%v:::%c:::%sh:::%m:::%w");
610  else
611    getNGProc->start(QString("chroot"), QStringList() << wDir << "pkg" << "rquery" << "-a" << "%o:::%n-%v:::%c:::%sh:::%m:::%w");
612
613}
614
615void mainWin::slotGetNGPackageDataOutput()
616{
617   while (getNGProc->canReadLine())
618     tmpPkgList << getNGProc->readLine().simplified();
619}
620
621void mainWin::slotGetNGInstalledDataOutput()
622{
623   while (getNGProc->canReadLine())
624     pkgList << getNGProc->readLine().simplified();
625}
626
627void mainWin::slotGetNGInstalledPkgs() {
628
629  qDebug() << "Building dependancy lists...";
630  QProcess p;
631  pkgDepList.clear();
632  if ( wDir.isEmpty() )
633    p.start("pkg", QStringList() << "rquery" << "-a" << "%n-%v:::%dn-%dv");
634  else
635    p.start("chroot", QStringList() << wDir << "pkg" << "rquery" << "-a" << "%n-%v:::%dn-%dv" );
636  while(p.state() == QProcess::Starting || p.state() == QProcess::Running) {
637      p.waitForFinished(200);
638      QCoreApplication::processEvents();
639  }
640  while (p.canReadLine()) {
641    pkgDepList << p.readLine().simplified();
642  }
643
644  getNGProc = new QProcess();
645  qDebug() << "Searching for installed pkgs...";
646  connect( getNGProc, SIGNAL(readyReadStandardOutput()), this, SLOT(slotGetNGInstalledDataOutput()) );
647  connect( getNGProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotFinishLoadingNGPkgs()) );
648  getNGProc->setProcessChannelMode(QProcess::MergedChannels);
649  if ( wDir.isEmpty() )
650    getNGProc->start(QString("pkg"), QStringList() << "info" << "-aq" );
651  else
652    getNGProc->start(QString("chroot"), QStringList() << wDir << "pkg" << "info" << "-aq");
653
654}
655
656void mainWin::slotFinishLoadingNGPkgs()
657{
658  treeNGPkgs->clear();
659
660  addNGItems();
661
662  pushPkgApply->setEnabled(false);
663
664  connect(treeNGPkgs, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotEnableApply()));
665  connect(treeNGPkgs, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(slotNGItemChanged()));
666  //Enable the search option
667  tool_search->setEnabled(true);
668  // Now we can look for updates safely
669  slotRescanPkgsClicked();
670}
671
672void mainWin::slotNGItemChanged()
673{
674  if ( ! treeNGPkgs->currentItem() ) {
675     groupInfo->setVisible(false);
676     return;
677  }
678  QString desc, size, maint, weburl;
679
680  QTreeWidgetItem *cItem = treeNGPkgs->currentItem();
681  QString pName = cItem->text(0).section("(", 1, 1).section(")", 0, 0);
682  if ( pName.isEmpty() ) {
683     groupInfo->setVisible(false);
684     return;
685  }
686  qDebug() << "Checking: " + pName;
687
688  QRegExp rx("*:::" + pName + ":::*");
689  rx.setPatternSyntax(QRegExp::Wildcard);
690  int pAt = tmpPkgList.indexOf(rx);
691  if (pAt == -1 ) {
692     qDebug() << "Unable to find package: " + pName;
693     groupInfo->setVisible(false);
694     return;
695  }
696
697  desc = tmpPkgList.at(pAt).section(":::", 2,2);
698  size = tmpPkgList.at(pAt).section(":::", 3,3);
699  maint = tmpPkgList.at(pAt).section(":::", 4,4);
700  weburl = tmpPkgList.at(pAt).section(":::", 5,5);
701  labelPkgNameVer->setText(pName);
702  labelSize->setText(size);
703  labelWeb->setText(weburl);
704  textDesc->setText(desc);
705  textOptions->clear();
706
707  QCoreApplication::processEvents();
708
709  // Display the depends
710  QString depTxt;
711  QRegExp rxd( pName + ":::*");
712  rxd.setPatternSyntax(QRegExp::Wildcard);
713  QStringList aDeps = pkgDepList.filter(rxd);
714  for ( int r=0; r < aDeps.size(); ++r) {
715      QString dName = aDeps.at(r).section(":::", 1, 1);
716      // Is this package installed?
717      if ( pkgList.indexOf(dName) != -1 )
718         depTxt+= dName + " (Installed)\n";
719      else
720         depTxt+= dName + "\n";
721  }
722
723  textDeps->setText(depTxt);
724
725  groupInfo->setVisible(true);
726
727  getNGInfo = new QProcess();
728  qDebug() << "Getting Info for " + pName;
729  connect( getNGInfo, SIGNAL(readyReadStandardOutput()), this, SLOT(slotNGReadInfo()) );
730  getNGInfo->setProcessChannelMode(QProcess::MergedChannels);
731  if ( wDir.isEmpty() )
732    getNGInfo->start(QString("pkg"), QStringList() << "rquery" << "%Ok=%Ov" << pName );
733  else
734    getNGInfo->start(QString("chroot"), QStringList() << wDir << "pkg" << "rquery" << "%Ok=%Ov" << pName);
735}
736
737void mainWin::slotNGReadInfo()
738{
739  while (getNGInfo->canReadLine())
740     textOptions->append(getNGInfo->readLine().simplified() );
741
742  textOptions->moveCursor(QTextCursor::Start);
743}
744
745void mainWin::slotEnableApply()
746{
747  pushPkgApply->setEnabled(true);
748}
749
750void mainWin::addNGItems()
751{
752   QString curCat, cat, name, pkgname, desc, size, maint, weburl;
753
754   // We like to add alphabetically
755   tmpPkgList.sort();
756
757   QTreeWidgetItem *catItem = new QTreeWidgetItem;
758
759   // Lets start adding packages to the tree widget
760   for (int i = 0; i < tmpPkgList.size(); ++i) {
761        name = cat = tmpPkgList.at(i).section(":::", 0,0);
762        cat=cat.section("/", 0, 0);
763        name=name.section("/", 1, 1);
764        pkgname = tmpPkgList.at(i).section(":::", 1,1);
765        desc = tmpPkgList.at(i).section(":::", 2,2);
766        size = tmpPkgList.at(i).section(":::", 3,3);
767        maint = tmpPkgList.at(i).section(":::", 4,4);
768        weburl = tmpPkgList.at(i).section(":::", 5,5);
769
770        // Check if we need to add a top-level category
771        if ( cat != curCat )
772        {
773           qDebug() << "Adding cat: " + cat;
774           catItem = new QTreeWidgetItem(QStringList() << cat);
775           treeNGPkgs->addTopLevelItem(catItem);
776           curCat = cat;
777        }
778 
779        // Now lets create the item and attach to the category
780        QTreeWidgetItem *pkgItem = new QTreeWidgetItem();
781        pkgItem->setText(0, name + " (" + pkgname + ") - " + size );
782        pkgItem->setToolTip(0, desc);
783
784        if ( pkgList.indexOf(pkgname) != -1 ) {
785          pkgItem->setCheckState(0, Qt::Checked);
786          selPkgList << pkgname;
787        } else
788          pkgItem->setCheckState(0, Qt::Unchecked);
789 
790        catItem->addChild(pkgItem);
791   }
792}
793
794// Lets prompt user, and do it!
795void mainWin::applyNGChanges()
796{
797   QString tmp;
798   QStringList curPkgChecked;
799   QStringList newPkgs;
800   QStringList rmPkgs;
801
802   QTreeWidgetItemIterator it(treeNGPkgs);
803   while (*it) {
804         if ((*it)->checkState(0) == Qt::Checked) {
805           tmp = (*it)->text(0).section("(", 1, 1).section(")", 0, 0);
806           curPkgChecked << tmp;
807           if (pkgList.indexOf(tmp) == -1 ) 
808              newPkgs << tmp;
809         }
810         ++it;
811   }
812
813   for ( int i=0; i < pkgList.size(); ++i)
814      // Has this package been unchecked?
815      if (curPkgChecked.indexOf(pkgList.at(i)) == -1 )  {
816         // Make sure this is a package in the repo
817         // This filters out any custom packages the user may have loaded which may not exist in our repo
818         QRegExp rx("*" + pkgList.at(i) + "*");
819         rx.setPatternSyntax(QRegExp::Wildcard);
820         if ( tmpPkgList.indexOf(rx) != -1 )
821           rmPkgs << pkgList.at(i);
822      }
823
824   if ( rmPkgs.isEmpty() && newPkgs.isEmpty() ) {
825      QMessageBox::warning(this, tr("No changes"),
826        tr("No changes to make!"),
827        QMessageBox::Ok,
828        QMessageBox::Ok);
829      return;
830   }
831
832   qDebug() << "Added packages" << newPkgs;
833   qDebug() << "Removed packages" << rmPkgs;
834   pkgRemoveList = rmPkgs;
835   pkgAddList = newPkgs;
836
837   QString confirmText;
838
839   // Lets start creating our confirmation text
840   if ( ! rmPkgs.isEmpty() ) {
841      confirmText+=tr("The following packages will be removed:") + "\n"; 
842      confirmText+= "------------------------------------------\n";
843      confirmText+=rmPkgs.join("\n"); 
844      confirmText+= "\n\n" + tr("The following packages that require the above packages will also removed:") + "\n"; 
845      confirmText+= "------------------------------------------\n";
846      for ( int i=0; i < rmPkgs.size(); ++i) {
847       
848         // Get rdeps for this pkg
849         qDebug() << "Building reverse dependancy lists...";
850         pkgRDepList.clear();
851         QProcess p;
852         if ( wDir.isEmpty() )
853           p.start("pkg", QStringList() << "rquery" << "%n-%v:::%rn-%rv" << rmPkgs.at(i));
854         else
855           p.start("chroot", QStringList() << wDir << "pkg" << "rquery" << "%n-%v:::%rn-%rv" << rmPkgs.at(i) );
856         while(p.state() == QProcess::Starting || p.state() == QProcess::Running) {
857           p.waitForFinished(200);
858           QCoreApplication::processEvents();
859         }
860         while (p.canReadLine()) {
861           pkgRDepList << p.readLine().simplified();
862         }
863
864         QRegExp rx(rmPkgs.at(i) + ":::*");
865         rx.setPatternSyntax(QRegExp::Wildcard);
866         QStringList rDeps = pkgRDepList.filter(rx);
867         for ( int r=0; r < rDeps.size(); ++r) {
868             QString pName = rDeps.at(r).section(":::", 1, 1); 
869             // Is this package installed?
870             if ( pkgList.indexOf(pName) != -1 )
871               confirmText+= pName + " ";
872         }
873      }
874   }
875
876   if ( ! newPkgs.isEmpty() ) {
877      if ( ! rmPkgs.isEmpty() )
878        confirmText+= "\n\n";
879      confirmText+=tr("The following packages will be installed:") + "\n"; 
880      confirmText+= "------------------------------------------\n";
881      confirmText+=newPkgs.join("\n"); 
882      confirmText+= "\n\n" + tr("The following dependances will also be installed:") + "\n"; 
883      confirmText+= "------------------------------------------\n";
884      for ( int i=0; i < newPkgs.size(); ++i) {
885         QRegExp rx(newPkgs.at(i) + ":::*");
886         rx.setPatternSyntax(QRegExp::Wildcard);
887         QStringList aDeps = pkgDepList.filter(rx);
888         for ( int r=0; r < aDeps.size(); ++r) {
889             QString pName = aDeps.at(r).section(":::", 1, 1); 
890             // Is this package installed?
891             if ( pkgList.indexOf(pName) == -1 )
892               confirmText+= pName + " ";
893         }
894      }
895   }
896
897   // Launch our AddPartitionDialog to add a new device
898   askUserConfirm = new dialogConfirm();
899   connect(askUserConfirm, SIGNAL(ok()),this, SLOT(slotStartNGChanges()) );
900   askUserConfirm->programInit(tr("Confirm package changes"));
901   askUserConfirm->setInfoText(QString(confirmText));
902   askUserConfirm->exec();
903
904}
905
906
907// Time to start doing our NG changes!
908void mainWin::slotStartNGChanges()
909{
910  // Init the pkg process
911  prepPkgProcess();
912
913  // Create our runlist of package commands
914  QStringList pCmds;
915 
916  if ( ! pkgRemoveList.isEmpty() ) {
917    if ( wDir.isEmpty() )
918      pCmds << "pkg" << "delete" << "-R" << "-y" << pkgRemoveList.join(" ");
919    else
920      pCmds << "chroot" << wDir << "pkg" << "delete" << "-R" << "-y" << pkgRemoveList.join(" ");
921    pkgCmdList << pCmds;
922  }
923         
924  pCmds.clear();
925
926  if ( ! pkgAddList.isEmpty() ) {
927    if ( wDir.isEmpty() )
928      pCmds << "pc-pkg" << "install" << "-y" << pkgAddList.join(" ");
929    else
930      pCmds << "chroot" << wDir << "pc-pkg" << "install" << "-y" << pkgAddList.join(" ");
931    pkgCmdList << pCmds;
932  }
933
934  // Lets kick it off now
935  startPkgProcess();
936}
937
938// Display found meta-pkg data
939void mainWin::populateMetaPkgs()
940{
941  pushPkgApply->setEnabled(false);
942  treeMetaPkgs->clear();
943  tmpMetaPkgList.clear();
944  new QTreeWidgetItem(treeMetaPkgs, QStringList() << tr("Loading... Please wait...") );
945
946  if ( ! metaPkgList.isEmpty() )
947        disconnect(treeMetaPkgs, SIGNAL(itemChanged(QTreeWidgetItem *, int)), 0, 0);
948  metaPkgList.clear();
949
950  // Start the process to get meta-pkg info
951  getMetaProc = new QProcess();
952  qDebug() << "Searching for meta-pkgs...";
953  connect( getMetaProc, SIGNAL(readyReadStandardOutput()), this, SLOT(slotGetPackageDataOutput()) );
954  connect( getMetaProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotFinishLoadingMetaPkgs()) );
955  getMetaProc->setProcessChannelMode(QProcess::MergedChannels);
956  getMetaProc->start(QString("pc-metapkgmanager"), QStringList() << "list");
957
958}
959
960// Display found meta-pkg data
961void mainWin::slotFinishLoadingMetaPkgs()
962{
963
964  // Populate the metaPkgList
965  parseTmpMetaList();
966
967  treeMetaPkgs->clear();
968
969  addTreeItems(QString()); 
970
971  pushPkgApply->setEnabled(false);
972
973  connect(treeMetaPkgs, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotDeskPkgsChanged(QTreeWidgetItem *, int)));
974  //Enable the search option
975  tool_search->setEnabled(true);
976  // Now we can look for updates safely
977  slotRescanPkgsClicked();
978}
979
980void mainWin::addTreeItems(QString parent)
981{
982  for (int z=0; z < metaPkgList.count(); ++z) {
983    if ( metaPkgList.at(z).at(3) != parent )
984      continue;
985
986    // Hide the "base-system" package, since we are installing it anyway
987    if (metaPkgList.at(z).at(0) == "base-system" )
988      return;
989
990    QTreeWidgetItem *deskItem = new QTreeWidgetItem(QStringList() << metaPkgList.at(z).at(0) );
991    deskItem->setIcon(0, QIcon(metaPkgList.at(z).at(2)));
992    deskItem->setToolTip(0, metaPkgList.at(z).at(1));
993    deskItem->setCheckState(0, Qt::Unchecked);
994
995    if ( metaPkgList.at(z).at(5) == "YES" )
996      deskItem->setCheckState(0, Qt::Checked);
997
998    if ( parent.isEmpty() ) {
999      treeMetaPkgs->addTopLevelItem(deskItem);
1000    } else {
1001      // Locate the parent to attach to
1002      QTreeWidgetItemIterator it(treeMetaPkgs);
1003      while (*it) {
1004        if ((*it)->text(0) == parent ) {
1005          (*it)->addChild(deskItem);
1006          if ( metaPkgList.at(z).at(5) == "YES" && (*it)->checkState(0) == Qt::Unchecked)
1007            (*it)->setCheckState(0, Qt::PartiallyChecked);
1008          if ( metaPkgList.at(z).at(5) == "NO" && (*it)->checkState(0) == Qt::Checked)
1009            (*it)->setCheckState(0, Qt::PartiallyChecked);
1010          break;
1011        }
1012        it++;
1013      }
1014    }
1015
1016    // Now look for any possible children
1017    addTreeItems(metaPkgList.at(z).at(0));   
1018  }
1019
1020}
1021
1022// Check if a meta-pkg is installed
1023bool mainWin::isMetaPkgInstalled(QString mPkg)
1024{
1025  QString tmp;
1026  QProcess pcmp;
1027  pcmp.start(QString("pc-metapkgmanager"), QStringList() << chrootArg1 << chrootArg2 << "status" << mPkg);
1028  while ( pcmp.state() != QProcess::NotRunning ) {
1029     pcmp.waitForFinished(50);
1030     QCoreApplication::processEvents();
1031  }
1032
1033  while (pcmp.canReadLine()) {
1034     tmp = pcmp.readLine().simplified();
1035     if ( tmp.indexOf("is installed") != -1 )
1036     return true;
1037  }
1038
1039  return false;
1040}
1041
1042// Function which checks for our GUI package schema data
1043void mainWin::slotGetPackageDataOutput()
1044{
1045  while (getMetaProc->canReadLine())
1046        tmpMetaPkgList << getMetaProc->readLine().simplified();
1047}
1048
1049// Parse the pc-metapkg saved output
1050void mainWin::parseTmpMetaList()
1051{
1052  QString tmp, mName, mDesc, mIcon, mParent, mDesktop, mInstalled, mPkgFileList;
1053  QStringList package;
1054
1055  for ( int i = 0 ; i < tmpMetaPkgList.size(); i++ )
1056  {
1057        QApplication::processEvents();
1058
1059        tmp = tmpMetaPkgList.at(i);
1060
1061        if ( tmp.indexOf("Meta Package: ") == 0) {
1062                mName = tmp.replace("Meta Package: ", "");
1063                continue;
1064        }
1065        if ( tmp.indexOf("Description: ") == 0) {
1066                mDesc = tmp.replace("Description: ", "");
1067                continue;
1068        }
1069        if ( tmp.indexOf("Icon: ") == 0) {
1070                mIcon = tmp.replace("Icon: ", "");
1071                mPkgFileList = mIcon;
1072                mPkgFileList.replace("pkg-icon.png", "pkg-list");
1073                continue;
1074        }
1075        if ( tmp.indexOf("Parent: ") == 0) {
1076                mParent = tmp.replace("Parent: ", "");
1077                continue;
1078        }
1079        if ( tmp.indexOf("Desktop: ") == 0) {
1080                mDesktop = tmp.replace("Desktop: ", "");
1081                continue;
1082        }
1083
1084        // This is an empty category
1085        if ( tmp.indexOf("Category Entry") == 0) {
1086                // Now add this category to the string list
1087                package.clear();
1088                qDebug() << "Found Package" << mName << mDesc << mIcon << mParent << mDesktop;
1089                mInstalled = "CATEGORY";
1090                package << mName << mDesc << mIcon << mParent << mDesktop << mInstalled;
1091                metaPkgList.append(package);
1092                mName=""; mDesc=""; mIcon=""; mParent=""; mDesktop=""; mInstalled=""; mPkgFileList="";
1093        }
1094
1095        // We have a Meta-Pkg
1096        if ( tmp.indexOf("Required Packages:") == 0) {
1097                // Now add this meta-pkg to the string list
1098                package.clear();
1099                qDebug() << "Found Package" << mName << mDesc << mIcon << mParent << mDesktop << mPkgFileList;
1100
1101                if ( isMetaPkgInstalled(mName) )
1102                        mInstalled = "YES";
1103                else
1104                        mInstalled = "NO";
1105
1106                package << mName << mDesc << mIcon << mParent << mDesktop << mInstalled << mPkgFileList;
1107                metaPkgList.append(package);
1108                mName=""; mDesc=""; mIcon=""; mParent=""; mDesktop=""; mInstalled=""; mPkgFileList="";
1109        }
1110
1111    }
1112
1113}
1114
1115void mainWin::saveMetaPkgs()
1116{
1117        if ( ! haveMetaPkgChanges() )
1118                return;
1119
1120        addPkgs = getAddPkgs();
1121        delPkgs = getDelPkgs(); 
1122
1123        startMetaChanges();
1124
1125}
1126
1127void mainWin::startMetaChanges()
1128{
1129
1130  // Init the pkg process
1131  prepPkgProcess();
1132  // Create our runlist of package commands
1133  QStringList pCmds;
1134
1135  if ( ! delPkgs.isEmpty() ) {
1136    if ( wDir.isEmpty() )
1137      pCmds << "pc-metapkgmanager" << "del" << delPkgs;
1138    else 
1139      pCmds << "chroot" << wDir << "pc-metapkgmanager" << "del" << delPkgs;
1140    pkgCmdList << pCmds;
1141  }
1142 
1143  pCmds.clear();
1144
1145  if ( ! addPkgs.isEmpty() ) {
1146    if ( wDir.isEmpty() )
1147      pCmds << "pc-metapkgmanager" << "add" << addPkgs;
1148    else 
1149      pCmds << "chroot" << wDir << "pc-metapkgmanager" << "add" << addPkgs;
1150    pkgCmdList << pCmds;
1151  }
1152
1153  // Lets kick it off now
1154  startPkgProcess();
1155}
1156
1157bool mainWin::haveAMetaDesktop()
1158{
1159        // If running in a chroot we can skip this check
1160        if ( ! chrootArg1.isEmpty() )
1161          return true;
1162       
1163        QTreeWidgetItemIterator it(treeMetaPkgs);
1164        while (*it) {
1165         if ( ((*it)->checkState(0) == Qt::Checked) || ((*it)->checkState(0) == Qt::PartiallyChecked) )
1166           for (int z=0; z < metaPkgList.count(); ++z)
1167             if ( (*it)->text(0) == metaPkgList.at(z).at(0) && metaPkgList.at(z).at(4) == "YES" )
1168                return true;
1169         ++it;
1170        }
1171
1172        QMessageBox::warning(this, tr("No Desktop"),
1173          tr("No desktops have been selected! Please choose at least one desktop before saving."),
1174          QMessageBox::Ok,
1175          QMessageBox::Ok);
1176
1177        return false;
1178}
1179
1180bool mainWin::haveMetaPkgChanges()
1181{
1182        QTreeWidgetItemIterator it(treeMetaPkgs);
1183        while (*it) {
1184          for (int z=0; z < metaPkgList.count(); ++z)
1185            // See if any packages status have changed
1186            if ( ( (*it)->text(0) == metaPkgList.at(z).at(0) && metaPkgList.at(z).at(5) == "YES" && (*it)->checkState(0) == Qt::Unchecked ) \
1187              || ( (*it)->text(0) == metaPkgList.at(z).at(0) && metaPkgList.at(z).at(5) == "YES" && (*it)->checkState(0) == Qt::PartiallyChecked ) \
1188              || ( (*it)->text(0) == metaPkgList.at(z).at(0) && metaPkgList.at(z).at(5) == "NO" && (*it)->checkState(0) == Qt::Checked ) )
1189                return true;
1190         ++it;
1191        }
1192
1193        return false;
1194}
1195
1196QString mainWin::getAddPkgs()
1197{
1198        QString tmp;
1199        QTreeWidgetItemIterator it(treeMetaPkgs);
1200        while (*it) {
1201          for (int z=0; z < metaPkgList.count(); ++z)
1202            // See if any packages status have changed
1203            if ( ( (*it)->text(0) == metaPkgList.at(z).at(0) && metaPkgList.at(z).at(5) == "NO" && (*it)->checkState(0) == Qt::Checked ) || \
1204                 ( (*it)->text(0) == metaPkgList.at(z).at(0) && metaPkgList.at(z).at(5) == "NO" && (*it)->checkState(0) == Qt::PartiallyChecked ) ){
1205                if ( tmp.isEmpty() ){
1206                        tmp = (*it)->text(0);
1207                }else{
1208                        tmp = tmp + "," + (*it)->text(0);
1209                }
1210            }
1211         ++it;
1212        }
1213
1214        return tmp;
1215}
1216
1217QString mainWin::getDelPkgs()
1218{
1219        QString tmp;
1220        QTreeWidgetItemIterator it(treeMetaPkgs);
1221        while (*it) {
1222          for (int z=0; z < metaPkgList.count(); ++z)
1223            // See if any packages status have changed
1224            if ( (*it)->text(0) == metaPkgList.at(z).at(0) && metaPkgList.at(z).at(5) == "YES" && (*it)->checkState(0) == Qt::Unchecked )
1225                if ( tmp.isEmpty() ){
1226                        tmp = (*it)->text(0);
1227                }else{
1228                        tmp = tmp + "," + (*it)->text(0);
1229                }
1230         ++it;
1231        }
1232
1233        return tmp;
1234}
1235
1236
1237// Time to save meta-pkgs
1238void mainWin::slotApplyMetaChanges() {
1239    saveMetaPkgs();
1240}
1241
1242
1243
1244// The User changed the tree widget checked / unchecked stuff sanity check
1245void mainWin::slotDeskPkgsChanged(QTreeWidgetItem *aItem, int __unused)
1246{
1247        if (!aItem)
1248          return;
1249
1250        disconnect(treeMetaPkgs, SIGNAL(itemChanged(QTreeWidgetItem *, int)), 0, 0);
1251
1252        if (aItem->childCount() == 0) {
1253                if (aItem->checkState(0) == Qt::Checked && aItem->parent() ){
1254                        if ( allChildrenPkgsChecked(aItem->parent()->text(0))){
1255                                aItem->parent()->setCheckState(0, Qt::Checked); 
1256                        }else{
1257                                aItem->parent()->setCheckState(0, Qt::PartiallyChecked);       
1258                        }
1259                }
1260                if (aItem->checkState(0) == Qt::Unchecked && aItem->parent() ){
1261                        if ( ! allChildrenPkgsUnchecked(aItem->parent()->text(0)))
1262                                aItem->parent()->setCheckState(0, Qt::PartiallyChecked);       
1263                }
1264
1265        } else {
1266                if (aItem->checkState(0) == Qt::Checked ){
1267                        checkAllChildrenPkgs(aItem->text(0));
1268                }else{
1269                        uncheckAllChildrenPkgs(aItem->text(0));
1270                }
1271        }
1272       
1273
1274    connect(treeMetaPkgs, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotDeskPkgsChanged(QTreeWidgetItem *, int)));
1275
1276        if ( haveMetaPkgChanges() )
1277                pushPkgApply->setEnabled(true);
1278        else
1279                pushPkgApply->setEnabled(false);
1280}
1281
1282// Check the "parent" app to see if all its children are checked or not
1283bool mainWin::allChildrenPkgsChecked(QString parent)
1284{
1285        QTreeWidgetItemIterator it(treeMetaPkgs);
1286        while (*it) {
1287         if ((*it)->text(0) == parent ) {
1288           if ( (*it)->childCount() <= 0)
1289             return true;
1290
1291           for ( int i = 0; i < (*it)->childCount() ; ++i) {
1292             if ( ! allChildrenPkgsChecked((*it)->child(i)->text(0)))
1293               return false;
1294
1295             if ((*it)->child(i)->checkState(0) != Qt::Checked ) 
1296               return false;
1297           }
1298         }
1299         ++it;
1300        }
1301        return true;
1302}
1303
1304// Check the "parent" app to see if all its children are unchecked or not
1305bool mainWin::allChildrenPkgsUnchecked(QString parent)
1306{
1307        QTreeWidgetItemIterator it(treeMetaPkgs);
1308        while (*it) {
1309         if ((*it)->text(0) == parent ) {
1310           if ( (*it)->childCount() <= 0)
1311             return true;
1312
1313           for ( int i = 0; i < (*it)->childCount() ; ++i) {
1314             if ( ! allChildrenPkgsUnchecked((*it)->child(i)->text(0)))
1315               return false;
1316
1317             if ((*it)->child(i)->checkState(0) != Qt::Unchecked ) 
1318               return false;
1319           }
1320         }
1321         ++it;
1322        }
1323        return true;
1324}
1325
1326// Check all children of parent
1327void mainWin::checkAllChildrenPkgs(QString parent)
1328{
1329        QTreeWidgetItemIterator it(treeMetaPkgs);
1330        while (*it) {
1331         if (! (*it)->parent()) {
1332           ++it;
1333           continue;
1334         } 
1335
1336         // Lets walk the tree see what pops up
1337         bool pFound=false;
1338         QTreeWidgetItem *itP = (*it)->parent();
1339         do {
1340           pFound=false;
1341           if (itP->text(0) == parent) {
1342             (*it)->setCheckState(0, Qt::Checked);
1343             break;
1344           }
1345           if ( itP->parent() ) {
1346             itP = itP->parent();
1347             pFound=true;
1348           }
1349         } while (pFound);
1350
1351         ++it;
1352       }
1353}
1354
1355// UnCheck all children of parent
1356void mainWin::uncheckAllChildrenPkgs(QString parent)
1357{
1358        QTreeWidgetItemIterator it(treeMetaPkgs);
1359        while (*it) {
1360         if (! (*it)->parent()) {
1361           ++it;
1362           continue;
1363         } 
1364
1365         // Lets walk the tree see what pops up
1366         bool pFound=false;
1367         QTreeWidgetItem *itP = (*it)->parent();
1368         do {
1369           pFound=false;
1370           if (itP->text(0) == parent) {
1371             (*it)->setCheckState(0, Qt::Unchecked);
1372             break;
1373           }
1374           if ( itP->parent() ) {
1375             itP = itP->parent();
1376             pFound=true;
1377           }
1378         } while (pFound);
1379
1380         ++it;
1381       }
1382}
1383
1384void mainWin::slotMetaRightClick()
1385{
1386        QTreeWidgetItemIterator it(treeMetaPkgs);
1387        while (*it) {
1388          for (int z=0; z < metaPkgList.count(); ++z) {
1389            if ( (*it)->isSelected() && (*it)->text(0) == metaPkgList.at(z).at(0) ) {
1390              if (metaPkgList.at(z).at(5) == "CATEGORY")
1391                return;
1392              popup = new QMenu;
1393              popup->setTitle((*it)->text(0));
1394              popup->addAction(tr("View Packages"), this, SLOT(slotMetaViewPkgs()));
1395              popup->exec( QCursor::pos() );
1396            }
1397          }
1398         ++it;
1399        }
1400}
1401
1402void mainWin::slotMetaViewPkgs()
1403{
1404        QStringList packageList;
1405        QTreeWidgetItemIterator it(treeMetaPkgs);
1406        while (*it) {
1407          for (int z=0; z < metaPkgList.count(); ++z) {
1408            if ( (*it)->isSelected() && (*it)->text(0) == metaPkgList.at(z).at(0) ) {
1409 
1410                QFile pList(metaPkgList.at(z).at(6));
1411                if ( ! pList.exists() )
1412                  return;
1413               
1414                if ( ! pList.open(QIODevice::ReadOnly | QIODevice::Text))
1415                  return;
1416
1417                while ( !pList.atEnd() )
1418                  packageList << pList.readLine().simplified();
1419
1420                pList.close();
1421                packageList.sort();
1422                       
1423                dIB = new dialogInfo();
1424                dIB->programInit(tr("Package Listing for:") + " " + (*it)->text(0));
1425                dIB->setInfoText(packageList.join("\n"));
1426                dIB->show();
1427            }
1428          }
1429         ++it;
1430        }
1431}
1432
1433QString mainWin::getLineFromCommandOutput( QString cmd )
1434{
1435        FILE *file = popen(cmd.toLatin1(),"r");
1436 
1437        char buffer[100];
1438 
1439        QString line = "";
1440        char firstChar;
1441
1442        if ((firstChar = fgetc(file)) != -1){
1443                line += firstChar;
1444                line += fgets(buffer,100,file);
1445        }
1446        pclose(file);
1447        return line.simplified();
1448}
1449
1450void mainWin::slotCloseAdvClicked()
1451{
1452   groupInfo->setVisible(false);
1453}
1454
1455void mainWin::closeEvent(QCloseEvent *event) {
1456
1457  if ( pkgCmdList.isEmpty() ) {
1458    this->close();
1459    return;   
1460  }
1461  if ( pkgCmdList.at(0).at(0).isEmpty() ) {
1462    this->close();
1463    return; 
1464  }
1465
1466  //Verify that they want to continue
1467  QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Processes Running"), tr("Packages are currently being changed. Are you sure you want to quit?"), QMessageBox::Yes | QMessageBox::Cancel,QMessageBox::Cancel);
1468  if(button == QMessageBox::Yes) {
1469    this->close();
1470  } else {
1471    event->ignore();
1472    return;
1473  }
1474}
1475
Note: See TracBrowser for help on using the repository browser.