source: src-qt4/pc-pkgmanager/mainWin.cpp @ 358972f

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3
Last change on this file since 358972f was 358972f, checked in by Kris Moore <kris@…>, 13 months ago

Make sure we don't end up back in basic mode for the package
manager when running on a chroot / jail

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