code cleanup
[fapman] / mainwindow.cpp
1 /*
2         This file is part of Faster Application Manager.
3
4         Faster Application Manager is free software: you can redistribute it and/or modify
5         it under the terms of the GNU General Public License as published by
6         the Free Software Foundation, either version 3 of the License, or
7         (at your option) any later version.
8
9         Faster Application Manager is distributed in the hope that it will be useful,
10         but WITHOUT ANY WARRANTY; without even the implied warranty of
11         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12         GNU General Public License for more details.
13
14         You should have received a copy of the GNU General Public License
15         along with Faster Application Manager.  If not, see <http://www.gnu.org/licenses/>.
16
17         (C) Heikki Holstila 2010
18 */
19
20 #ifdef MYDEF_GTK_EXISTS
21 extern "C"
22 {
23         #include <gdk/gdk.h>
24         #include <gtk/gtk.h>
25 }
26 #endif
27
28 #include <QtCore>
29 #include <QtGui>
30 #include <QDBusConnection>
31 #include <QDBusInterface>
32 #include <phonon/AudioOutput>
33 #include <phonon/MediaObject>
34
35 #ifdef Q_WS_MAEMO_5
36 #include <QtMaemo5>
37 #endif
38
39 extern "C"
40 {
41         #include <sys/vfs.h>
42 }
43
44 #include "mainwindow.h"
45 #include "version.h"
46 #include "ui_mainwindow.h"
47 #include "aaptinterface.h"
48 #include "packageview.h"
49 #include "confirmdialog.h"
50 #include "dimmer.h"
51 #include "repoview.h"
52 #include "help.h"
53 #include "settings.h"
54 #include "logview.h"
55 #include "rotatingbackground.h"
56 #include "dpkginterface.h"
57
58
59 MainWindow::MainWindow(QWidget *parent) :
60     QMainWindow(parent),
61     ui(new Ui::MainWindow)
62 {
63     ui->setupUi(this);
64
65         iAptInterface = new AAptInterface(this);
66         iWinPackageView = new PackageView(this);
67         iWinPackageView->setAptInterface(iAptInterface);
68         iWinRepoView = new RepoView(this);
69         iWinRepoView->setAptInterface(iAptInterface);
70         iSettings = new Settings(this);
71         iSettings->setAptInterface(iAptInterface);
72         iSettings->setPackageView(iWinPackageView);
73         iWinPackageView->setSettings(iSettings);
74         iAptInterface->setSettings(iSettings);
75         iDpkgInterface = new DpkgInterface(this);
76
77         iWinPackageView->setSortOrder( (PackageView::sortOrder)iSettings->qsettings()->value("default_sort_order",0).toInt() );
78
79         iWinPackageView->setSearchOptions( iSettings->qsettings()->value("search_pkgnames",true).toBool(),
80                                                                            iSettings->qsettings()->value("search_displaynames",true).toBool(),
81                                                                            iSettings->qsettings()->value("search_descshort",true).toBool(),
82                                                                            iSettings->qsettings()->value("search_desclong",false).toBool() );
83
84 #ifdef Q_WS_MAEMO_5
85         this->setAttribute(Qt::WA_Maemo5StackedWindow);
86         if( !iSettings->qsettings()->value("disable_autorotation",false).toBool() ) {
87                 this->setAttribute(Qt::WA_Maemo5AutoOrientation);
88         } else {
89                 this->setAttribute(Qt::WA_Maemo5LandscapeOrientation);
90         }
91 #endif
92
93         iDimmer = new dimmer(this);
94
95         iReposAutoUpdating = false;
96         iUpgradeAutoUpdate = true;
97         iNextOperation = OpNone;
98
99         connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(orientationChanged()));
100
101         ui->centralWidget->loadWallpaper();
102
103         /*
104         QString stylesheet_mainscreen =
105                         "QPushButton {"
106                         "border-radius: 16px;"
107                         "border-width: 1px;"
108                         "border-color: palette(light);"
109                         "border-style: outset;"
110                         "padding-right: 10px;"
111                         "padding-left: 10px;"
112                         "color: palette(buttontext);"
113                         "background: rgba(255,255,255,80);"
114                         "}"
115                         "QPushButton:pressed {"
116                         "border-style: inset;"
117                         "background-color: rgba(255,255,255,150);"
118                         "}";
119         */
120
121         if( ((QApplication*)QApplication::instance())->styleSheet().isEmpty() )
122         {
123                 QString stylesheet_file;
124                 QFile f("/root/.fapman/style.css");
125                 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
126                 {
127                         while(!f.atEnd()) {
128                                 stylesheet_file += f.readLine().trimmed();
129                         }
130                         f.close();
131                 }
132
133                 if( stylesheet_file.isEmpty() ) {
134                         //ui->centralWidget->setStyleSheet(stylesheet_mainscreen);
135                 } else {
136                         ((QApplication*)QApplication::instance())->setStyleSheet(stylesheet_file);
137                 }
138         }
139
140
141         /*
142         // does not work
143
144         QDBusConnection conn = QDBusConnection::connectToBus(QDBusConnection::SystemBus, "faster_application_manager");
145
146         QString service = "com.nokia.icd";
147         QString path = "/com/nokia/icd";
148         QString method = "connect";
149
150         QDBusInterface net(service, path, service, conn, this);
151         net.call(method,"[ANY]",0);
152         */
153
154         iMediaObject = new Phonon::MediaObject(this);
155         Phonon::AudioOutput* aout = new Phonon::AudioOutput(Phonon::NotificationCategory, this);
156         Phonon::createPath(iMediaObject, aout);
157
158         showFreeSpace();
159
160         show();
161         orientationChanged();
162 }
163
164 MainWindow::~MainWindow()
165 {
166         // save "need repo refresh" status
167         iSettings->qsettings()->setValue("need_repo_refresh", iAptInterface->needRepoRefresh());
168
169         delete iWinPackageView; iWinPackageView=0;
170         delete iWinRepoView; iWinRepoView=0;
171         delete iAptInterface; iAptInterface=0;
172         delete iDpkgInterface; iDpkgInterface=0;
173         delete iDimmer; iDimmer=0;
174         delete iSettings; iSettings=0;
175         delete ui; ui=0;
176         //iMediaObject and aout automatically deleted by their parent
177 }
178
179 void MainWindow::changeEvent(QEvent *e)
180 {
181     QMainWindow::changeEvent(e);
182     switch (e->type()) {
183     case QEvent::LanguageChange:
184         ui->retranslateUi(this);
185         break;
186     default:
187         break;
188     }
189 }
190
191 void MainWindow::on_btnRepos_clicked()
192 {
193         iWinRepoView->openWin();
194 }
195
196 void MainWindow::on_btnUpdate_clicked()
197 {       
198         // update catalogs
199
200         busyDialog(true, tr("Operation in progress"), tr("Updating catalogs"));
201
202         iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetUpdate);
203         iAptInterface->run(iDimmer);
204 }
205
206 #ifdef Q_WS_MAEMO_5
207 int MainWindow::top_application()
208 {
209         show();
210         activateWindow();
211         raise();
212         return 0;
213 }
214 #endif
215
216 void MainWindow::dateFetchAsk()
217 {
218         if( !iSettings->qsettings()->value("firstrun_asked_fetch_dates",false).toBool() &&
219                 !iSettings->qsettings()->value("fetch_dates",false).toBool() )
220         {
221                 iSettings->qsettings()->setValue("firstrun_asked_fetch_dates", true);
222                 ConfirmDialog d(true, this);
223                 d.setText("Fetch date information?","Enable date information fetching for packages? You have to enable it in order to be "
224                                   "able to sort packages by date. The first fetch can be slow but the dates are cached for later use. You can later "
225                                   "change this selection from the options menu.");
226                 if( d.exec() )
227                         iSettings->qsettings()->setValue("fetch_dates", true);
228         }
229         if( iSettings->qsettings()->value("fetch_dates",false).toBool() )
230         {
231                 iSettings->qsettings()->setValue("firstrun_asked_fetch_dates", true);   // don't ask if the option has already been enabled
232                 if( !iAptInterface->dateCacheExists() )
233                 {
234                         ConfirmDialog d(false, this);
235                         d.setText("Notice","Date information will be fetched only for packages from maemo.org and only for user categories.");
236                         d.exec();
237                 }
238                 iAptInterface->addQueuedOperation(AAptInterface::ModeFetchDates);
239         }
240 }
241
242 void MainWindow::on_btnListInstallable_clicked()
243 {
244         //install
245
246         int listupd = -1;
247         int dpkgupd = -1;
248         if( iAptInterface->lastListUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
249                 listupd = 1;
250         if( iAptInterface->lastDpkgUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
251                 dpkgupd = 1;
252         iAptInterface->setNeedRefresh(-1,listupd,dpkgupd,listupd);
253
254         iWinPackageView->setStatFilter( Package::PkgStatNotInstalled );
255
256         if( iAptInterface->needRepoRefresh() && !iSettings->qsettings()->value("no_catalogs_autoupdate",false).toBool() )
257                 iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetUpdate);
258
259         busyDialog(true, tr("Operation in progress"), tr("Reading package lists"));
260
261         iNextOperation = OpOpenPkgView;
262         iAptInterface->addQueuedOperation(AAptInterface::ModeReadPackages);
263
264         dateFetchAsk();
265
266         iAptInterface->run(iDimmer);
267 }
268
269 void MainWindow::on_btnUpgrade_clicked()
270 {
271         // upgrade
272
273         int listupd = -1;
274         int dpkgupd = -1;
275         if( iAptInterface->lastListUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
276                 listupd = 1;
277         if( iAptInterface->lastDpkgUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
278                 dpkgupd = 1;
279         iAptInterface->setNeedRefresh(-1,listupd,dpkgupd,listupd);
280
281         iWinPackageView->setStatFilter( Package::PkgStatUpgradeable );
282
283         if( iAptInterface->needRepoRefresh() && !iSettings->qsettings()->value("no_catalogs_autoupdate",false).toBool() )
284                 iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetUpdate);
285
286         busyDialog(true, tr("Operation in progress"), tr("Reading package lists"));
287
288         iNextOperation = OpOpenPkgView;
289         iAptInterface->addQueuedOperation(AAptInterface::ModeReadPackages);
290
291         dateFetchAsk();
292
293         iAptInterface->run(iDimmer);
294 }
295
296 void MainWindow::on_btnListInstalled_clicked()
297 {
298         //remove
299
300         if( !iSettings->qsettings()->value("remove_readfull",false).toBool() )
301                 iAptInterface->setSkipListAndDates();
302
303         int dpkgupd = -1;
304         if( iAptInterface->lastDpkgUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
305                 dpkgupd = 1;
306         iAptInterface->setNeedRefresh(-1,-1,dpkgupd,-1);
307
308         iWinPackageView->setStatFilter( Package::PkgStatInstalled );
309
310         busyDialog(true, tr("Operation in progress"), tr("Reading package lists"));
311
312         iNextOperation = OpOpenPkgView;
313         iAptInterface->addQueuedOperation(AAptInterface::ModeReadPackages);
314
315         dateFetchAsk();
316
317         iAptInterface->run(iDimmer);
318 }
319
320 void MainWindow::operationQueueFinished(QList<AAptInterface::interfaceMode> lastModes, bool success, QString title, QStringList msgs)
321 {
322         if( lastModes.contains(AAptInterface::ModeAptGetSimulate) && success ) {
323                 iNextOperation = OpPromptSimulated;
324         }
325         if( lastModes.contains(AAptInterface::ModeAptGetInstall) && success ) {
326                 iWinPackageView->clearSelections();
327                 busyDialog(false);
328                 iWinPackageView->close();
329                 iNextOperation = OpNone;
330
331                 GdkEventIconThemeReload();
332         }
333
334         QWidget* dialogParent = this;
335         if( iWinPackageView->isVisible() )
336                 dialogParent = iWinPackageView;
337
338         if( iNextOperation == OpOpenPkgView && success )
339         {
340                 iWinPackageView->openWin();
341                 busyDialog(false);
342                 iNextOperation = OpNone;
343         } else if( iNextOperation == OpPromptSimulated && success )
344         {
345                 QStringList inst,remv,instver,remvver;
346                 QStringList all = iAptInterface->processPackages();
347                 QStringList vers = iAptInterface->processPackageVersions();
348                 for(int zyx=0; zyx<all.count(); zyx++)
349                 {
350                         if( all.at(zyx).endsWith('-') )
351                         {
352                                 remv.append( all.at(zyx).left( all.at(zyx).size()-1 ) );
353                                 if( vers.count()>zyx )
354                                         remvver.append( vers.at(zyx) );
355                         } else {
356                                 inst.append( all.at(zyx) );
357                                 if( vers.count()>zyx )
358                                         instver.append( vers.at(zyx) );
359                         }
360                 }
361
362                 int total_dl_size = 0;
363                 for( int i=0; i<inst.count(); i++ ) {
364                         Package* pkg = iAptInterface->packagesAvailable()->value(inst.at(i),0);
365                         if( pkg ) {
366                                 total_dl_size += pkg->size()/1024;
367                         }
368                 }
369
370                 QString pkglist;
371                 pkglist = QString("<b>The following operations will be performed:</b><br>"
372                                   "%1 to install/upgrade, %2 to remove<br>").arg(inst.count()).arg(remv.count());
373                 if( inst.count()>0 )
374                         pkglist += QString("Total download size: %L1 kB<br>").arg(total_dl_size);
375                 bool mismatch = false;
376                 bool warn_system_package_remove = false;
377                 bool warn_system_package_install = false;
378
379                 if( remv.count()>0 ) {
380                         pkglist += "<br><b><u>REMOVE:</u></b><br><font size=\"-1\">";
381                         for( int i=0; i<remv.count(); i++ ) {
382                                 pkglist += "<b>" + remv.at(i) + "</b>";
383                                 Package* pkg = iAptInterface->packagesInstalled()->value(remv.at(i),0);
384                                 if( !pkg ) {
385                                         qDebug() << "Warning: unknown package" << remv.at(i);
386                                         pkglist += "<font color=\"red\">***UNKNOWN***</font>";
387                                         mismatch = true;
388                                 }
389 #ifdef Q_WS_MAEMO_5
390                                 if( pkg && pkg->maemoDisplayName()=="Maemo 5" ) {
391                                         warn_system_package_remove = true;
392                                 }
393 #endif
394                                 if( remvver.count()>i ) {
395                                         pkglist += " " + remvver.at(i);
396                                         if( pkg && remvver.at(i) != pkg->version() ) {
397                                                 qDebug() << "Version mismatch, database version is" << pkg->version() << "but removing" << remvver.at(i);
398                                                 mismatch = true;
399                                                 pkglist += " <font color=\"red\">***TRYING TO REMOVE " + pkg->version() + "***</font> ";
400                                         }
401                                 }
402                                 if( pkg && pkg->installedSize()>0 )
403                                         pkglist += QString(" (%L1 kB)").arg(pkg->installedSize());
404                                 pkglist += "<br>";
405                         }
406                 }
407                 pkglist += "</font>";
408
409                 bool installing_blacklisted = false;
410                 if( inst.count()>0 ) {
411                         pkglist += "<br><b><u>INSTALL/UPGRADE:</u></b><br><font size=\"-1\">";
412                         for( int i=0; i<inst.count(); i++ ) {
413                                 pkglist += "<b>" + inst.at(i) + "</b>";
414                                 Package* pkg = iAptInterface->packagesAvailable()->value(inst.at(i),0);
415                                 if( !pkg ) {
416                                         qDebug() << "Warning: unknown package" << inst.at(i);
417                                         pkglist += "<font color=\"red\">***NEW/UNKNOWN***</font>";
418                                         mismatch = true;
419                                 }
420                                 if( pkg && pkg->isBlacklisted() ) {
421                                         qDebug() << "Warning: installing blacklisted package" << inst.at(i);
422                                         pkglist += "<font color=\"red\">***BLACKLISTED***</font>";
423                                         installing_blacklisted = true;
424                                 }
425 #ifdef Q_WS_MAEMO_5
426                                 if( pkg && pkg->maemoDisplayName()=="Maemo 5" ) {
427                                         warn_system_package_install = true;
428                                 }
429 #endif
430                                 if( instver.count()>i ) {
431                                         pkglist += " " + instver.at(i);
432                                         if( pkg && instver.at(i) != pkg->version() ) {
433                                                 qDebug() << "Version mismatch, database version is" << pkg->version() << "but installing" << instver.at(i);
434                                                 mismatch = true;
435                                                 pkglist += " <font color=\"red\">***TRYING TO INSTALL " + pkg->version() + "***</font> ";
436                                         }
437                                 }
438                                 if( pkg && pkg->size()>0 ) {
439                                         pkglist += QString(" (%L1 kB)").arg(pkg->size()/1024);
440                                 }
441                                 pkglist += "<br>";
442                         }
443                 }
444                 pkglist += "</font>";
445
446                 if( mismatch ) {
447                         ConfirmDialog m(false, dialogParent);
448                         m.setText("Warning", "There is a version mismatch between your original package selections and some of the packages being installed " \
449                                           "from the repositories. This could be due to your application catalogs being out of date.");
450                         m.exec();
451                 }
452                 if( installing_blacklisted ) {
453                         ConfirmDialog b(false, dialogParent);
454                         b.setText("Warning","Blacklisted package(s) will be installed");
455                         b.exec();
456                 }
457                 if( warn_system_package_remove ) {
458                         ConfirmDialog s(false, dialogParent);
459                         s.setText("Warning","You are about to remove a critical system package.");
460                         s.exec();
461                 }
462                 if( warn_system_package_install ) {
463                         ConfirmDialog s(false, dialogParent);
464                         s.setText("Warning","You are trying to perform an install/upgrade operation on a critical system package. Doing a system upgrade with " \
465                                           "Faster Application Manager has not been tested and it could result in a horrible failure. You have been warned.");
466                         s.exec();
467                 }
468
469                 busyDialog(false);
470                 ConfirmDialog d(true, dialogParent);
471                 if( inst.count()==0 && remv.count()==0 )
472                 {
473                         pkglist = "None of the packages can be installed";
474                         d.disableButton();
475                 }
476                 d.setText("Confirmation",pkglist);
477                 if( d.exec() ) {
478                         iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetInstall);
479
480                         if( iSettings->qsettings()->value("enable_autoclean",true).toBool() && inst.count()>0 )
481                                 iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetClean);
482
483                         QString busytext;
484                         if( remv.count() > 0 )
485                                 busytext += QString("Remove %1 package(s)<br>").arg(remv.count());
486                         if( inst.count() > 0 )
487                                 busytext += QString("Install %1 package(s)<br>").arg(inst.count());
488                         busytext += "Preparing...";
489                         busyDialog(true, "Operation in progress", busytext);
490
491                         // "run" really does nothing here since the previous item should still be running
492                         if( iWinPackageView->isVisible() ) {
493                                 iAptInterface->run(iWinPackageView->mydimmer());
494                         } else {
495                                 iAptInterface->run(iDimmer);
496                         }
497                 }
498                 iNextOperation = OpNone;
499                 return;
500         } else {
501                 busyDialog(false);
502                 iNextOperation = OpNone;
503
504                 if( iSettings->qsettings()->value("sound_notify",false).toBool() )
505                 {
506                         qDebug() << "playing sound";
507                         iMediaObject->setCurrentSource( Phonon::MediaSource(iSettings->qsettings()->value("sound_file","/usr/share/sounds/ui-operation_ready.wav").toString()) );
508                         iMediaObject->play();
509                 }
510
511                 QString text = "<br><b><u>Faster Application Manager</u></b><br>"
512                                            "<b>"+title+"</b><br>" + msgs.join("<br>") + "<br>";
513
514                 QRect r = QApplication::desktop()->rect();
515                 if(r.width() < r.height()) {
516                         ConfirmDialog d(false, dialogParent);
517                         d.setText(title,msgs.join("<br>"));
518                         d.exec();
519                 } else {
520 #ifdef Q_WS_MAEMO_5
521                         QMaemo5InformationBox::information(0, text, QMaemo5InformationBox::NoTimeout);
522 #else
523                         ConfirmDialog d(false, dialogParent);
524                         d.setText(title,msgs.join("<br>"));
525                         d.exec();
526 #endif
527                 }
528
529                 showFreeSpace();
530         }
531
532 }
533
534 void MainWindow::busyDialog(bool show_, QString title, QString text)
535 {
536         if( show_ ) {
537                 iDimmer->setProgress(-1);
538                 ui->menuMenu->setEnabled(false);
539                 ui->centralWidget->setEnabled(false);
540                 iWinPackageView->disableMenu();
541                 iDimmer->resizeEvent(0);
542                 iDimmer->dim(title, text);
543                 iWinPackageView->mydimmer()->resizeEvent(0);
544                 iWinPackageView->mydimmer()->dim(title, text);
545         } else {
546                 iDimmer->undim();
547                 iWinPackageView->mydimmer()->undim();
548                 ui->menuMenu->setEnabled(true);
549                 ui->centralWidget->setEnabled(true);
550                 iWinPackageView->enableMenu();
551         }
552 }
553
554 void MainWindow::on_actionAbout_triggered()
555 {
556         ConfirmDialog d(false, this);
557         d.setText("About","Faster Application Manager<br>"
558                           "<font size=\"-1\">Version " + PROGRAM_VERSION + "</font><br><br>"
559                           "(C) Heikki Holstila 2010<br>Donate using "
560                           "<a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=6ZKRY5QFHL42A&lc=FI&item_name=Faster%20Application%20Manager"
561                           "%20for%20Maemo5&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted\">PayPal</a>");
562         d.exec();
563 }
564
565 void MainWindow::on_actionClean_triggered()
566 {
567         //if( iOperation != OpNone ) return;
568         //iOperation = OpClean;
569         iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetClean);
570         iAptInterface->run(iDimmer);
571 }
572
573 void MainWindow::closeEvent(QCloseEvent *event)
574 {
575         if( iDimmer->busy() ) {
576                 iAptInterface->cancel();
577                 event->ignore();
578         } else {
579                 event->accept();
580         }
581 }
582
583 void MainWindow::on_actionView_log_triggered()
584 {
585         QByteArray log = iAptInterface->readLogFile();
586         LogView l(log, this);
587         l.exec();
588 }
589
590 void MainWindow::on_actionOptions_triggered()
591 {
592         iSettings->openWin();
593 }
594
595 void MainWindow::notifyDialog(QString title, QString msg)
596 {
597         QWidget* dialogParent = this;
598         if( iWinPackageView->isVisible() )
599                 dialogParent = iWinPackageView;
600
601         ConfirmDialog d(false, dialogParent);
602         d.setText(title, msg);
603         d.exec();
604 }
605
606 bool MainWindow::confirmDialog(QString title, QString msg)
607 {
608         QWidget* dialogParent = this;
609         if( iWinPackageView->isVisible() )
610                 dialogParent = iWinPackageView;
611
612         ConfirmDialog d(true, dialogParent);
613         d.setText(title, msg);
614         return d.exec();
615 }
616
617 void MainWindow::GdkEventIconThemeReload()
618 {
619         // DOES NOT EVEN WORK (at least not reliably) - disabled from the project file
620
621 #ifdef MYDEF_GTK_EXISTS
622         qDebug() << "Sending GDK icon theme reload event";
623
624         gdk_init((int*)QApplication::argc(),(gchar***)QApplication::argv());
625
626         // taken from hildon application manager
627         GdkEventClient ev;
628         ev.type = GDK_CLIENT_EVENT;
629         ev.window = NULL;
630         ev.send_event = TRUE;
631         ev.message_type = gdk_atom_intern_static_string("_GTK_LOAD_ICONTHEMES");
632         ev.data_format = 32;
633         gdk_event_send_clientmessage_toall((GdkEvent*)&ev);
634
635         while(gdk_events_pending()) {
636                 g_main_context_iteration(NULL, true);
637         }
638
639 #endif
640 }
641
642 void MainWindow::on_actionLoad_file_triggered()
643 {
644         QStringList files = QFileDialog::getOpenFileNames(this, "Open files", "/", "Files (*.deb *.install)");
645         if( files.count() > 0 ) {
646                 QStringList debs = files.filter(QRegExp(".*\\.deb$"));
647                 QStringList installs = files.filter(QRegExp(".*\\.install$"));
648                 if( debs.count()>0 && installs.count()>0 ) {
649                         ConfirmDialog d(false, this);
650                         d.setText("Error", "You can't mix different file types in your selection");
651                         d.exec();
652                         return;
653                 }
654                 if( debs.count()>0 )
655                         iDpkgInterface->loadDebFiles(debs);
656                 else if( installs.count()>0 )
657                         iAptInterface->loadInstallFiles(installs);
658         }
659 }
660
661 void MainWindow::orientationChanged()
662 {
663         if( QApplication::desktop()->width() > QApplication::desktop()->height() )
664                 ui->listWidget->setGridSize( QSize((ui->listWidget->width()-12)/5, (ui->listWidget->height()-12)/2) );
665         else
666                 ui->listWidget->setGridSize( QSize((ui->listWidget->width()-12)/3, (ui->listWidget->height()-12)/3) );
667 }
668
669
670 void MainWindow::showFreeSpace()
671 {
672         quint64 warn_limit_root = 5120;
673         quint64 warn_limit_opt = 51200;
674         struct statfs root_stat;
675         struct statfs opt_stat;
676         statfs("/",&root_stat);
677         statfs("/opt",&opt_stat);
678         quint64 free_root = root_stat.f_bavail * root_stat.f_bsize / 1024;
679         quint64 free_opt = opt_stat.f_bavail * opt_stat.f_bsize / 1024;
680         quint64 total_root = root_stat.f_blocks * root_stat.f_bsize / 1024;
681         quint64 total_opt = opt_stat.f_blocks * opt_stat.f_bsize / 1024;
682         qDebug() << "rootfs" << free_root << "/" << total_root << "kB free";
683         qDebug() << "opt fs" << free_opt << "/" << total_opt << "kB free";
684
685         QString rootstr = QString("rootfs: %L1 / %L2 MB free").arg(free_root/1024).arg(total_root/1024);
686         QString optstr = QString("opt: %L1 / %L2 MB free").arg(free_opt/1024).arg(total_opt/1024);
687
688         ui->label->setText("<font size=\"-1\">" + rootstr + "<br>" + optstr + "</font>");
689
690         /*
691         ui->progressBarRoot->setFormat(rootstr);
692         ui->progressBarRoot->setMaximum(total_root/1024);
693         ui->progressBarRoot->setValue(free_root/1024);
694         ui->progressBarOpt->setFormat(optstr);
695         ui->progressBarOpt->setMaximum(total_opt/1024);
696         ui->progressBarOpt->setValue(free_opt/1024);
697         */
698
699         if( free_root < warn_limit_root || free_opt < warn_limit_opt )
700         {
701                 ConfirmDialog d(false, this);
702                 QString t;
703                 if( free_root < warn_limit_root )
704                         t += QString("Root filesystem has %L1 kB available<br>").arg(free_root);
705                 if( free_opt < warn_limit_opt )
706                         t += QString("Opt (home) filesystem has %L1 kB available<br>").arg(free_opt);
707                 t += "<br>You may proceed, but consider freeing up space to prevent problems in the future";
708                 d.setText("Warning: Low disk space",t);
709                 d.exec();
710         }
711 }
712
713 void MainWindow::on_listWidget_itemClicked(QListWidgetItem* item)
714 {
715         qDebug() << "main menu:" << item->statusTip();
716
717         if( item->statusTip() == "manage_repos" ) {
718                 on_btnRepos_clicked();
719         }
720         else if( item->statusTip() == "update_catalogs" ) {
721                 on_btnUpdate_clicked();
722         }
723         else if( item->statusTip() == "install_apps" ) {
724                 on_btnListInstallable_clicked();
725         }
726         else if( item->statusTip() == "remove_apps" ) {
727                 on_btnListInstalled_clicked();
728         }
729         else if( item->statusTip() == "upgrade_apps" ) {
730                 on_btnUpgrade_clicked();
731         }
732         else {
733                 qDebug() << "Warning: Unhandled main menu item";
734         }
735         item->setSelected(false);
736 }