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

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

Warn before closing during package operations

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