fix #6581, #6590
[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         if( !iSettings->qsettings()->value("disable_autorotation",false).toBool() ) {
86                 this->setAttribute(Qt::WA_Maemo5AutoOrientation);
87         } else {
88                 this->setAttribute(Qt::WA_Maemo5LandscapeOrientation);
89         }
90         this->setAttribute(Qt::WA_Maemo5StackedWindow);
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         iMediaObject = new Phonon::MediaObject(this);
142         Phonon::AudioOutput* aout = new Phonon::AudioOutput(Phonon::NotificationCategory, this);
143         Phonon::createPath(iMediaObject, aout);
144
145         showFreeSpace();
146
147         iNetworkConfigurationManager = new QNetworkConfigurationManager(this);
148         iNetworkSession = new QNetworkSession(iNetworkConfigurationManager->defaultConfiguration(),this);
149
150         show();
151         rescaleMenuView();
152 }
153
154 MainWindow::~MainWindow()
155 {
156         // save "need repo refresh" status
157         iSettings->qsettings()->setValue("need_repo_refresh", iAptInterface->needRepoRefresh());
158
159         if( iNetworkSession && iNetworkSession->isOpen() ) {
160                 iNetworkSession->close();
161         }
162         // iNetworkSession automatically deleted by parent
163
164         delete iWinPackageView; iWinPackageView=0;
165         delete iWinRepoView; iWinRepoView=0;
166         delete iAptInterface; iAptInterface=0;
167         delete iDpkgInterface; iDpkgInterface=0;
168         delete iDimmer; iDimmer=0;
169         delete iSettings; iSettings=0;
170         delete ui; ui=0;
171         //iMediaObject and aout automatically deleted by their parent
172 }
173
174 void MainWindow::openNetworkConnection()
175 {
176         if( iNetworkSession->isOpen() )
177                 return;
178
179         iNetworkSession->open();
180         if( !iNetworkSession->waitForOpened(20000) )
181         {
182                 ConfirmDialog d(false, this);
183                 d.setText("Network error","Unable to open a network connection");
184                 d.exec();
185         }
186 }
187
188 void MainWindow::changeEvent(QEvent *e)
189 {
190     QMainWindow::changeEvent(e);
191     switch (e->type()) {
192     case QEvent::LanguageChange:
193         ui->retranslateUi(this);
194         break;
195     default:
196         break;
197     }
198 }
199
200 void MainWindow::on_btnRepos_clicked()
201 {
202         iWinRepoView->openWin();
203 }
204
205 void MainWindow::on_btnUpdate_clicked()
206 {       
207         // update catalogs
208
209         openNetworkConnection();
210
211         busyDialog(true, tr("Operation in progress"), tr("Updating catalogs"));
212
213         iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetUpdate);
214         iAptInterface->run(iDimmer);
215 }
216
217 #ifdef Q_WS_MAEMO_5
218 int MainWindow::top_application()
219 {
220         show();
221         activateWindow();
222         raise();
223         return 0;
224 }
225 #endif
226
227 void MainWindow::dateFetchAsk()
228 {
229         if( !iSettings->qsettings()->value("firstrun_asked_fetch_dates",false).toBool() &&
230                 !iSettings->qsettings()->value("fetch_dates",false).toBool() )
231         {
232                 iSettings->qsettings()->setValue("firstrun_asked_fetch_dates", true);
233                 ConfirmDialog d(true, this);
234                 d.setText("Fetch date information?","Enable date information fetching for packages? You have to enable it in order to be "
235                                   "able to sort packages by date. The first fetch can be slow but the dates are cached for later use. You can later "
236                                   "change this selection from the options menu.");
237                 if( d.exec() )
238                         iSettings->qsettings()->setValue("fetch_dates", true);
239         }
240         if( iSettings->qsettings()->value("fetch_dates",false).toBool() )
241         {
242                 iSettings->qsettings()->setValue("firstrun_asked_fetch_dates", true);   // don't ask if the option has already been enabled
243                 if( !iAptInterface->dateCacheExists() )
244                 {
245                         ConfirmDialog d(false, this);
246                         d.setText("Notice","Date information will be fetched only for packages from maemo.org and only for user categories.");
247                         d.exec();
248                 }
249                 iAptInterface->addQueuedOperation(AAptInterface::ModeFetchDates);
250         }
251 }
252
253 void MainWindow::on_btnListInstallable_clicked()
254 {
255         //install
256
257         openNetworkConnection();
258
259         int listupd = -1;
260         int dpkgupd = -1;
261         if( iAptInterface->lastListUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
262                 listupd = 1;
263         if( iAptInterface->lastDpkgUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
264                 dpkgupd = 1;
265         iAptInterface->setNeedRefresh(-1,listupd,dpkgupd,listupd);
266
267         iWinPackageView->setStatFilter( Package::PkgStatNotInstalled );
268
269         if( iAptInterface->needRepoRefresh() && !iSettings->qsettings()->value("no_catalogs_autoupdate",false).toBool() )
270                 iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetUpdate);
271
272         busyDialog(true, tr("Operation in progress"), tr("Reading package lists"));
273
274         iNextOperation = OpOpenPkgView;
275         iAptInterface->addQueuedOperation(AAptInterface::ModeReadPackages);
276
277         dateFetchAsk();
278
279         iAptInterface->run(iDimmer);
280 }
281
282 void MainWindow::on_btnUpgrade_clicked()
283 {
284         // upgrade
285
286         openNetworkConnection();
287
288         int listupd = -1;
289         int dpkgupd = -1;
290         if( iAptInterface->lastListUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
291                 listupd = 1;
292         if( iAptInterface->lastDpkgUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
293                 dpkgupd = 1;
294         iAptInterface->setNeedRefresh(-1,listupd,dpkgupd,listupd);
295
296         iWinPackageView->setStatFilter( Package::PkgStatUpgradeable );
297
298         if( iAptInterface->needRepoRefresh() && !iSettings->qsettings()->value("no_catalogs_autoupdate",false).toBool() )
299                 iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetUpdate);
300
301         busyDialog(true, tr("Operation in progress"), tr("Reading package lists"));
302
303         iNextOperation = OpOpenPkgView;
304         iAptInterface->addQueuedOperation(AAptInterface::ModeReadPackages);
305
306         dateFetchAsk();
307
308         iAptInterface->run(iDimmer);
309 }
310
311 void MainWindow::on_btnListInstalled_clicked()
312 {
313         //remove
314
315         if( !iSettings->qsettings()->value("remove_readfull",false).toBool() )
316                 iAptInterface->setSkipListAndDates();
317
318         int dpkgupd = -1;
319         if( iAptInterface->lastDpkgUpdate() < QDateTime::currentDateTime().addSecs(-KListExpireTime) )
320                 dpkgupd = 1;
321         iAptInterface->setNeedRefresh(-1,-1,dpkgupd,-1);
322
323         iWinPackageView->setStatFilter( Package::PkgStatInstalled );
324
325         busyDialog(true, tr("Operation in progress"), tr("Reading package lists"));
326
327         iNextOperation = OpOpenPkgView;
328         iAptInterface->addQueuedOperation(AAptInterface::ModeReadPackages);
329
330         dateFetchAsk();
331
332         iAptInterface->run(iDimmer);
333 }
334
335 void MainWindow::operationQueueFinished(QList<AAptInterface::interfaceMode> lastModes, bool success, QString title, QStringList msgs)
336 {
337         if( lastModes.contains(AAptInterface::ModeAptGetSimulate) && success ) {
338                 iNextOperation = OpPromptSimulated;
339         }
340         if( lastModes.contains(AAptInterface::ModeAptGetInstall) && success ) {
341                 iWinPackageView->clearSelections();
342                 busyDialog(false);
343                 iWinPackageView->close();
344                 iNextOperation = OpNone;
345
346                 GdkEventIconThemeReload();
347         }
348
349         QWidget* dialogParent = this;
350         if( iWinPackageView->isVisible() )
351                 dialogParent = iWinPackageView;
352
353         if( iNextOperation == OpOpenPkgView && success )
354         {
355                 iWinPackageView->openWin();
356                 busyDialog(false);
357                 iNextOperation = OpNone;
358         } else if( iNextOperation == OpPromptSimulated && success )
359         {
360                 QStringList inst,remv,instver,remvver;
361                 QStringList all = iAptInterface->processPackages();
362                 QStringList vers = iAptInterface->processPackageVersions();
363                 for(int zyx=0; zyx<all.count(); zyx++)
364                 {
365                         if( all.at(zyx).endsWith('-') )
366                         {
367                                 remv.append( all.at(zyx).left( all.at(zyx).size()-1 ) );
368                                 if( vers.count()>zyx )
369                                         remvver.append( vers.at(zyx) );
370                         } else {
371                                 inst.append( all.at(zyx) );
372                                 if( vers.count()>zyx )
373                                         instver.append( vers.at(zyx) );
374                         }
375                 }
376
377                 int total_dl_size = 0;
378                 for( int i=0; i<inst.count(); i++ ) {
379                         Package* pkg = iAptInterface->packagesAvailable()->value(inst.at(i),0);
380                         if( pkg ) {
381                                 total_dl_size += pkg->size()/1024;
382                         }
383                 }
384
385                 QString pkglist;
386                 pkglist = QString("<b>The following operations will be performed:</b><br>"
387                                   "%1 to install/upgrade, %2 to remove<br>").arg(inst.count()).arg(remv.count());
388                 if( inst.count()>0 )
389                         pkglist += QString("Total download size: %L1 kB<br>").arg(total_dl_size);
390                 bool mismatch = false;
391                 bool warn_system_package_remove = false;
392                 bool warn_system_package_install = false;
393
394                 if( remv.count()>0 ) {
395                         pkglist += "<br><b><u>REMOVE:</u></b><br><font size=\"-1\">";
396                         for( int i=0; i<remv.count(); i++ ) {
397                                 pkglist += "<b>" + remv.at(i) + "</b>";
398                                 Package* pkg = iAptInterface->packagesInstalled()->value(remv.at(i),0);
399                                 if( !pkg ) {
400                                         qDebug() << "Warning: unknown package" << remv.at(i);
401                                         pkglist += "<font color=\"red\">***UNKNOWN***</font>";
402                                         mismatch = true;
403                                 }
404 #ifdef Q_WS_MAEMO_5
405                                 if( pkg && pkg->maemoDisplayName()=="Maemo 5" ) {
406                                         warn_system_package_remove = true;
407                                 }
408 #endif
409                                 if( remvver.count()>i ) {
410                                         pkglist += " " + remvver.at(i);
411                                         if( pkg && remvver.at(i) != pkg->version() ) {
412                                                 qDebug() << "Version mismatch, database version is" << pkg->version() << "but removing" << remvver.at(i);
413                                                 mismatch = true;
414                                                 pkglist += " <font color=\"red\">***TRYING TO REMOVE " + pkg->version() + "***</font> ";
415                                         }
416                                 }
417                                 if( pkg && pkg->installedSize()>0 )
418                                         pkglist += QString(" (%L1 kB)").arg(pkg->installedSize());
419                                 pkglist += "<br>";
420                         }
421                 }
422                 pkglist += "</font>";
423
424                 bool installing_blacklisted = false;
425                 if( inst.count()>0 ) {
426                         pkglist += "<br><b><u>INSTALL/UPGRADE:</u></b><br><font size=\"-1\">";
427                         for( int i=0; i<inst.count(); i++ ) {
428                                 pkglist += "<b>" + inst.at(i) + "</b>";
429                                 Package* pkg = iAptInterface->packagesAvailable()->value(inst.at(i),0);
430                                 if( !pkg ) {
431                                         qDebug() << "Warning: unknown package" << inst.at(i);
432                                         pkglist += "<font color=\"red\">***NEW/UNKNOWN***</font>";
433                                         mismatch = true;
434                                 }
435                                 if( pkg && pkg->isBlacklisted() ) {
436                                         qDebug() << "Warning: installing blacklisted package" << inst.at(i);
437                                         pkglist += "<font color=\"red\">***BLACKLISTED***</font>";
438                                         installing_blacklisted = true;
439                                 }
440 #ifdef Q_WS_MAEMO_5
441                                 if( pkg && pkg->maemoDisplayName()=="Maemo 5" ) {       // unreliable?
442                                         warn_system_package_install = true;
443                                 }
444 #endif
445                                 if( instver.count()>i ) {
446                                         pkglist += " " + instver.at(i);
447                                         if( pkg && instver.at(i) != pkg->version() ) {
448                                                 qDebug() << "Version mismatch, database version is" << pkg->version() << "but installing" << instver.at(i);
449                                                 mismatch = true;
450                                                 pkglist += " <font color=\"red\">***TRYING TO INSTALL " + pkg->version() + "***</font> ";
451                                         }
452                                 }
453                                 if( pkg && pkg->size()>0 ) {
454                                         pkglist += QString(" (%L1 kB)").arg(pkg->size()/1024);
455                                 }
456                                 pkglist += "<br>";
457                         }
458                 }
459                 pkglist += "</font>";
460
461                 if( mismatch ) {
462                         ConfirmDialog m(false, dialogParent);
463                         m.setText("Warning", "There is a version mismatch between your original package selections and some of the packages being installed " \
464                                           "from the repositories. This could be due to your application catalogs being out of date.");
465                         m.exec();
466                 }
467                 if( installing_blacklisted ) {
468                         ConfirmDialog b(false, dialogParent);
469                         b.setText("Warning","Blacklisted package(s) will be installed");
470                         b.exec();
471                 }
472                 if( warn_system_package_remove ) {
473                         ConfirmDialog s(false, dialogParent);
474                         s.setText("Warning","You are about to remove a critical system package.");
475                         s.exec();
476                 }
477                 if( warn_system_package_install ) {
478                         ConfirmDialog s(false, dialogParent);
479                         s.setText("Warning","You are trying to perform an install/upgrade operation on a critical system package. Doing a system upgrade with " \
480                                           "Faster Application Manager has not been tested and it could result in a horrible failure. You have been warned.");
481                         s.exec();
482                 }
483
484                 busyDialog(false);
485                 ConfirmDialog d(true, dialogParent);
486                 if( inst.count()==0 && remv.count()==0 )
487                 {
488                         pkglist = "None of the packages can be installed";
489                         d.disableButton();
490                 }
491                 d.setText("Confirmation",pkglist);
492                 if( d.exec() ) {
493                         iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetInstall);
494
495                         if( iSettings->qsettings()->value("enable_autoclean",true).toBool() && inst.count()>0 )
496                                 iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetClean);
497
498                         QString busytext;
499                         if( remv.count() > 0 )
500                                 busytext += QString("Remove %1 package(s)<br>").arg(remv.count());
501                         if( inst.count() > 0 )
502                                 busytext += QString("Install %1 package(s)<br>").arg(inst.count());
503                         busytext += "Preparing...";
504                         busyDialog(true, "Operation in progress", busytext);
505
506                         // "run" really does nothing here since the previous item should still be running
507                         if( iWinPackageView->isVisible() ) {
508                                 iAptInterface->run(iWinPackageView->mydimmer());
509                         } else {
510                                 iAptInterface->run(iDimmer);
511                         }
512                 }
513                 iNextOperation = OpNone;
514                 return;
515         } else {
516                 busyDialog(false);
517                 iNextOperation = OpNone;
518
519                 if( iSettings->qsettings()->value("sound_notify",false).toBool() )
520                 {
521                         qDebug() << "playing sound";
522                         iMediaObject->setCurrentSource( Phonon::MediaSource(iSettings->qsettings()->value("sound_file","/usr/share/sounds/ui-operation_ready.wav").toString()) );
523                         iMediaObject->play();
524                 }
525
526                 QString text = "<br><b><u>Faster Application Manager</u></b><br>"
527                                            "<b>"+title+"</b><br>" + msgs.join("<br>") + "<br>";
528
529                 QRect r = QApplication::desktop()->rect();
530                 if(r.width() < r.height()) {
531                         ConfirmDialog d(false, dialogParent);
532                         d.setText(title,msgs.join("<br>"));
533                         d.exec();
534                 } else {
535 #ifdef Q_WS_MAEMO_5
536                         QMaemo5InformationBox::information(0, text, QMaemo5InformationBox::NoTimeout);
537 #else
538                         ConfirmDialog d(false, dialogParent);
539                         d.setText(title,msgs.join("<br>"));
540                         d.exec();
541 #endif
542                 }
543
544                 showFreeSpace();
545         }
546
547 }
548
549 void MainWindow::busyDialog(bool show_, QString title, QString text)
550 {
551         if( show_ ) {
552                 iDimmer->setProgress(-1);
553                 ui->menuMenu->setEnabled(false);
554                 ui->centralWidget->setEnabled(false);
555                 iWinPackageView->disableMenu();
556                 iDimmer->resizeEvent(0);
557                 iDimmer->dim(title, text);
558                 iWinPackageView->mydimmer()->resizeEvent(0);
559                 iWinPackageView->mydimmer()->dim(title, text);
560         } else {
561                 iDimmer->undim();
562                 iWinPackageView->mydimmer()->undim();
563                 ui->menuMenu->setEnabled(true);
564                 ui->centralWidget->setEnabled(true);
565                 iWinPackageView->enableMenu();
566         }
567 }
568
569 void MainWindow::on_actionAbout_triggered()
570 {
571         ConfirmDialog d(false, this);
572         d.setText("About","Faster Application Manager<br>"
573                           "<font size=\"-1\">Version " + PROGRAM_VERSION + "</font><br><br>"
574                           "(C) Heikki Holstila 2010<br>Donate using "
575                           "<a href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=6ZKRY5QFHL42A&lc=FI&item_name=Faster%20Application%20Manager"
576                           "%20for%20Maemo5&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted\">PayPal</a>");
577         d.exec();
578 }
579
580 void MainWindow::on_actionClean_triggered()
581 {
582         //if( iOperation != OpNone ) return;
583         //iOperation = OpClean;
584         iAptInterface->addQueuedOperation(AAptInterface::ModeAptGetClean);
585         iAptInterface->run(iDimmer);
586 }
587
588 void MainWindow::closeEvent(QCloseEvent *event)
589 {
590         if( iDimmer->busy() ) {
591                 iAptInterface->cancel();
592                 event->ignore();
593         } else {
594                 event->accept();
595         }
596 }
597
598 void MainWindow::on_actionView_log_triggered()
599 {
600         QByteArray log = iAptInterface->readLogFile();
601         LogView l(log, this);
602         l.exec();
603 }
604
605 void MainWindow::on_actionOptions_triggered()
606 {
607         iSettings->openWin();
608 }
609
610 void MainWindow::notifyDialog(QString title, QString msg)
611 {
612         QWidget* dialogParent = this;
613         if( iWinPackageView->isVisible() )
614                 dialogParent = iWinPackageView;
615
616         ConfirmDialog d(false, dialogParent);
617         d.setText(title, msg);
618         d.exec();
619 }
620
621 bool MainWindow::confirmDialog(QString title, QString msg)
622 {
623         QWidget* dialogParent = this;
624         if( iWinPackageView->isVisible() )
625                 dialogParent = iWinPackageView;
626
627         ConfirmDialog d(true, dialogParent);
628         d.setText(title, msg);
629         return d.exec();
630 }
631
632 void MainWindow::GdkEventIconThemeReload()
633 {
634         // DOES NOT EVEN WORK (at least not reliably) - disabled from the project file
635
636 #ifdef MYDEF_GTK_EXISTS
637         qDebug() << "Sending GDK icon theme reload event";
638
639         gdk_init((int*)QApplication::argc(),(gchar***)QApplication::argv());
640
641         // taken from hildon application manager
642         GdkEventClient ev;
643         ev.type = GDK_CLIENT_EVENT;
644         ev.window = NULL;
645         ev.send_event = TRUE;
646         ev.message_type = gdk_atom_intern_static_string("_GTK_LOAD_ICONTHEMES");
647         ev.data_format = 32;
648         gdk_event_send_clientmessage_toall((GdkEvent*)&ev);
649
650         while(gdk_events_pending()) {
651                 g_main_context_iteration(NULL, true);
652         }
653
654 #endif
655 }
656
657 void MainWindow::on_actionLoad_file_triggered()
658 {
659         QStringList files = QFileDialog::getOpenFileNames(this, "Open files", "/", "Files (*.deb *.install)");
660         if( files.count() > 0 ) {
661                 QStringList debs = files.filter(QRegExp(".*\\.deb$"));
662                 QStringList installs = files.filter(QRegExp(".*\\.install$"));
663                 if( debs.count()>0 && installs.count()>0 ) {
664                         ConfirmDialog d(false, this);
665                         d.setText("Error", "You can't mix different file types in your selection");
666                         d.exec();
667                         return;
668                 }
669                 if( debs.count()>0 )
670                         iDpkgInterface->loadDebFiles(debs);
671                 else if( installs.count()>0 )
672                         iAptInterface->loadInstallFiles(installs);
673         }
674 }
675
676 void MainWindow::resizeEvent(QResizeEvent* event)
677 {
678         rescaleMenuView();
679
680         if( iDimmer ) {
681                 iDimmer->resize( this->size() );
682         }
683
684         QMainWindow::resizeEvent(event);
685 }
686
687 void MainWindow::rescaleMenuView()
688 {
689         QRect sg = ui->listWidget->rect();
690
691         if( sg.width() > sg.height() ) {
692                 ui->listWidget->setGridSize( QSize((sg.width()-12)/5, (sg.height()-12)/2) );
693         } else {
694                 ui->listWidget->setGridSize( QSize((sg.width()-12)/3, (sg.height()-12)/3) );
695         }
696 }
697
698 void MainWindow::orientationChanged()
699 {
700 }
701
702
703 void MainWindow::showFreeSpace()
704 {
705         quint64 warn_limit_root = 5120;
706         quint64 warn_limit_opt = 51200;
707         struct statfs root_stat;
708         struct statfs opt_stat;
709         statfs("/",&root_stat);
710         statfs("/opt",&opt_stat);
711         quint64 free_root = static_cast<quint64>(root_stat.f_bavail) * static_cast<quint64>(root_stat.f_bsize) / 1024;
712         quint64 free_opt = static_cast<quint64>(opt_stat.f_bavail) * static_cast<quint64>(opt_stat.f_bsize) / 1024;
713         quint64 total_root = static_cast<quint64>(root_stat.f_blocks) * static_cast<quint64>(root_stat.f_bsize) / 1024;
714         quint64 total_opt = static_cast<quint64>(opt_stat.f_blocks) * static_cast<quint64>(opt_stat.f_bsize) / 1024;
715         qDebug() << "rootfs" << free_root << "/" << total_root << "kB free";
716         qDebug() << "opt fs" << free_opt << "/" << total_opt << "kB free";
717
718         QString rootstr = QString("rootfs: %L1 / %L2 MB free").arg(free_root/1024).arg(total_root/1024);
719         QString optstr = QString("opt: %L1 / %L2 MB free").arg(free_opt/1024).arg(total_opt/1024);
720
721         ui->label->setText("<font size=\"-1\">" + rootstr + "<br>" + optstr + "</font>");
722
723         /*
724         ui->progressBarRoot->setFormat(rootstr);
725         ui->progressBarRoot->setMaximum(total_root/1024);
726         ui->progressBarRoot->setValue(free_root/1024);
727         ui->progressBarOpt->setFormat(optstr);
728         ui->progressBarOpt->setMaximum(total_opt/1024);
729         ui->progressBarOpt->setValue(free_opt/1024);
730         */
731
732         if( free_root < warn_limit_root || free_opt < warn_limit_opt )
733         {
734                 ConfirmDialog d(false, this);
735                 QString t;
736                 if( free_root < warn_limit_root )
737                         t += QString("Root filesystem has %L1 kB available<br>").arg(free_root);
738                 if( free_opt < warn_limit_opt )
739                         t += QString("Opt (home) filesystem has %L1 kB available<br>").arg(free_opt);
740                 t += "<br>You may proceed, but consider freeing up space to prevent problems in the future";
741                 d.setText("Warning: Low disk space",t);
742                 d.exec();
743         }
744 }
745
746 void MainWindow::on_listWidget_itemClicked(QListWidgetItem* item)
747 {
748         qDebug() << "main menu:" << item->statusTip();
749
750         if( item->statusTip() == "manage_repos" ) {
751                 on_btnRepos_clicked();
752         }
753         else if( item->statusTip() == "update_catalogs" ) {
754                 on_btnUpdate_clicked();
755         }
756         else if( item->statusTip() == "install_apps" ) {
757                 on_btnListInstallable_clicked();
758         }
759         else if( item->statusTip() == "remove_apps" ) {
760                 on_btnListInstalled_clicked();
761         }
762         else if( item->statusTip() == "upgrade_apps" ) {
763                 on_btnUpgrade_clicked();
764         }
765         else {
766                 qDebug() << "Warning: Unhandled main menu item";
767         }
768         item->setSelected(false);
769 }