File indexing completed on 2024-04-21 05:45:05

0001 /* This file is part of Apper
0002  *
0003  * Copyright (C) 2012 Matthias Klumpp <matthias@tenstral.net>
0004  *
0005  * This program is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation; either version 2 of the License, or
0008  * (at your option) any later version.
0009  *
0010  * This program is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0013  * GNU General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU General Public License
0016  * along with this program; see the file COPYING. If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include <limba.h>
0022 #include <appstream.h>
0023 
0024 #include "SetupWizard.h"
0025 #include "ui_SetupWizard.h"
0026 
0027 #include <QLabel>
0028 #include <QApplication>
0029 #include <QAction>
0030 #include <QProgressBar>
0031 #include <QCheckBox>
0032 #include <QPushButton>
0033 #include <KDebug>
0034 #include <KMessageBox>
0035 #include <KGlobalSettings>
0036 #include <KLocalizedString>
0037 
0038 #include "InfoWidget.h"
0039 #include "SimplePage.h"
0040 
0041 class SetupWizardPrivate
0042 {
0043 public:
0044     SetupWizardPrivate()
0045         : setup(NULL), cpt(NULL)
0046     {
0047         preparationPageCount = -1;
0048     }
0049 
0050     ~SetupWizardPrivate()
0051     {
0052         if (setup != NULL)
0053             g_object_unref (setup);
0054         if (cpt != NULL)
0055             g_object_unref (cpt);
0056     }
0057 
0058     int preparationPageCount;
0059 
0060     // Package information
0061     LiInstaller *setup;
0062     AsComponent *cpt;
0063     LiPkgInfo *pki;
0064 
0065     // UI components
0066     InfoWidget *infoPage;
0067     SimplePage *execPage;
0068     QProgressBar *progressBar;
0069 };
0070 
0071 SetupWizard::SetupWizard(QWidget *parent)
0072     : KDialog (parent),
0073       d(new SetupWizardPrivate()),
0074       ui(new Ui::SetupWizard)
0075 {
0076     ui->setupUi(KDialog::mainWidget());
0077     setAttribute(Qt::WA_DeleteOnClose);
0078 
0079     connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
0080             this, SLOT(updatePallete()));
0081     updatePallete();
0082 
0083     setWindowIcon(KIcon("system-software-install"));
0084     setButtons(KDialog::User1 | KDialog::Ok | KDialog::Cancel);
0085     setButtonText(KDialog::Ok, i18n("Continue"));
0086     setButtonIcon(KDialog::Ok, KIcon("go-next"));
0087     setButtonText(KDialog::User1, i18n("Back"));
0088     setButtonIcon(KDialog::User1, KIcon("go-previous"));
0089 
0090     enableButtonOk(true);
0091 
0092     connect(ui->stackedWidget, SIGNAL(currentChanged(int)), this, SLOT(currentPageChanged(int)));
0093 
0094     setMinimumSize(QSize(430,280));
0095     KConfig config("apper");
0096     KConfigGroup configGroup(&config, "AppInstaller");
0097     restoreDialogSize(configGroup);
0098 }
0099 
0100 SetupWizard::~SetupWizard()
0101 {
0102     delete d;
0103     delete ui;
0104 }
0105 
0106 void SetupWizard::showError(const QString& details)
0107 {
0108     d->infoPage->reset();
0109     d->infoPage->setWindowTitle(i18n("Error"));
0110     d->infoPage->setDescription(i18n("An error occurred"));
0111     d->infoPage->setIcon(KIcon("dialog-error"));
0112     d->infoPage->setDetails(details);
0113     this->setButtons(KDialog::Close);
0114     this->button(KDialog::Close)->setFocus();
0115     this->setCurrentPage(d->infoPage);
0116 }
0117 
0118 bool SetupWizard::constructWizardLayout()
0119 {
0120     if (d->preparationPageCount > 1)
0121         return true;
0122 
0123     if (d->preparationPageCount == 0) {
0124     ui->stackedWidget->addWidget(d->infoPage);
0125     }
0126 
0127 
0128     if (d->cpt == NULL) {
0129         kDebug() << "AppStream component was NULL!";
0130         return false;
0131     }
0132 
0133     QString appName = as_component_get_name(d->cpt);
0134 
0135     // Welcome page
0136     SimplePage *introP = new SimplePage(this);
0137     introP->setTitle(i18n("Welcome!"));
0138     introP->setDescription(i18n("Welcome to the installation of %1!", appName));
0139     introP->setDetails(i18n("Please be careful while installing a 3rd-party application.<br>"
0140                             "It might eventually <b>damage</b> your system or "
0141                             "have <b>malicious behaviour</b>, like spying out your passwords.<br>"
0142                             "Please do only install this software if you <b>trust its "
0143                             "publisher</b>."));
0144     ui->stackedWidget->addWidget(introP);
0145     d->preparationPageCount = 1;
0146 
0147     // Setup details page
0148     SimplePage *detailsP = new SimplePage(this);
0149     detailsP->setTitle(i18n("Details"));
0150     detailsP->setDescription(i18n("Details about this installation"));
0151 
0152     QWidget *securityWidget = new QWidget(detailsP);
0153     QHBoxLayout *secWgLayout = new QHBoxLayout();
0154     securityWidget->setLayout(secWgLayout);
0155 
0156     QLabel *pix = new QLabel(detailsP);
0157 
0158     LiTrustLevel trust = li_installer_get_package_trust_level(d->setup, NULL);
0159     if (trust == LI_TRUST_LEVEL_HIGH)
0160         pix->setPixmap(KIcon("security-high").pixmap (32, 32));
0161     else if ((trust == LI_TRUST_LEVEL_LOW) || (trust == LI_TRUST_LEVEL_MEDIUM))
0162         pix->setPixmap(KIcon("security-medium").pixmap (32, 32));
0163     else if ((trust == LI_TRUST_LEVEL_NONE) || (trust == LI_TRUST_LEVEL_INVALID))
0164         pix->setPixmap(KIcon("security-low").pixmap (32, 32));
0165     else
0166         pix->setPixmap(KIcon("task-reject").pixmap (32, 32));
0167     secWgLayout->addWidget(pix);
0168 
0169     QLabel *secInfoL = new QLabel(detailsP);
0170     secInfoL->setText(QString::fromUtf8(li_trust_level_to_text(trust)));
0171     secWgLayout->addWidget(secInfoL);
0172 
0173     // Install mode select checkbox
0174     secWgLayout->addStretch();
0175     detailsP->addWidget(securityWidget);
0176 
0177     ui->stackedWidget->addWidget(detailsP);
0178     d->preparationPageCount++;
0179 
0180     // Application description page
0181     QString desc = as_component_get_description(d->cpt);
0182     if (desc.isEmpty())
0183         desc = as_component_get_summary(d->cpt);
0184     SimplePage *descP = new SimplePage(this);
0185     descP->setTitle(i18n("Application description"));
0186     descP->setDescription(i18n("Description"));
0187     descP->setDetails(desc);
0188     ui->stackedWidget->addWidget(descP);
0189     d->preparationPageCount++;
0190 
0191     // Setup exec page
0192     d->execPage = new SimplePage(this);
0193     d->execPage->setTitle(i18n("Running installation"));
0194     d->execPage->setDescription(i18n("Installing %1...", appName));
0195     d->progressBar = new QProgressBar(d->execPage);
0196     d->progressBar->setMinimumHeight(40);
0197     d->execPage->addWidget(d->progressBar);
0198     ui->stackedWidget->addWidget(d->execPage);
0199     d->preparationPageCount++;
0200 
0201     setCurrentPage(introP);
0202 
0203     return true;
0204 }
0205 
0206 void SetupWizard::currentPageChanged(int index)
0207 {
0208     // Set the page title
0209     ui->titleL->setText(ui->stackedWidget->currentWidget()->windowTitle());
0210 
0211     // Show "back" button if necessary
0212     if (index > 1)
0213         enableButton(KDialog::User1, true);
0214     else
0215         enableButton(KDialog::User1, false);
0216 }
0217 
0218 void SetupWizard::setCurrentPage(QWidget* widget)
0219 {
0220     ui->stackedWidget->setCurrentWidget(widget);
0221 }
0222 
0223 void SetupWizard::runInstallation()
0224 {
0225     GError *error = NULL;
0226 
0227     // We now show the install dialog, so run the installation now!
0228     li_installer_install(d->setup, &error);
0229 
0230     if (error == NULL) {
0231         /* we installed successfully */
0232         QString appName = QString::fromUtf8(as_component_get_name (d->cpt));
0233         d->infoPage->reset();
0234         d->infoPage->setWindowTitle(i18n("Installation finished!"));
0235         d->infoPage->setDescription(i18n("%1 has been installed successfully!", appName));
0236         d->infoPage->setIcon(KIcon("dialog-ok-apply"));
0237         setButtons(KDialog::Close);
0238         button(KDialog::Close)->setFocus();
0239         setCurrentPage(d->infoPage);
0240     } else {
0241         /* there was an error */
0242         showError(QString::fromUtf8(error->message));
0243         g_error_free (error);
0244     }
0245 }
0246 
0247 
0248 void SetupWizard::slotButtonClicked(int button)
0249 {
0250     if (button == KDialog::Ok) {
0251         // We go forward
0252 
0253         int index = ui->stackedWidget->currentIndex();
0254         if (index < d->preparationPageCount) {
0255             index++;
0256             ui->stackedWidget->setCurrentIndex(index);
0257         }
0258 
0259         if (index == d->preparationPageCount-1) {
0260             setButtonText(KDialog::Ok, i18n("Install"));
0261             setButtonIcon(KDialog::Ok, KIcon("dialog-ok-apply"));
0262         }
0263 
0264         if (index == d->preparationPageCount) {
0265             // We can install the software now, so disable prev/fwd & abort buttons
0266             enableButton(KDialog::User1, false);
0267             enableButton(KDialog::Ok, false);
0268             enableButton(KDialog::Cancel, false);
0269 
0270             ui->stackedWidget->update();
0271             runInstallation();
0272         }
0273 
0274     } else if (button == KDialog::User1) {
0275         // We go back
0276 
0277         int index = ui->stackedWidget->currentIndex();
0278         if (index > 1) {
0279             index--;
0280             // Make sure go-forward button is enabled
0281             enableButton(KDialog::Ok, true);
0282             ui->stackedWidget->setCurrentIndex(index);
0283             if (index == 1)
0284                 enableButton(KDialog::User1, false);
0285         }
0286     } else if (button == KDialog::Cancel) {
0287         close();
0288     } else if (button == KDialog::Close) {
0289         close();
0290     }
0291 }
0292 
0293 bool SetupWizard::initialize(const QString& ipkFName)
0294 {
0295     GError *error = NULL;
0296     AsMetadata *mdata;
0297     gchar *data;
0298 
0299     // Create a new installer instance
0300     d->setup = li_installer_new ();
0301 
0302     // Create info page to notify about errors
0303     d->infoPage = new InfoWidget(this);
0304     d->infoPage->setWindowTitle("Information");
0305     ui->stackedWidget->addWidget(d->infoPage);
0306 
0307     // Load the package file, required to have metadata
0308     li_installer_open_file(d->setup, ipkFName.toUtf8().data(), &error);
0309     if (error != NULL) {
0310         this->showError(QString::fromUtf8(error->message));
0311         g_error_free (error);
0312         return false;
0313     }
0314 
0315     data = li_installer_get_appstream_data (d->setup);
0316     mdata = as_metadata_new ();
0317     as_metadata_parse (mdata, data, AS_FORMAT_KIND_XML, &error);
0318     g_free (data);
0319     if (error != NULL) {
0320         this->showError(QString::fromUtf8(error->message));
0321         g_error_free (error);
0322         g_object_unref (mdata);
0323         return false;
0324     }
0325 
0326     d->cpt = as_metadata_get_component (mdata);
0327     g_object_ref (d->cpt);
0328     d->pki = li_installer_get_package_info (d->setup);
0329     g_object_unref (mdata);
0330 
0331     // Build layout of our setup wizard
0332     constructWizardLayout();
0333 
0334     return true;
0335 }
0336 
0337 void SetupWizard::updatePallete()
0338 {
0339     QPalette pal;
0340     pal.setColor(QPalette::Window, KGlobalSettings::activeTitleColor());
0341     pal.setColor(QPalette::WindowText, KGlobalSettings::activeTextColor());
0342     ui->backgroundFrame->setPalette(pal);
0343 }