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

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

Make sure that hitting the "return" key in the search box will automatically start the package search.

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