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

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

Finish up the pc-pkgmanager search algorithm, now it will also search the top level items, and expand them properly as necessary

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