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

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

Skip empty lines in pkgng output

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