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