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

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

Clean up the new search functionality in pc-pkgmanager. It is now recursive and fast (so no worries about changing the depth of the tree's) The only caveat is that it will not return a top-level item as a search result at the moment.
Also setup the search button to be actively enabled/disabled

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