source: src-qt4/pc-updategui/mainWin.cpp @ 67e6e29

9.1-release9.2-releasereleng/10.0releng/10.0.1releng/10.0.2
Last change on this file since 67e6e29 was 67e6e29, checked in by Kris Moore <kris@…>, 15 months ago

Update the pc-updatemanager, remove the pkgng stuff, since its all
in pc-pkgmanager now

  • Property mode set to 100644
File size: 16.6 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 "mainWin.h"
23#include "../config.h"
24
25void mainWin::ProgramInit(QString ch, QString ip)
26{
27  // Set any warden directories
28  doingUpdate=false;
29  lastError="";
30  wDir = ch;
31  wIP = ip;
32  if ( ! wDir.isEmpty() )
33     setWindowTitle(tr("Updates for Jail:") + " " + wIP );
34
35  //Grab the username
36  //username = QString::fromLocal8Bit(getenv("LOGNAME"));
37  connect(buttonRescan, SIGNAL(clicked()), this, SLOT(slotRescanUpdates()));
38  connect(pushInstallUpdates, SIGNAL(clicked()), this, SLOT(slotInstallClicked()));
39  connect(pushClose, SIGNAL(clicked()), this, SLOT(slotCloseClicked()));
40  connect(checkAll, SIGNAL(clicked()), this, SLOT(slotSelectAllClicked()));
41  connect(listViewUpdates, SIGNAL(itemClicked(QListWidgetItem *)),this,SLOT(slotListClicked()));
42  connect(listViewUpdates, SIGNAL(itemActivated(QListWidgetItem *)),this,SLOT(slotListClicked()));
43  connect(listViewUpdates, SIGNAL(itemChanged(QListWidgetItem *)),this,SLOT(slotListClicked()));
44  connect(listViewUpdates, SIGNAL(itemPressed(QListWidgetItem *)),this,SLOT(slotListClicked()));
45  connect(listViewUpdates, SIGNAL(itemDoubleClicked(QListWidgetItem *)),this,SLOT(slotListDoubleClicked(QListWidgetItem *)));
46  progressUpdate->setHidden(true);
47
48  QTimer::singleShot(100, this, SLOT(slotRescanUpdates() ) );
49}
50
51void mainWin::slotListDoubleClicked(QListWidgetItem *cItem)
52{
53  if ( listUpdates.at(listViewUpdates->row(cItem)).at(7).isEmpty() )
54     return;
55
56  QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
57  QString username = env.value( "LOGNAME" );
58
59
60  QString url = listUpdates.at(listViewUpdates->row(cItem)).at(7);
61  qDebug() << url;
62  system("su -m " + username.toLatin1() + " -c 'openwith " + url.toLatin1() + "' &"); 
63}
64
65//Check whether an update was selected to enable the button
66void mainWin::slotListClicked(){
67  bool found = false;
68
69  // Get the total number of updates
70  for (int z=0; z < listViewUpdates->count(); ++z)
71    if ( listViewUpdates->item(z)->checkState() == Qt::Checked )
72      found = true;
73
74  if(!found)
75    pushInstallUpdates->setEnabled(false);
76  else
77    pushInstallUpdates->setEnabled(true);
78}
79
80bool mainWin::sanityCheck()
81{
82  bool haveUP, haveMU;
83  int sa = 0;
84  haveUP = false;
85  haveMU = false;
86
87  for (int z=0; z < listViewUpdates->count(); ++z) {
88    if ( listViewUpdates->item(z)->checkState() == Qt::Checked ) {
89      if ( listUpdates.at(z).at(1) == "PACKAGE") {
90        haveUP = true;
91      }
92      if ( listUpdates.at(z).at(1) == "PATCH") {
93        haveUP = true;
94        if ( listUpdates.at(z).at(5) == "YES" ) 
95          sa++;
96      }
97      if ( listUpdates.at(z).at(1) == "SYSUPDATE") {
98        haveMU = true;
99      }
100    }
101  }
102
103  if ( (haveMU && haveUP ) || sa > 1 ) {
104    QMessageBox::warning(this, tr("Update Conflict"), tr("More than one stand-alone update has been selected! Please unselect all other updates and try again."));
105    return false;
106  }
107
108  return true;
109}
110
111void mainWin::doUpdates()
112{
113  // Set our UI elements
114  progressUpdate->setHidden(false);
115
116  curUpdate = -1;
117  curUpdateIndex = 0;
118  totUpdate = 0;
119
120  // Get the total number of updates
121  for (int z=0; z < listViewUpdates->count(); ++z)
122    if ( listViewUpdates->item(z)->checkState() == Qt::Checked )
123      totUpdate++;
124
125  // Start our loop processing updates
126  slotUpdateLoop();
127}
128
129void mainWin::slotUpdateLoop()
130{
131  QString tmp, tmp2, mUrl, PkgSet, Version, Arch;
132
133  // Check if the last update process finished
134  if ( curUpdate != -1 ) {
135    qDebug() << "Finished Update";
136    if ( uProc->exitStatus() != QProcess::NormalExit || uProc->exitCode() != 0)
137    {
138      // Read any remaining buffers
139      slotReadUpdateOutput();
140
141      // Warn user that this update failed
142      if ( lastError.isEmpty() )
143         QMessageBox::critical(this, tr("Update Failed!"), tr("Failed to install:") + listUpdates.at(curUpdate).at(0) + " " + tr("An unknown error occured!")); 
144      else
145         QMessageBox::critical(this, tr("Update Failed!"), tr("Failed to install:") + listUpdates.at(curUpdate).at(0) + " " + lastError); 
146    } else {
147      // If successfull system update download
148      if ( listUpdates.at(curUpdate).at(1) == "SYSUPDATE" )
149        QMessageBox::information(this, tr("Update Ready"), tr("Please reboot to start the update to PC-BSD version \"") + listUpdates.at(curUpdate).at(0) + "\". " + tr("This process may take a while, please do NOT interrupt the process.")); 
150    }
151
152    listViewUpdates->item(curUpdate)->setIcon(QIcon());
153    setWindowTitle(tr("Update Manager"));
154  }
155
156  // Start looking for the next update
157  for (int z=0; z < listViewUpdates->count(); ++z) {
158    if ( listViewUpdates->item(z)->checkState() == Qt::Checked && curUpdate < z ) 
159    {
160      curUpdate = z;
161      curUpdateIndex++;
162      progressUpdate->setHidden(false);
163      progressUpdate->setRange(0, 0);
164      tmp.setNum(curUpdateIndex);
165      tmp2.setNum(totUpdate);
166      setWindowTitle(tr("Updating:") + " " + listUpdates.at(z).at(0));
167
168      textLabel->setText(tr("Starting Update: %1 (%2 of %3)")
169                         .arg(listUpdates.at(z).at(0))
170                         .arg(tmp)
171                         .arg(tmp2));
172
173      // Get the icon
174      listViewUpdates->item(z)->setIcon(QIcon(":images/current-item.png"));
175
176      // Get the install tag
177      QString tag;
178      if ( listUpdates.at(z).at(1) == "SYSUPDATE" )
179        tag = listUpdates.at(z).at(4);
180      if ( listUpdates.at(z).at(1) == "PATCH" )
181        tag = listUpdates.at(z).at(3);
182
183      // Show tray that we are doing a download
184      QFile sysTrig( SYSTRIGGER );
185      if ( sysTrig.open( QIODevice::WriteOnly ) ) {
186        QTextStream streamTrig( &sysTrig );
187        streamTrig << "DOWNLOADING: ";
188      }
189
190      // Setup the upgrade process
191      uProc = new QProcess();
192      QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
193      env.insert("PCFETCHGUI", "YES");
194      uProc->setProcessEnvironment(env);
195      uProc->setProcessChannelMode(QProcess::MergedChannels);
196
197      // Connect the slots
198      connect( uProc, SIGNAL(readyReadStandardOutput()), this, SLOT(slotReadUpdateOutput()) );
199      connect( uProc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(slotUpdateLoop()) );
200
201      // If doing FreeBSD Update run freebsd-update cmd
202      if ( wDir.isEmpty() ) {
203         if ( listUpdates.at(z).at(1) == "FBSDUPDATE" ) {
204           uProc->start("freebsd-update", QStringList() << "install"); 
205         } else {
206           uProc->start("pc-updatemanager", QStringList() << "install" << tag ); 
207         }
208      } else {
209         // Doing a warden update in a chroot environment
210         if ( listUpdates.at(z).at(1) == "FBSDUPDATE" ) {
211           uProc->start("chroot", QStringList() << wDir << "freebsd-update" << "install"); 
212         } 
213      }
214      qDebug() << "Update started";
215      return;
216    }
217
218  }
219
220  // If we get here, no more updates to do
221  slotUpdateFinished();
222}
223
224void mainWin::slotReadUpdateOutput()
225{
226  QString line, cI, tI, tmp;
227  bool ok, ok2;
228  cI.setNum(curUpdateIndex);
229  tI.setNum(totUpdate);
230
231
232  while (uProc->canReadLine()) {
233    line = uProc->readLine().simplified();
234
235    if ( line.indexOf("FETCH:") == 0 ) {
236      tmp = line;
237      tmp = tmp.remove(0, tmp.lastIndexOf("/") + 1);
238      textLabel->setText(tr("Downloading: %1 (Update %2 of %3)")
239                         .arg(tmp)
240                         .arg(cI)
241                         .arg(tI));
242      continue;
243    }
244   
245    if ( line.indexOf("SIZE:") == 0 ) {
246      line.section(" ", 1,1).toInt(&ok);
247      line.section(" ", 3,3).toInt(&ok2);
248      if ( ok && ok2 ) {
249        progressUpdate->setRange(0, line.section(" ", 1,1).toInt(&ok));
250        progressUpdate->setValue(line.section(" ", 3,3).toInt(&ok));
251      }
252      continue;
253    }
254    if ( line.indexOf("FETCHDONE") == 0 ) {
255      progressUpdate->setRange(0, 0);
256      textLabel->setText(tr("Updating: %1 (%2 of %3)")
257                         .arg(listUpdates.at(curUpdate).at(0))
258                         .arg(cI)
259                         .arg(tI));
260      continue;
261    }
262
263    if ( line.indexOf("TOTALSTEPS:") == 0 ) {
264      line.section(" ", 1,1).toInt(&ok);
265      if ( ok )
266        progressUpdate->setRange(0, line.section(" ", 1, 1).toInt(&ok));
267      continue;
268    }
269    if ( line.indexOf("SETSTEPS:") == 0 ) {
270      line.section(" ", 1,1).toInt(&ok);
271      if ( ok )
272        progressUpdate->setValue(line.section(" ", 1, 1).toInt(&ok));
273      continue;
274    }
275    if ( line.indexOf("ERROR:") == 0 ) {
276       lastError = line;
277       continue; 
278    }
279    qDebug() << line;
280  }
281}
282
283void mainWin::slotUpdateFinished()
284{
285  qDebug() << "Updates all Finished";
286  QFile sysTrig( SYSTRIGGER );
287  if ( sysTrig.open( QIODevice::WriteOnly ) ) {
288    QTextStream streamTrig( &sysTrig );
289     streamTrig << "INSTALLFINISHED: ";
290  }
291  sysTrig.close();
292
293  progressUpdate->setHidden(true);
294  slotRescanUpdates();
295}
296
297void mainWin::slotInstallClicked()
298{
299  // Sanity check our install choices
300  if (!sanityCheck())
301    return;
302
303  // Start the installation
304  doUpdates();
305}
306
307void mainWin::slotSelectAllClicked()
308{
309  for (int z=0; z < listViewUpdates->count(); ++z) {
310    listViewUpdates->item(z)->setCheckState(checkAll->checkState());   
311  }
312
313  slotListClicked();
314}
315
316void mainWin::slotRescanUpdates()
317{
318  if ( doingUpdate )
319     return;
320  groupUpdates->setEnabled(false);
321  listUpdates.clear();
322  textLabel->setText(tr("Checking for updates... Please Wait..."));
323  slotReadUpdateData();
324  slotDisplayUpdates();
325  qDebug() << listUpdates;
326  //disable the "select all" checkbox if no updates available
327  if(listUpdates.isEmpty() ){
328    checkAll->setEnabled(false);
329  }
330  pushInstallUpdates->setEnabled(false); //disable the button until an update is selected
331  if ( ! doingUpdate )
332    groupUpdates->setEnabled(true);
333}
334
335void mainWin::slotDisplayUpdates()
336{
337  if ( ! doingUpdate )
338    groupUpdates->setEnabled(true);
339  listViewUpdates->clear();
340
341  // Check if the system has an upgrade available
342  if ( QFile::exists("/usr/local/tmp/update-stagedir/doupdate.sh") ) {
343    textLabel->setText(tr("A system upgrade is waiting to be installed. Please reboot to begin!"));
344    return;
345  }
346
347
348  // Any system updates?
349  if ( listUpdates.isEmpty() ) {
350    textLabel->setText(tr("Your system is fully updated!"));
351    groupUpdates->setTitle("");
352    groupUpdates->setEnabled(true);
353    return;
354  }
355
356  textLabel->setText(tr("System updates available!"));
357  groupUpdates->setTitle(tr("Available Updates"));
358
359  // Start parsing the updates and list whats available
360  for (int z=0; z < listUpdates.count(); ++z) {
361    if ( listUpdates.at(z).at(1) == "SYSUPDATE" ) {
362      QListWidgetItem *item = new QListWidgetItem(tr("System Upgrade: %1 (%2)")
363                                                  .arg(listUpdates.at(z).at(2))
364                                                  .arg(listUpdates.at(z).at(3)));
365      item->setToolTip(tr("PC-BSD Version:") + "<br>" + listUpdates.at(z).at(2) + "<hr>" + tr("This update must be installed by itself.") + "<br>" + tr("Creating a backup of your data first is recommended."));
366      item->setCheckState(Qt::Unchecked);
367      listViewUpdates->addItem(item);
368    }
369    if ( listUpdates.at(z).at(1) == "PATCH" ) {
370      QListWidgetItem *item = new QListWidgetItem(tr("Patch: %1 (%2)")
371                                                  .arg(listUpdates.at(z).at(0))
372                                                  .arg(listUpdates.at(z).at(2)));
373      item->setCheckState(Qt::Unchecked);
374      item->setToolTip(tr("This is a patch for your version of PC-BSD") + "<hr>" + tr("Patch Size:") + " " + listUpdates.at(z).at(4) + "MB<br>");
375      listViewUpdates->addItem(item);
376    }
377
378    if ( listUpdates.at(z).at(1) == "FBSDUPDATE" ) {
379      QString fileNameList;
380      for (int p=2; p < listUpdates.at(z).count(); p++)
381        fileNameList += listUpdates.at(z).at(p) + "<br>";
382
383      QListWidgetItem *item = new QListWidgetItem(tr("FreeBSD Security Update"));
384      item->setCheckState(Qt::Unchecked);
385      item->setToolTip(tr("The following files need updating:") + "<hr>" + fileNameList);
386     
387      listViewUpdates->addItem(item);
388    }
389
390    if ( listUpdates.at(z).at(1) == "PACKAGE" ) {
391      QString pkgNameList;
392      for (int p=2; p < listUpdates.at(z).count(); p=p+5) {
393        if ( listUpdates.at(z).count() < p + 4 ) 
394          break;
395
396        pkgNameList += listUpdates.at(z).at((p)) + " " + listUpdates.at(z).at((p+1)) + " -> " + listUpdates.at(z).at((p+2)) + "<br>";
397      }
398      QListWidgetItem *item = new QListWidgetItem(tr("System Package Updates"));
399      item->setCheckState(Qt::Unchecked);
400      item->setToolTip(tr("The following package updates are available:") + "<hr>" + pkgNameList);
401     
402      listViewUpdates->addItem(item);
403    }
404  }
405}
406
407void mainWin::slotReadUpdateData()
408{
409  // If on the base system, check for PC-BSD updates
410  if ( wDir.isEmpty() )
411    checkPCUpdates();
412
413  // Check for FreeBSD Updates now
414  checkFBSDUpdates();
415
416}
417
418void mainWin::checkPCUpdates() {
419
420  QString line, tmp, name, type, version, date, tag, url, size, sa, rr;
421  QStringList up;
422
423  QProcess p;
424  p.start(QString("pc-updatemanager"), QStringList() << "check");
425  while(p.state() == QProcess::Starting || p.state() == QProcess::Running)
426     QCoreApplication::processEvents();
427
428  while (p.canReadLine()) {
429    line = p.readLine().simplified();
430    if ( line.indexOf("NAME: ") == 0) {
431       name = line.replace("NAME: ", "");
432       continue;
433    }
434    if ( line.indexOf("TYPE: ") == 0) {
435       type = line.replace("TYPE: ", "");
436       continue;
437    }
438
439    if ( type == "SYSUPDATE" ) {
440      if ( line.indexOf("VERSION: ") == 0) {
441         version = line.replace("VERSION: ", "");
442         continue;
443      }
444      if ( line.indexOf("DATE: ") == 0) {
445         date = line.replace("DATE: ", "");
446         continue;
447      }
448      if ( line.indexOf("TAG: ") == 0) {
449         tag = line.replace("TAG: ", "");
450         continue;
451      }
452      if ( line.indexOf("DETAILS: ") == 0) {
453         url = line.replace("DETAILS: ", "");
454         continue;
455      }
456
457      if ( line.indexOf("To install:") == 0) {
458         up.clear();
459         up << name << type << version << date << tag << url;
460         listUpdates.append(up);
461         type=""; name="", version="", date="", tag="", url="";
462         continue;
463      }
464
465    }
466    if ( type == "PATCH" ) {
467      if ( line.indexOf("DATE: ") == 0) {
468         date = line.replace("DATE: ", "");
469         continue;
470      }
471      if ( line.indexOf("TAG: ") == 0) {
472         tag = line.replace("TAG: ", "");
473         continue;
474      }
475      if ( line.indexOf("SIZE: ") == 0) {
476         size = line.replace("SIZE: ", "");
477         continue;
478      }
479      if ( line.indexOf("STANDALONE: ") == 0) {
480         sa = line.replace("STANDALONE: ", "");
481         continue;
482      }
483      if ( line.indexOf("REQUIRESREBOOT: ") == 0) {
484         rr = line.replace("REQUIRESREBOOT: ", "");
485         continue;
486      }
487      if ( line.indexOf("DETAILS: ") == 0) {
488         url = line.replace("DETAILS: ", "");
489         continue;
490      }
491      if ( line.indexOf("To install:") == 0) {
492         // TODO add this update to list
493         up.clear();
494         up << name << type << date << tag << size << sa << rr << url;
495         listUpdates.append(up);
496         type=""; name="", date="", tag="", size="", sa="", rr="", url="";
497         continue;
498      }
499    }
500
501  }
502
503
504}
505
506void mainWin::checkFBSDUpdates() {
507  QString line;
508  QStringList up, listPkgs;
509
510  // Now check if there are freebsd-updates to install
511  QProcess f;
512  if ( wDir.isEmpty() )
513     f.start(QString("pc-fbsdupdatecheck"), QStringList());
514  else {
515     QProcess::execute("cp /usr/local/bin/pc-fbsdupdatecheck " + wDir + "/tmp/.fbupdatechk");
516     QProcess::execute("chmod 755 " + wDir + "/tmp/.fbupdatechk");
517     f.start(QString("chroot"), QStringList() << wDir << "/tmp/.fbupdatechk" << "fetch" );
518  }
519  while(f.state() == QProcess::Starting || f.state() == QProcess::Running)
520     QCoreApplication::processEvents();
521
522  bool fUp = false;
523 
524  while (f.canReadLine()) {
525    line = f.readLine().simplified();
526    qDebug() << line;
527    if ( line.indexOf("The following files will be updated ") == 0) {
528       fUp = true;
529       continue;
530    }
531
532    if ( fUp )
533       listPkgs << line;
534  }
535
536  if ( ! wDir.isEmpty() )
537     QProcess::execute("rm " + wDir + "/tmp/.fbupdatechk");
538
539  // Are there freebsd updates to install?
540  if ( fUp ) {
541    up.clear();
542    up << "FreeBSD Security Updates" << "FBSDUPDATE";
543    up.append(listPkgs);
544    listUpdates.append(up);
545  }
546
547}
548
549void mainWin::slotSingleInstance() {
550   this->hide();
551   this->showNormal();
552   this->activateWindow();
553   this->raise();
554}
555
556void mainWin::slotCloseClicked() {
557   close();
558}
559
Note: See TracBrowser for help on using the repository browser.