~dantti/apper/master

« back to all changes in this revision

Viewing changes to libapper/PkTransaction.cpp

  • Committer: Daniel Nicoletti
  • Date: 2011-07-27 21:02:31 UTC
  • Revision ID: git-v1:2fb51b7787e2e9d70d2085cc8181a12f4277b047
The idea of libshared, was for it to be static, as
this doesn't seem too simple as putting STATIC word
I'm renaming it to libapper so we don't have such a geniric
lib installed (as pointed by Kevin Kofler

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2008-2011 by Daniel Nicoletti                           *
 
3
 *   dantti85-pk@yahoo.com.br                                              *
 
4
 *                                                                         *
 
5
 *   This program is free software; you can redistribute it and/or modify  *
 
6
 *   it under the terms of the GNU General Public License as published by  *
 
7
 *   the Free Software Foundation; either version 2 of the License, or     *
 
8
 *   (at your option) any later version.                                   *
 
9
 *                                                                         *
 
10
 *   This program is distributed in the hope that it will be useful,       *
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
13
 *   GNU General Public License for more details.                          *
 
14
 *                                                                         *
 
15
 *   You should have received a copy of the GNU General Public License     *
 
16
 *   along with this program; see the file COPYING. If not, write to       *
 
17
 *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,  *
 
18
 *   Boston, MA 02110-1301, USA.                                           *
 
19
 ***************************************************************************/
 
20
 
 
21
#include <config.h>
 
22
 
 
23
#include "PkTransaction.h"
 
24
 
 
25
#include <KLocale>
 
26
#include <KMessageBox>
 
27
#include <KPushButton>
 
28
#include <KService>
 
29
#include <KPixmapSequence>
 
30
#include <KPixmapSequenceOverlayPainter>
 
31
 
 
32
#include <KDebug>
 
33
 
 
34
#include <QPropertyAnimation>
 
35
#include <QtDBus/QDBusMessage>
 
36
#include <QtDBus/QDBusConnection>
 
37
#include <QtGui/QTreeView>
 
38
 
 
39
#include <Daemon>
 
40
 
 
41
#include "KpkMacros.h"
 
42
#include "KpkEnum.h"
 
43
#include "KpkStrings.h"
 
44
#include "KpkRepoSig.h"
 
45
#include "KpkLicenseAgreement.h"
 
46
#include "KpkIcons.h"
 
47
#include "ProgressView.h"
 
48
#include "ApplicationLauncher.h"
 
49
#include "KpkSimulateModel.h"
 
50
#include "KpkRequirements.h"
 
51
 
 
52
#include "ui_PkTransaction.h"
 
53
 
 
54
class PkTransactionPrivate
 
55
{
 
56
public:
 
57
    QString tid;
 
58
    bool showDetails;
 
59
    bool finished;
 
60
    bool allowDeps;
 
61
    bool onlyTrusted;
 
62
    Transaction::Role role;
 
63
    Transaction::Error error;
 
64
    QString errorDetails;
 
65
    QList<Package> packages;
 
66
    QStringList files;
 
67
    QVector<KService*> applications;
 
68
    KpkSimulateModel *simulateModel;
 
69
    KPixmapSequenceOverlayPainter *busySeq;
 
70
 
 
71
    void clearApplications()
 
72
    {
 
73
        while (!applications.isEmpty()) {
 
74
            delete applications.at(0);
 
75
            applications.remove(0);
 
76
        }
 
77
    }
 
78
};
 
79
 
 
80
PkTransaction::PkTransaction(Transaction *trans, QWidget *parent)
 
81
 : QWidget(parent),
 
82
   m_trans(trans),
 
83
   m_handlingActionRequired(false),
 
84
   m_showingError(false),
 
85
   m_exitStatus(Success),
 
86
   m_status(Transaction::UnknownStatus),
 
87
   ui(new Ui::PkTransaction),
 
88
   d(new PkTransactionPrivate)
 
89
{
 
90
    ui->setupUi(this);
 
91
 
 
92
    d->busySeq = new KPixmapSequenceOverlayPainter(this);
 
93
    d->busySeq->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
 
94
    d->busySeq->setWidget(ui->label);
 
95
    ui->label->clear();
 
96
 
 
97
    d->finished = true; // for sanity we are finished till some transaction is set
 
98
    d->onlyTrusted = true; // for sanity we are trusted till an error is given and the user accepts
 
99
    d->simulateModel = 0;
 
100
 
 
101
//     setButtons(KDialog::Details | KDialog::User1 | KDialog::Cancel);
 
102
//     enableButton(KDialog::Details, false);
 
103
//     button(KDialog::Details)->setCheckable(true);
 
104
    // Setup HIDE custom button
 
105
//     setButtonText(KDialog::User1, i18n("Hide"));
 
106
//     setButtonToolTip(KDialog::User1,
 
107
//                      i18n("Allows you to hide the window whilst keeping the transaction task running."));
 
108
//     setEscapeButton(KDialog::User1);
 
109
 
 
110
    KConfig config("KPackageKit");
 
111
    KConfigGroup transactionGroup(&config, "Transaction");
 
112
    
 
113
    connect(ui->cancelButton, SIGNAL(rejected()), this, SLOT(cancel()));
 
114
 
 
115
    // We need to track when the user close the dialog using the [X] button
 
116
//     connect(this, SIGNAL(finished()), SLOT(finishedDialog()));
 
117
 
 
118
    // after ALL set, lets set the transaction
 
119
    setTransaction(m_trans);
 
120
 
 
121
//     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
 
122
//     setMaximumSize(QWIDGETSIZE_MAX, size().height());
 
123
 
 
124
//     KConfigGroup transactionDialog(&config, "TransactionDialog");
 
125
//     restoreDialogSize(transactionDialog);
 
126
}
 
127
 
 
128
PkTransaction::~PkTransaction()
 
129
{
 
130
//     KConfig config("KPackageKit");
 
131
//     if (isButtonEnabled(KDialog::Details)) {
 
132
//         KConfigGroup transactionGroup(&config, "Transaction");
 
133
//         transactionGroup.writeEntry("ShowDetails", d->showDetails);
 
134
//     }
 
135
//     KConfigGroup transactionDialog(&config, "TransactionDialog");
 
136
//     saveDialogSize(transactionDialog);
 
137
 
 
138
    if (!d->finished) {
 
139
        // We are going to hide the transaction,
 
140
        // which can make the user even close System Settings or KPackageKit
 
141
        // so we call the tray icon to keep watching the transaction so if the
 
142
        // transaction receives some error we can display them
 
143
        QDBusMessage message;
 
144
        message = QDBusMessage::createMethodCall("org.kde.KPackageKitSmartIcon",
 
145
                                                 "/",
 
146
                                                 "org.kde.KPackageKitSmartIcon",
 
147
                                                 QLatin1String("WatchTransaction"));
 
148
        // Use our own cached tid to avoid crashes
 
149
        message << qVariantFromValue(d->tid);
 
150
        QDBusMessage reply = QDBusConnection::sessionBus().call(message);
 
151
        if (reply.type() != QDBusMessage::ReplyMessage) {
 
152
            kWarning() << "Message did not receive a reply";
 
153
        }
 
154
    }
 
155
 
 
156
    // DO NOT disconnect the transaction here,
 
157
    // it might not exist when this happen
 
158
    d->clearApplications();
 
159
    delete d;
 
160
}
 
161
 
 
162
void PkTransaction::hideCancelButton()
 
163
{
 
164
    ui->cancelButton->hide();
 
165
}
 
166
 
 
167
void PkTransaction::installFiles(const QStringList &files)
 
168
{
 
169
    if (Daemon::actions() & Transaction::RoleInstallFiles) {
 
170
        if (Daemon::actions() & Transaction::RoleSimulateInstallFiles) {
 
171
            d->files         = files;
 
172
            d->simulateModel = new KpkSimulateModel(this, d->packages);
 
173
 
 
174
            // Create the simulate transaction and it's model
 
175
            Transaction *trans = new Transaction(this);
 
176
            trans->simulateInstallFiles(files);
 
177
            if (trans->error()) {
 
178
                KMessageBox::sorry(this,
 
179
                                   KpkStrings::daemonError(trans->error()),
 
180
                                   i18n("Failed to simulate file install"));
 
181
//                 taskDone(Transaction::RoleInstallPackages);
 
182
            } else {
 
183
                setTransaction(trans);
 
184
            }
 
185
        } else {
 
186
            installFiles();
 
187
        }
 
188
    } else {
 
189
        KMessageBox::error(this, i18n("Current backend does not support installing files."), i18n("Error"));
 
190
    }
 
191
}
 
192
 
 
193
void PkTransaction::installPackages(const QList<Package> &packages)
 
194
{
 
195
    if (Daemon::actions() & Transaction::RoleInstallPackages) {
 
196
        if (Daemon::actions() & Transaction::RoleSimulateInstallPackages/* &&
 
197
            !(m_flags & HideConfirmDeps)*/) {
 
198
            d->packages      = packages;
 
199
            d->simulateModel = new KpkSimulateModel(this, d->packages);
 
200
 
 
201
            // Create the depends transaction and it's model
 
202
            Transaction *trans = new Transaction(this);
 
203
            trans->simulateInstallPackages(d->packages);
 
204
            if (trans->error()) {
 
205
                KMessageBox::sorry(this,
 
206
                                   KpkStrings::daemonError(trans->error()),
 
207
                                   i18n("Failed to simulate package install"));
 
208
            } else {
 
209
                setTransaction(trans);
 
210
            }
 
211
        } else {
 
212
            installPackages();
 
213
        }
 
214
    } else {
 
215
        KMessageBox::error(this, i18n("Current backend does not support installing packages."), i18n("Error"));
 
216
    }
 
217
}
 
218
 
 
219
void PkTransaction::removePackages(const QList<Package> &packages)
 
220
{
 
221
    if (Daemon::actions() & Transaction::RoleRemovePackages) {
 
222
        if (Daemon::actions() & Transaction::RoleSimulateRemovePackages/* &&
 
223
            !(m_flags & HideConfirmDeps)*/) { //TODO we need admin to lock this down
 
224
            d->packages      = packages;
 
225
            d->simulateModel = new KpkSimulateModel(this, d->packages);
 
226
 
 
227
            // Create the requirements transaction and it's model
 
228
            Transaction *trans = new Transaction(this);
 
229
            trans->simulateRemovePackages(d->packages, AUTOREMOVE);
 
230
            if (trans->error()) {
 
231
                KMessageBox::sorry(this,
 
232
                                   KpkStrings::daemonError(trans->error()),
 
233
                                   i18n("Failed to simulate package removal"));
 
234
            } else {
 
235
                setTransaction(trans);
 
236
            }
 
237
        } else {
 
238
            // As we can't check for requires don't allow deps removal
 
239
            removePackages(false);
 
240
        }
 
241
    } else {
 
242
        KMessageBox::error(this, i18n("The current backend does not support removing packages."), i18n("Error"));
 
243
    }
 
244
}
 
245
 
 
246
void PkTransaction::updatePackages(const QList<Package> &packages)
 
247
{
 
248
    if (Daemon::actions() & Transaction::RoleRemovePackages) {
 
249
        if (Daemon::actions() & Transaction::RoleSimulateUpdatePackages) {
 
250
            d->packages      = packages;
 
251
            d->simulateModel = new KpkSimulateModel(this, d->packages);
 
252
 
 
253
            Transaction *trans = new Transaction(this);
 
254
            trans->simulateUpdatePackages(d->packages);
 
255
            if (trans->error()) {
 
256
                KMessageBox::sorry(this, KpkStrings::daemonError(trans->error()),
 
257
                                i18n("Failed to simulate package update"));
 
258
            } else {
 
259
                setTransaction(trans);
 
260
            }
 
261
        } else {
 
262
            updatePackages();
 
263
        }
 
264
    } else {
 
265
        KMessageBox::error(this, i18n("The current backend does not support updating packages."), i18n("Error"));
 
266
    }
 
267
}
 
268
 
 
269
void PkTransaction::refreshCache()
 
270
{
 
271
    SET_PROXY
 
272
    Transaction *trans = new Transaction(this);
 
273
    trans->refreshCache(true);
 
274
    if (trans->error()) {
 
275
        KMessageBox::sorry(this, KpkStrings::daemonError(trans->error()),
 
276
                           i18n("Failed to refresh package cache"));
 
277
    } else {
 
278
        setTransaction(trans);
 
279
    }
 
280
}
 
281
 
 
282
void PkTransaction::installPackages()
 
283
{
 
284
    SET_PROXY
 
285
    QString socket = "/tmp/kpk_debconf_" + QString::number(QCoreApplication::applicationPid());
 
286
    Transaction *trans = new Transaction(this);
 
287
    trans->setHints("frontend-socket=" + socket);
 
288
    trans->installPackages(d->packages, d->onlyTrusted);
 
289
    if (trans->error()) {
 
290
        KMessageBox::sorry(this,
 
291
                           KpkStrings::daemonError(trans->error()),
 
292
                           i18n("Failed to install package"));
 
293
    } else {
 
294
        setTransaction(trans);
 
295
        setupDebconfDialog(socket);
 
296
    }
 
297
}
 
298
 
 
299
void PkTransaction::installFiles()
 
300
{
 
301
    SET_PROXY
 
302
    QString socket = "/tmp/kpk_debconf_" + QString::number(QCoreApplication::applicationPid());
 
303
    Transaction *trans = new Transaction(this);
 
304
    trans->setHints("frontend-socket=" + socket);
 
305
    trans->installFiles(d->files, d->onlyTrusted);
 
306
    if (trans->error()) {
 
307
        KMessageBox::sorry(this,
 
308
                           KpkStrings::daemonError(trans->error()),
 
309
                           i18np("Failed to install file",
 
310
                                 "Failed to install files",
 
311
                                 d->files.size()));
 
312
    } else {
 
313
        setTransaction(trans);
 
314
        setupDebconfDialog(socket);
 
315
    }
 
316
}
 
317
 
 
318
void PkTransaction::removePackages(bool allow_deps)
 
319
{
 
320
    SET_PROXY
 
321
    QString socket = "/tmp/kpk_debconf_" + QString::number(QCoreApplication::applicationPid());
 
322
    Transaction *trans = new Transaction(this);
 
323
    trans->setHints("frontend-socket=" + socket);
 
324
    trans->removePackages(d->packages, d->allowDeps, AUTOREMOVE);
 
325
    if (trans->error()) {
 
326
        KMessageBox::sorry(this,
 
327
                           KpkStrings::daemonError(trans->error()),
 
328
                           i18n("Failed to remove package"));
 
329
//         taskDone(Transaction::RoleRemovePackages);
 
330
    } else {
 
331
        setTransaction(trans);
 
332
        setupDebconfDialog(socket);
 
333
//         setAllowDeps(allowDeps);
 
334
//         d->transactionDialog->setAllowDeps(allowDeps);
 
335
    }
 
336
}
 
337
 
 
338
void PkTransaction::updatePackages()
 
339
{
 
340
    SET_PROXY
 
341
    QString socket = "/tmp/kpk_debconf_" + QString::number(QCoreApplication::applicationPid());
 
342
    Transaction *trans = new Transaction(this);
 
343
    trans->setHints("frontend-socket=" + socket);
 
344
    trans->updatePackages(d->packages, true);
 
345
    if (trans->error()) {
 
346
        KMessageBox::sorry(this,
 
347
                           KpkStrings::daemonError(trans->error()),
 
348
                           i18n("Failed to update package"));
 
349
//         taskDone(Transaction::RoleRemovePackages);
 
350
    } else {
 
351
        setTransaction(trans);
 
352
        setupDebconfDialog(socket);
 
353
//         d->transactionDialog->setAllowDeps(allowDeps);
 
354
    }
 
355
}
 
356
 
 
357
void PkTransaction::cancel()
 
358
{
 
359
    m_trans->cancel();
 
360
//     m_flags |= CloseOnFinish;
 
361
}
 
362
 
 
363
void PkTransaction::setTransaction(Transaction *trans)
 
364
{
 
365
    if (!trans) {
 
366
        // 0 pointer passed
 
367
        return;
 
368
    }
 
369
 
 
370
    m_trans = trans;
 
371
    Transaction::Role role = trans->role();
 
372
    if (role != Transaction::RoleInstallSignature &&
 
373
        role != Transaction::RoleAcceptEula &&
 
374
        role != Transaction::RoleGetFiles) {
 
375
        // We need to keep the original role for requeuing
 
376
        d->role = role;
 
377
    }
 
378
    d->tid = trans->tid();
 
379
    d->finished = false;
 
380
    d->error = Transaction::UnknownError;
 
381
    d->errorDetails.clear();
 
382
    ui->progressView->clear();
 
383
    d->clearApplications();
 
384
 
 
385
    KConfig config("KPackageKit");
 
386
    KConfigGroup transactionGroup(&config, "Transaction");
 
387
    // enable the Details button just on these roles
 
388
    if (role == Transaction::RoleInstallPackages ||
 
389
        role == Transaction::RoleInstallFiles ||
 
390
        role == Transaction::RoleRemovePackages ||
 
391
        role == Transaction::RoleUpdatePackages ||
 
392
        role == Transaction::RoleUpdateSystem ||
 
393
        role == Transaction::RoleRefreshCache) {
 
394
        // DISCONNECT THIS SIGNAL BEFORE SETTING A NEW ONE
 
395
        if (role == Transaction::RoleRefreshCache) {
 
396
            connect(m_trans, SIGNAL(repoDetail(const QString &, const QString &, bool)),
 
397
                    ui->progressView, SLOT(currentRepo(const QString &, const QString &)));
 
398
            ui->progressView->handleRepo(true);
 
399
        } else {
 
400
            connect(m_trans, SIGNAL(package(const PackageKit::Package &)),
 
401
                ui->progressView, SLOT(currentPackage(const PackageKit::Package &)));
 
402
            ui->progressView->handleRepo(false);
 
403
        }
 
404
        d->showDetails = transactionGroup.readEntry("ShowDetails", false);
 
405
//         enableButton(KDialog::Details, true);
 
406
        if (d->showDetails != ui->progressView->isVisible()) {
 
407
//             slotButtonClicked(KDialog::Details);
 
408
        }
 
409
 
 
410
        d->simulateModel->deleteLater();
 
411
        d->simulateModel = 0;
 
412
    } else {
 
413
        if (role == Transaction::RoleSimulateInstallPackages ||
 
414
            role == Transaction::RoleSimulateInstallFiles ||
 
415
            role == Transaction::RoleSimulateRemovePackages ||
 
416
            role == Transaction::RoleSimulateUpdatePackages) {
 
417
            // DISCONNECT THIS SIGNAL BEFORE SETTING A NEW ONE
 
418
            if (!d->simulateModel) {
 
419
                d->simulateModel = new KpkSimulateModel(this, d->packages);
 
420
            }
 
421
            d->simulateModel->clear();
 
422
            connect(m_trans, SIGNAL(package(const PackageKit::Package &)),
 
423
                    d->simulateModel, SLOT(addPackage(const PackageKit::Package &)));
 
424
        }
 
425
 
 
426
        if (ui->progressView->isVisible()) {
 
427
//             slotButtonClicked(KDialog::Details);
 
428
        }
 
429
//         ui->gridLayout->removeWidget(d->progressView);
 
430
//         enableButton(KDialog::Details, false);
 
431
    }
 
432
 
 
433
    // sets the action icon to be the window icon
 
434
    setWindowIcon(KpkIcons::actionIcon(role));
 
435
 
 
436
    // Sets the kind of transaction
 
437
    emit titleChanged(KpkStrings::action(role));
 
438
//     setCaption(KpkStrings::action(role));
 
439
 
 
440
    // Now sets the last package
 
441
    ui->progressView->currentPackage(m_trans->lastPackage());
 
442
 
 
443
    // sets ui
 
444
    updateUi();
 
445
 
 
446
    // DISCONNECT ALL THESE SIGNALS BEFORE SETTING A NEW ONE
 
447
    connect(m_trans, SIGNAL(finished(PackageKit::Transaction::Exit, uint)),
 
448
            this, SLOT(transactionFinished(PackageKit::Transaction::Exit)));
 
449
    connect(m_trans, SIGNAL(errorCode(PackageKit::Transaction::Error, const QString &)),
 
450
            this, SLOT(errorCode(PackageKit::Transaction::Error, const QString &)));
 
451
    connect(m_trans, SIGNAL(changed()),
 
452
            this, SLOT(updateUi()));
 
453
    connect(m_trans, SIGNAL(eulaRequired(PackageKit::Eula)),
 
454
            this, SLOT(eulaRequired(PackageKit::Eula)));
 
455
    connect(m_trans, SIGNAL(mediaChangeRequired(PackageKit::Transaction::MediaType, const QString &, const QString &)),
 
456
            this, SLOT(mediaChangeRequired(PackageKit::Transaction::MediaType, const QString &, const QString &)));
 
457
    connect(m_trans, SIGNAL(repoSignatureRequired(PackageKit::Signature)),
 
458
            this, SLOT(repoSignatureRequired(PackageKit::Signature)));
 
459
    // DISCONNECT ALL THESE SIGNALS BEFORE SETTING A NEW ONE
 
460
}
 
461
 
 
462
void PkTransaction::unsetTransaction()
 
463
{
 
464
    disconnect(m_trans, SIGNAL(package(const PackageKit::Package &)),
 
465
               d->simulateModel, SLOT(addPackage(const PackageKit::Package &)));
 
466
    disconnect(m_trans, SIGNAL(finished(PackageKit::Transaction::Exit, uint)),
 
467
               this, SLOT(transactionFinished(PackageKit::Transaction::Exit)));
 
468
    disconnect(m_trans, SIGNAL(errorCode(PackageKit::Transaction::Error, const QString &)),
 
469
               this, SLOT(errorCode(PackageKit::Transaction::Error, const QString &)));
 
470
    disconnect(m_trans, SIGNAL(changed()),
 
471
               this, SLOT(updateUi()));
 
472
    disconnect(m_trans, SIGNAL(eulaRequired(PackageKit::Eula)),
 
473
               this, SLOT(eulaRequired(PackageKit::Eula)));
 
474
    disconnect(m_trans, SIGNAL(mediaChangeRequired(PackageKit::Transaction::MediaType, const QString &, const QString &)),
 
475
               this, SLOT(mediaChangeRequired(PackageKit::Transaction::MediaType, const QString &, const QString &)));
 
476
    disconnect(m_trans, SIGNAL(repoSignatureRequired(PackageKit::Signature)),
 
477
               this, SLOT(repoSignatureRequired(PackageKit::Signature)));
 
478
}
 
479
 
 
480
void PkTransaction::requeueTransaction()
 
481
{
 
482
    SET_PROXY
 
483
    Transaction *trans = new Transaction(this);
 
484
    QString socket;
 
485
    socket = "/tmp/kpk_debconf_" + QString::number(QCoreApplication::applicationPid());
 
486
    trans->setHints("frontend-socket=" + socket);
 
487
    switch (d->role) {
 
488
    case Transaction::RoleRemovePackages :
 
489
        trans->removePackages(d->packages, d->allowDeps, AUTOREMOVE);
 
490
        break;
 
491
    case Transaction::RoleInstallPackages :
 
492
        trans->installPackages(d->packages, d->onlyTrusted);
 
493
        break;
 
494
    case Transaction::RoleInstallFiles :
 
495
        trans->installFiles(d->files, d->onlyTrusted);
 
496
        break;
 
497
    case Transaction::RoleUpdatePackages :
 
498
        trans->updatePackages(d->packages, d->onlyTrusted);
 
499
        break;
 
500
    default :
 
501
        setExitStatus(Failed);
 
502
        return;
 
503
    }
 
504
 
 
505
    if (trans->error()) {
 
506
        KMessageBox::sorry(this,
 
507
                           KpkStrings::daemonError(trans->error()),
 
508
                           KpkStrings::action(trans->role()));
 
509
        setExitStatus(Failed);
 
510
    } else {
 
511
        setTransaction(trans);
 
512
    }
 
513
}
 
514
 
 
515
void PkTransaction::updateUi()
 
516
{
 
517
    uint percentage = m_trans->percentage();
 
518
    if (percentage <= 100) {
 
519
        ui->progressBar->setMaximum(100);
 
520
        ui->progressBar->setValue(percentage);
 
521
    } else if (ui->progressBar->maximum() != 0) {
 
522
        ui->progressBar->setMaximum(0);
 
523
        ui->progressBar->reset();
 
524
    }
 
525
 
 
526
    ui->progressView->setSubProgress(m_trans->subpercentage());
 
527
    ui->progressBar->setRemaining(m_trans->remainingTime());
 
528
 
 
529
    // Status & Speed
 
530
    Transaction::Status status = m_trans->status();
 
531
    if (m_status != status) {
 
532
        m_status = status;
 
533
        ui->currentL->setText(KpkStrings::status(status));
 
534
 
 
535
//         kDebug() << KIconLoader::global()->iconPath(KpkIcons::statusAnimation(status), -KIconLoader::SizeLarge);
 
536
        KPixmapSequence sequence = KPixmapSequence(KpkIcons::statusAnimation(status),
 
537
                                                   KIconLoader::SizeLarge);
 
538
        if (sequence.isValid()) {
 
539
            d->busySeq->setSequence(sequence);
 
540
            d->busySeq->start();
 
541
        }
 
542
    } else if (status == Transaction::StatusDownload && m_trans->speed() != 0) {
 
543
        uint speed = m_trans->speed();
 
544
        if (speed) {
 
545
            ui->currentL->setText(i18n("Downloading packages at %1/s",
 
546
                                         KGlobal::locale()->formatByteSize(speed)));
 
547
        }
 
548
    }
 
549
 
 
550
    // check to see if we can cancel
 
551
    bool cancel = m_trans->allowCancel();
 
552
    emit allowCancel(cancel);
 
553
    ui->cancelButton->setEnabled(cancel);
 
554
}
 
555
 
 
556
// Return value: if the error code suggests to try with only_trusted %FALSE
 
557
static bool untrustedIsNeed(Transaction::Error error)
 
558
{
 
559
    switch (error) {
 
560
    case Transaction::ErrorGpgFailure:
 
561
    case Transaction::ErrorBadGpgSignature:
 
562
    case Transaction::ErrorMissingGpgSignature:
 
563
    case Transaction::ErrorCannotInstallRepoUnsigned:
 
564
    case Transaction::ErrorCannotUpdateRepoUnsigned:
 
565
        return true;
 
566
    default:
 
567
        return false;
 
568
    }
 
569
}
 
570
 
 
571
void PkTransaction::errorCode(Transaction::Error error, const QString &details)
 
572
{
 
573
//     kDebug() << "errorCode: " << error << details;
 
574
    d->error = error;
 
575
    d->errorDetails = details;
 
576
    // obvious message, don't tell the user
 
577
    if (m_handlingActionRequired ||
 
578
        error == Transaction::ErrorTransactionCancelled ||
 
579
        error == Transaction::ErrorProcessKill) {
 
580
        return;
 
581
    }
 
582
 
 
583
    if (untrustedIsNeed(error)) {
 
584
        m_handlingActionRequired = true;
 
585
        int ret = KMessageBox::warningYesNo(this,
 
586
                                            i18n("You are about to install unsigned packages that can compromise your system, "
 
587
                                            "as it is impossible to verify if the software came from a trusted "
 
588
                                            "source.\n\nAre you sure you want to proceed with the installation?"),
 
589
                                            i18n("Installing unsigned software"));
 
590
        if (ret == KMessageBox::Yes) {
 
591
            // Set only trusted to false, to do as the user asked
 
592
            d->onlyTrusted = false;
 
593
            requeueTransaction();
 
594
        } else {
 
595
            setExitStatus(Cancelled);
 
596
//             if (m_flags & CloseOnFinish) {
 
597
//                 done(QDialog::Rejected);
 
598
//             }
 
599
        }
 
600
        m_handlingActionRequired = false;
 
601
        return;
 
602
    }
 
603
 
 
604
    // check to see if we are already handlying these errors
 
605
    if (error == Transaction::ErrorNoLicenseAgreement ||
 
606
        error == Transaction::ErrorMediaChangeRequired)
 
607
    {
 
608
        if (m_handlingActionRequired) {
 
609
            return;
 
610
        }
 
611
    }
 
612
 
 
613
    m_showingError = true;
 
614
    KMessageBox::detailedSorry(this,
 
615
                               KpkStrings::errorMessage(error),
 
616
                               QString(details).replace('\n', "<br />"),
 
617
                               KpkStrings::error(error),
 
618
                               KMessageBox::Notify);
 
619
    m_showingError = false;
 
620
 
 
621
    // when we receive an error we are done
 
622
    setExitStatus(Failed);
 
623
    // TODO maybe this should go in the above method
 
624
//     if (m_flags & CloseOnFinish) {
 
625
//         done(QDialog::Rejected);
 
626
//     }
 
627
}
 
628
 
 
629
void PkTransaction::eulaRequired(PackageKit::Eula info)
 
630
{
 
631
    if (m_handlingActionRequired) {
 
632
        // if its true means that we alread passed here
 
633
        m_handlingActionRequired = false;
 
634
        return;
 
635
    } else {
 
636
        m_handlingActionRequired = true;
 
637
    }
 
638
 
 
639
    QPointer<KpkLicenseAgreement> frm = new KpkLicenseAgreement(info, true, this);
 
640
    if (frm->exec() == KDialog::Yes) {
 
641
        m_handlingActionRequired = false;
 
642
        Transaction *trans = new Transaction(this);
 
643
        trans->acceptEula(info.id);
 
644
        if (trans->error()) {
 
645
            KMessageBox::sorry(this,
 
646
                               KpkStrings::daemonError(trans->error()),
 
647
                               i18n("Failed to accept EULA"));
 
648
        } else {
 
649
            setTransaction(trans);
 
650
        }
 
651
    } else {
 
652
        setExitStatus(Cancelled);
 
653
        m_handlingActionRequired = false;
 
654
    }
 
655
    delete frm;
 
656
}
 
657
 
 
658
void PkTransaction::mediaChangeRequired(Transaction::MediaType type, const QString &id, const QString &text)
 
659
{
 
660
    Q_UNUSED(id)
 
661
 
 
662
    m_handlingActionRequired = true;
 
663
    int ret = KMessageBox::questionYesNo(this,
 
664
                                         KpkStrings::mediaMessage(type, text),
 
665
                                         i18n("A media change is required"),
 
666
                                         KStandardGuiItem::cont(),
 
667
                                         KStandardGuiItem::cancel());
 
668
    m_handlingActionRequired = false;
 
669
 
 
670
    // if the user clicked continue we got yes
 
671
    if (ret == KMessageBox::Yes) {
 
672
        requeueTransaction();
 
673
    } else {
 
674
        setExitStatus(Cancelled);
 
675
    }
 
676
}
 
677
 
 
678
void PkTransaction::repoSignatureRequired(PackageKit::Signature info)
 
679
{
 
680
    if (m_handlingActionRequired) {
 
681
        // if its true means that we alread passed here
 
682
        m_handlingActionRequired = false;
 
683
        return;
 
684
    } else {
 
685
        m_handlingActionRequired = true;
 
686
    }
 
687
 
 
688
    QPointer<KpkRepoSig> frm = new KpkRepoSig(info, true, this);
 
689
    frm->exec();
 
690
    if (frm && frm->result() == KDialog::Yes) {
 
691
        m_handlingActionRequired = false;
 
692
        Transaction *trans = new Transaction(this);
 
693
        trans->installSignature(info);
 
694
        if (trans->error()) {
 
695
            KMessageBox::sorry(this,
 
696
                               KpkStrings::daemonError(trans->error()),
 
697
                               i18n("Failed to install signature"));
 
698
        } else {
 
699
            setTransaction(trans);
 
700
        }
 
701
    } else {
 
702
        setExitStatus(Cancelled);
 
703
        m_handlingActionRequired = false;
 
704
    }
 
705
    delete frm;
 
706
}
 
707
 
 
708
void PkTransaction::files(const PackageKit::Package &package, const QStringList &files)
 
709
{
 
710
    Q_UNUSED(package)
 
711
    foreach (const QString &desktop, files.filter(".desktop")) {
 
712
        // we create a new KService because findByDestopPath
 
713
        // might fail because the Sycoca database is not up to date yet.
 
714
        KService *service = new KService(desktop);
 
715
        if (service->isApplication() &&
 
716
           !service->noDisplay() &&
 
717
           !service->exec().isEmpty())
 
718
        {
 
719
            d->applications << service;
 
720
        }
 
721
    }
 
722
}
 
723
 
 
724
void PkTransaction::transactionFinished(Transaction::Exit status)
 
725
{
 
726
    Transaction *trans = qobject_cast<Transaction*>(sender());
 
727
    Transaction::Role role = trans->role();
 
728
    KpkRequirements *requires = 0;
 
729
 
 
730
//     kDebug() << status;
 
731
    d->finished = true;
 
732
    switch(status) {
 
733
    case Transaction::ExitSuccess :
 
734
        ui->progressBar->setMaximum(100);
 
735
        ui->progressBar->setValue(100);
 
736
 
 
737
        // If the simulate model exists we were simulating
 
738
        if (d->simulateModel) {
 
739
            if (d->simulateModel->rowCount() > 0) {
 
740
                requires = new KpkRequirements(d->simulateModel, this);
 
741
                connect(requires, SIGNAL(rejected()), this, SLOT(reject()));
 
742
                requires->show();
 
743
            }
 
744
 
 
745
            switch (role) {
 
746
            case Transaction::RoleSimulateInstallPackages:
 
747
                if (requires) {
 
748
                    connect(requires, SIGNAL(accepted()), this, SLOT(installPackages()));
 
749
                } else {
 
750
                    installPackages();
 
751
                }
 
752
                return;
 
753
            case Transaction::RoleSimulateRemovePackages:
 
754
                if (requires) {
 
755
                    connect(requires, SIGNAL(accepted()), this, SLOT(removePackages()));
 
756
                } else {
 
757
                    // As there was no requires don't allow deps removal
 
758
                    removePackages(false);
 
759
                }
 
760
                return;
 
761
            case Transaction::RoleSimulateUpdatePackages:
 
762
                if (requires) {
 
763
                    connect(requires, SIGNAL(accepted()), this, SLOT(updatePackages()));
 
764
                } else {
 
765
                    updatePackages();
 
766
                }
 
767
                return;
 
768
            case Transaction::RoleSimulateInstallFiles:
 
769
                if (requires) {
 
770
                    connect(requires, SIGNAL(accepted()), this, SLOT(installFiles()));
 
771
                } else {
 
772
                    installFiles();
 
773
                }
 
774
                return;
 
775
            default:
 
776
                break;
 
777
            }
 
778
        }
 
779
 
 
780
        if (role != Transaction::RoleInstallSignature &&
 
781
            role != Transaction::RoleAcceptEula &&
 
782
            role != Transaction::RoleGetFiles) {
 
783
            KConfig config("KPackageKit");
 
784
            KConfigGroup transactionGroup(&config, "Transaction");
 
785
            if ((role == Transaction::RoleInstallPackages ||
 
786
                 role == Transaction::RoleInstallFiles) &&
 
787
                transactionGroup.readEntry("ShowApplicationLauncher", true) &&
 
788
                Daemon::actions() & Transaction::RoleGetFiles) {
 
789
                // Let's try to find some desktop files'
 
790
                Transaction *transaction = new Transaction(this);
 
791
                transaction->getFiles(d->packages);
 
792
                if (!transaction->error()) {
 
793
                    setTransaction(transaction);
 
794
                    connect(transaction, SIGNAL(files(const PackageKit::Package &, const QStringList &)),
 
795
                            this, SLOT(files(const PackageKit::Package &, const QStringList &)));
 
796
                    return; // avoid the exit code
 
797
                }
 
798
            }
 
799
            setExitStatus(Success);
 
800
        } else if (role == Transaction::RoleGetFiles) {
 
801
            if (!d->applications.isEmpty()) {
 
802
                ApplicationLauncher *launcher = new ApplicationLauncher(d->applications, this);
 
803
                launcher->exec();
 
804
            }
 
805
            setExitStatus(Success);
 
806
        } else {
 
807
            d->finished = false;
 
808
            requeueTransaction();
 
809
        }
 
810
        break;
 
811
    case Transaction::ExitCancelled :
 
812
        ui->progressBar->setMaximum(100);
 
813
        ui->progressBar->setValue(100);
 
814
        // Avoid crash in case we are showing an error
 
815
        if (!m_showingError) {
 
816
            setExitStatus(Cancelled);
 
817
        }
 
818
        break;
 
819
    case Transaction::ExitFailed :
 
820
        kDebug() << "Failed.";
 
821
        if (!m_handlingActionRequired && !m_showingError) {
 
822
            ui->progressBar->setMaximum(0);
 
823
            ui->progressBar->reset();
 
824
            kDebug() << "Yep, we failed.";
 
825
            setExitStatus(Failed);
 
826
        }
 
827
        break;
 
828
    case Transaction::ExitKeyRequired :
 
829
    case Transaction::ExitEulaRequired :
 
830
    case Transaction::ExitMediaChangeRequired :
 
831
    case Transaction::ExitNeedUntrusted :
 
832
        kDebug() << "finished KeyRequired or EulaRequired: " << status;
 
833
        ui->currentL->setText(KpkStrings::status(Transaction::StatusSetup));
 
834
        if (!m_handlingActionRequired) {
 
835
            setExitStatus(Failed);
 
836
        }
 
837
        break;
 
838
    default :
 
839
        ui->progressBar->setMaximum(100);
 
840
        ui->progressBar->setValue(100);
 
841
        kDebug() << "finished default" << status;
 
842
//         KDialog::slotButtonClicked(KDialog::Close);
 
843
        setExitStatus(Failed);
 
844
        break;
 
845
    }
 
846
    // if we're not showing an error or don't have the
 
847
    // CloseOnFinish flag don't close the dialog
 
848
    //TODO !!!!!!!!!
 
849
//     if (m_flags & CloseOnFinish && !m_handlingActionRequired && !m_showingError) {
 
850
// //         kDebug() << "CloseOnFinish && !m_handlingActionRequired && !m_showingError";
 
851
//         done(QDialog::Rejected);
 
852
//         deleteLater();
 
853
//     }
 
854
}
 
855
 
 
856
PkTransaction::ExitStatus PkTransaction::exitStatus() const
 
857
{
 
858
    return m_exitStatus;
 
859
}
 
860
 
 
861
bool PkTransaction::isFinished() const
 
862
{
 
863
    return d->finished;
 
864
}
 
865
 
 
866
void PkTransaction::setExitStatus(PkTransaction::ExitStatus status)
 
867
{
 
868
    kDebug() << status;
 
869
    m_exitStatus = status;
 
870
    emit finished(status);
 
871
}
 
872
 
 
873
void PkTransaction::reject()
 
874
{
 
875
    d->finished = true;
 
876
    setExitStatus(Cancelled);
 
877
}
 
878
 
 
879
QString PkTransaction::tid() const
 
880
{
 
881
    return d->tid;
 
882
}
 
883
 
 
884
bool PkTransaction::allowDeps() const
 
885
{
 
886
    return d->allowDeps;
 
887
}
 
888
 
 
889
bool PkTransaction::onlyTrusted() const
 
890
{
 
891
    return d->onlyTrusted;
 
892
}
 
893
 
 
894
Transaction::Role PkTransaction::role() const
 
895
{
 
896
    return d->role;
 
897
}
 
898
 
 
899
Transaction::Error PkTransaction::error() const
 
900
{
 
901
    return d->error;
 
902
}
 
903
 
 
904
QString PkTransaction::errorDetails() const
 
905
{
 
906
    return d->errorDetails;
 
907
}
 
908
 
 
909
QList<Package> PkTransaction::packages() const
 
910
{
 
911
    return d->packages;
 
912
}
 
913
 
 
914
QStringList PkTransaction::files() const
 
915
{
 
916
    return d->files;
 
917
}
 
918
 
 
919
KpkSimulateModel* PkTransaction::simulateModel() const
 
920
{
 
921
    return d->simulateModel;
 
922
}
 
923
 
 
924
void PkTransaction::setAllowDeps(bool allowDeps)
 
925
{
 
926
    d->allowDeps = allowDeps;
 
927
}
 
928
 
 
929
void PkTransaction::setPackages(const QList<Package> &packages)
 
930
{
 
931
    d->packages = packages;
 
932
}
 
933
 
 
934
void PkTransaction::setFiles(const QStringList &files)
 
935
{
 
936
    d->files = files;
 
937
}
 
938
 
 
939
void PkTransaction::setupDebconfDialog(const QString &tid)
 
940
{
 
941
#ifdef HAVE_DEBCONFKDE
 
942
    QDBusMessage message;
 
943
    message = QDBusMessage::createMethodCall("org.kde.ApperSentinel",
 
944
                                             "/",
 
945
                                             "org.kde.ApperSentinel",
 
946
                                             QLatin1String("SetupDebconfDialog"));
 
947
    // Use our own cached tid to avoid crashes
 
948
    message << qVariantFromValue(tid);
 
949
    message << qVariantFromValue(static_cast<uint>(effectiveWinId()));
 
950
    QDBusMessage reply = QDBusConnection::sessionBus().call(message);
 
951
    if (reply.type() != QDBusMessage::ReplyMessage) {
 
952
        kWarning() << "Message did not receive a reply";
 
953
    }
 
954
#else
 
955
    Q_UNUSED(tid)
 
956
#endif //HAVE_DEBCONFKDE
 
957
}
 
958
 
 
959
#include "PkTransaction.moc"