syncoperation.cpp 20.1 KB
Newer Older
Lisa's avatar
Lisa committed
1
/* This file is part of the Chakra project
Lukas Appelhans's avatar
Lukas Appelhans committed
2 3 4 5 6 7 8 9 10 11

   Copyright (C) 2010 Lukas Appelhans

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
*/

#include "syncoperation.h"
Lisa's avatar
Lisa committed
12
#include "queueoperation.h"
Lukas Appelhans's avatar
Lukas Appelhans committed
13

Lukas Appelhans's avatar
Lukas Appelhans committed
14 15 16 17
#include <akabeibackend.h>
#include <akabeipackage.h>
#include <akabeidatabase.h>
#include <akabeiclientbackend.h>
18
#include <akabeiconfig.h>
Lisa's avatar
Lisa committed
19 20 21 22 23 24
#include <akabeigroup.h>
#include <akabeiclientqueue.h>
#include <akabeiclienttransactionhandler.h>
#include <akabeioperation.h>
#include <akabeioperationrunner.h>

Lukas Appelhans's avatar
Lukas Appelhans committed
25
#include <QTextStream>
Lukas Appelhans's avatar
Lukas Appelhans committed
26
#include <QDateTime>
27
#include <QCoreApplication>
28 29
#include <QFile>
#include <QDir>
Lisa's avatar
Lisa committed
30 31 32 33

#include <klocale.h>
#include <kio/global.h>
#include <kdebug.h>
34
#include <kio/global.h>
Lukas Appelhans's avatar
Lukas Appelhans committed
35

Lisa's avatar
Lisa committed
36
#include <iostream>
Lukas Appelhans's avatar
Lukas Appelhans committed
37

Lisa's avatar
Lisa committed
38 39 40 41
SyncOperation::SyncOperation(QObject* parent)
  : QObject(parent)
  , m_maxDbNameLenght(0)
{}
Lukas Appelhans's avatar
Lukas Appelhans committed
42

Lisa's avatar
Lisa committed
43
SyncOperation::~SyncOperation() {}
Lukas Appelhans's avatar
Lukas Appelhans committed
44

Lukas Appelhans's avatar
Lukas Appelhans committed
45
void SyncOperation::start(QList<APM::Operation> operations, QMultiHash<APM::Operation, QString> options, QStringList args)
Lukas Appelhans's avatar
Lukas Appelhans committed
46
{
Lisa's avatar
Lisa committed
47 48 49 50
    APM::Operation operation = operations.takeFirst();
    QTextStream err(stderr);
    Akabei::Backend *backend = Akabei::Backend::instance();
    
Lukas Appelhans's avatar
Lukas Appelhans committed
51 52 53
    m_operations = operations;
    m_options = options;
    m_args = args;
Lisa's avatar
Lisa committed
54 55 56 57 58 59 60 61 62 63 64 65
    
    switch(operation) {
        case APM::Search:
        {
            if (args.isEmpty()) {
                err << "akabei: An argument is needed." << endl;
                return;
            }
            
            connect(backend, SIGNAL(queryPackagesCompleted(QUuid, QList<Akabei::Package*>)), SLOT(searchResult(QUuid,QList<Akabei::Package*>)));
            backend->searchPackages(args);
            break;
Lukas Appelhans's avatar
Lukas Appelhans committed
66
        }
Lisa's avatar
Lisa committed
67 68 69 70 71 72 73 74 75 76
        
        case APM::ListRepo:
        {
            if (args.isEmpty()) {
                err << "akabei: An argument is needed." << endl;
                return;
            }
            
            listRepo(args.first());
            break;
77
        }
Lisa's avatar
Lisa committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
            
        case APM::ShowInformation:
        {
            if (args.isEmpty()) {
                err << "akabei: An argument is needed" << endl;
                return;
            }
            
            connect(backend, SIGNAL(queryPackagesCompleted(QUuid,QList<Akabei::Package*>)), SLOT(showInformation(QUuid,QList<Akabei::Package*>)));
            backend->searchPackages(args);
            break;
        }
            
        case APM::ShowPackagesOfGroup:
        {
            if (args.isEmpty()) {
                err << "akabei: An argument is needed" << endl;
                return;
            }
            
            connect(backend, SIGNAL(queryGroupsCompleted(QUuid,QList<Akabei::Group*>)), SLOT(showGroup(QUuid,QList<Akabei::Group*>)));
            backend->queryGroups("SELECT * FROM groups WHERE name LIKE \"" + args.first() + "\"");
            break;
        }
            
        case APM::UpdateDatabases:
        {
            if (AkabeiClient::Backend::instance()->databases().isEmpty()) {
                return;
            }
            
            QTextStream out(stdout);
            out << i18n("Starting database update") << endl;
        
            foreach (AkabeiClient::DatabaseHandler* db, AkabeiClient::Backend::instance()->databases()) {
                if (db->name().length() > m_maxDbNameLenght)
                    m_maxDbNameLenght = db->name().length();
            }
            m_currentDatabasePos = 0;
            updateNextDatabase();
            break;
        }
        
        case APM::UpdateSystem:           
        {
            QStringList locals;
            foreach (Akabei::Package *p, Akabei::Backend::instance()->localDatabase()->packages()) {
                locals << p->name();
            }
            
            connect(backend, SIGNAL(queryPackagesCompleted(QUuid,QList<Akabei::Package*>)), SLOT(upgrade(QUuid,QList<Akabei::Package*>)));
            queryId = backend->searchPackages(locals);
            break;
        }
        
        case APM::Install:
        {
            if (args.isEmpty()) {
                err << "akabei: An argument is needed." << endl;
            }
            
            connect(backend, SIGNAL(queryPackagesCompleted(QUuid,QList<Akabei::Package*>)), SLOT(install(QUuid,QList<Akabei::Package*>)));
            queryId = backend->searchPackages(args);
            break;
        }
        
        default:
        {
            err << "akabei: No operation specified." << endl;
            QCoreApplication::instance()->quit();
            return;
149 150 151 152
        }
    }
}

Lukas Appelhans's avatar
Lukas Appelhans committed
153
void SyncOperation::upgrade(QUuid uuid, QList< Akabei::Package* > packages)
154
{
Lisa's avatar
Lisa committed
155
    if (packages.isEmpty() || queryId != uuid) {
Lukas Appelhans's avatar
Lukas Appelhans committed
156
        return;
Lisa's avatar
Lisa committed
157 158 159
    }
    
    QHash<QString, QList<Akabei::Package*> > mappedpkgs;
160
    foreach (Akabei::Package * pkg, packages) {
Lisa's avatar
Lisa committed
161
        mappedpkgs[pkg->name()].append(pkg);
162
    }
Lisa's avatar
Lisa committed
163
    
164
    QList<Akabei::Package*> toBeUpgraded;
Lisa's avatar
Lisa committed
165 166 167
    foreach (const QString &pkg, mappedpkgs.keys()) {
        QList<Akabei::Package*> candidates = mappedpkgs[pkg];
        
168 169 170
        if (!candidates.isEmpty()) {
            QMap<Akabei::Package::Version, Akabei::Package*> versions;
            Akabei::Package * local = 0;
Lisa's avatar
Lisa committed
171
            
172
            foreach (Akabei::Package* p, candidates) {
Lisa's avatar
Lisa committed
173
                if (p->database() == Akabei::Backend::instance()->localDatabase()) {
174
                    local = p;
Lisa's avatar
Lisa committed
175
                } else {
176
                    versions[p->version()] = p;
Lisa's avatar
Lisa committed
177
                }
178
            }
Lisa's avatar
Lisa committed
179 180 181
            
            /* Something is wrong */
            if (!local) {
182
                continue;
Lisa's avatar
Lisa committed
183 184
            }
           
185
            if (!versions.isEmpty() && versions.values().last()->version() > local->version()) {
Lukas Appelhans's avatar
Lukas Appelhans committed
186
                toBeUpgraded << versions.values().last();
187 188 189
            }
        }
    }
Lisa's avatar
Lisa committed
190
    
Lukas Appelhans's avatar
Lukas Appelhans committed
191 192 193
    if (toBeUpgraded.isEmpty()) {
        return;
    }
Lisa's avatar
Lisa committed
194
    
195 196 197
    QueueOperation *op = new QueueOperation(m_operations, m_options, this);
    op->start(AkabeiClient::Update, toBeUpgraded);
    connect(op, SIGNAL(finished()), QCoreApplication::instance(), SLOT(quit()));
198 199
}

Lukas Appelhans's avatar
Lukas Appelhans committed
200
void SyncOperation::install(QUuid uuid, QList< Akabei::Package* > packages)
201
{
Lisa's avatar
Lisa committed
202
    if (queryId != uuid) {
Lukas Appelhans's avatar
Lukas Appelhans committed
203
        return;
Lisa's avatar
Lisa committed
204 205
    }
   
Lukas Appelhans's avatar
Lukas Appelhans committed
206
    disconnect(Akabei::Backend::instance(), SIGNAL(queryPackagesCompleted(QUuid,QList<Akabei::Package*>)), this, SLOT(install(QUuid,QList<Akabei::Package*>)));
Lisa's avatar
Lisa committed
207
    
Lukas Appelhans's avatar
Lukas Appelhans committed
208
    //FIXME: Cleanup and show all the packages and what is going to be done with them!
209
    QTextStream out(stdout);
Lisa's avatar
Lisa committed
210 211
    QTextStream err(stderr);
    
212
    QMap<QString, Akabei::Package*> toBeInstalled;
213 214
    QMap<QString, Akabei::Package*> toBeUpgraded;
    QMap<QString, Akabei::Package*> toBeReinstalled;
215
    QMap<QString, Akabei::Package*> local;
Lisa's avatar
Lisa committed
216
    
217
    foreach (Akabei::Package * pkg, packages) {
218
        if (pkg->database() == Akabei::Backend::instance()->localDatabase()) {
219
            local[pkg->name()] = pkg;
220 221 222
            packages.removeAll(pkg);
        }
    }
Lisa's avatar
Lisa committed
223
    
224
    if (packages.isEmpty()) {
Lisa's avatar
Lisa committed
225 226
        err << i18n("No appropriate packages found") << endl;
        err.flush();
227
        return;
228
    }
Lisa's avatar
Lisa committed
229
    
230
    foreach (Akabei::Package * pkg, packages) {
231 232 233 234 235 236 237 238 239 240 241 242
        if (toBeInstalled.contains(pkg->name()) && toBeInstalled[pkg->name()]->version() < pkg->version()) {
            toBeInstalled[pkg->name()] = pkg;
        } else if (toBeUpgraded.contains(pkg->name()) && toBeUpgraded[pkg->name()]->version() < pkg->version()) {
            toBeUpgraded[pkg->name()] = pkg;
        } else if (toBeReinstalled.contains(pkg->name()) && toBeReinstalled[pkg->name()]->version() < pkg->version()) {
            toBeReinstalled.remove(pkg->name());
            toBeUpgraded[pkg->name()] = pkg;
        } else if (local.contains(pkg->name())) {
            if (local[pkg->name()]->version() == pkg->version()) {
                toBeReinstalled[pkg->name()] = pkg;
            } else if (local[pkg->name()]->version() < pkg->version()) {
                toBeUpgraded[pkg->name()] = pkg;
Lukas Appelhans's avatar
Lukas Appelhans committed
243
            }
244 245
        } else {
            toBeInstalled[pkg->name()] = pkg;
246
        }
Lisa's avatar
Lisa committed
247

248
    }
Lisa's avatar
Lisa committed
249

250 251 252 253
    if (toBeInstalled.isEmpty() && toBeUpgraded.isEmpty() && toBeReinstalled.isEmpty()) {
        out << i18n("No appropriate packages found") << endl;
        out.flush();
        QCoreApplication::instance()->quit();
254
        return;
255
    }
Lisa's avatar
Lisa committed
256
    
257 258 259
    if (!toBeReinstalled.isEmpty() || !toBeUpgraded.isEmpty()) {
        Akabei::Package::List pkgs = toBeReinstalled.values();
        pkgs << toBeUpgraded.values();
Lisa's avatar
Lisa committed
260
        
261 262 263 264
        if (pkgs.count() == 1) { //It's only one package
            Akabei::Package * pkg = pkgs.first();
            out << i18n("The following package was already found on your system: ")
                << pkg->name() << " (" << local[pkg->name()]->version().toByteArray() << ")" << endl;
Lisa's avatar
Lisa committed
265
            
266 267 268 269 270 271 272
            if (!toBeReinstalled.isEmpty()) {
                out << i18n("Do you want to reinstall it?[Y/n]");
            } else {
                out << i18n("Do you want to upgrade it to version %1?[Y/n]").arg(QString(pkg->version().toByteArray()));
            }
        } else { //Multiple packages
            out << i18n("Some packages were already found on your system.") << endl;
Lisa's avatar
Lisa committed
273
            
274 275
            if (!toBeUpgraded.isEmpty()) {
                out << i18n("The following packages are going to be upgraded:");
Lisa's avatar
Lisa committed
276
                
277 278 279 280 281 282 283 284
                foreach (Akabei::Package * p, toBeUpgraded.values()) {
                    out << " " << p->name() << " (" << local[p->name()]->version().toByteArray().data() << " -> " << p->version().toByteArray() << ")";
                    if (p != toBeUpgraded.values().last())
                        out << ",";
                    else
                        out << endl;
                }
            }
Lisa's avatar
Lisa committed
285
            
286 287
            if (!toBeReinstalled.isEmpty()) {
                out << i18n("The following packages are going to be reinstalled:");
Lisa's avatar
Lisa committed
288
                
289 290 291 292 293 294 295 296 297 298 299
                foreach (Akabei::Package * p, toBeReinstalled.values()) {
                    out << " " << p->name() << " (" << p->version().toByteArray().data() << ")";
                    if (p != toBeReinstalled.values().last())
                        out << ",";
                    else
                        out << endl;
                }
            }
            out << i18n("Do you want to continue?[Y/n]");
        }
        out.flush();
300 301 302

        std::string input;
        getline(std::cin, input);
303 304
        if (!input.empty() && input != i18n("y").toStdString()) {
            QCoreApplication::instance()->quit();
305
            return;
306
        }
307 308
    }

309
    QueueOperation *op = new QueueOperation(m_operations, m_options, this);
310
    op->start(AkabeiClient::Install, toBeInstalled.values() + toBeUpgraded.values() + toBeReinstalled.values());
311
    connect(op, SIGNAL(finished()), QCoreApplication::instance(), SLOT(quit()));
312 313
}

Lukas Appelhans's avatar
Lukas Appelhans committed
314 315
void SyncOperation::searchResult(QUuid , QList< Akabei::Package* > packages)
{
316 317
    if (packages.isEmpty()) {
        QCoreApplication::instance()->quit();
Lukas Appelhans's avatar
Lukas Appelhans committed
318
        return;
319
    }
Lisa's avatar
Lisa committed
320
    
Lukas Appelhans's avatar
Lukas Appelhans committed
321
    QTextStream out(stdout);
Lisa's avatar
Lisa committed
322
    
Lukas Appelhans's avatar
Lukas Appelhans committed
323 324 325
    foreach (Akabei::Package * p, packages) {
        if (p->database() == Akabei::Backend::instance()->localDatabase())
            continue;
Lisa's avatar
Lisa committed
326
        
Lukas Appelhans's avatar
Lukas Appelhans committed
327
        bool installed = !Akabei::Backend::instance()->localDatabase()->queryPackages("SELECT * FROM packages WHERE name=\"" + p->name() + "\" AND version=\"" + p->version().toByteArray() + "\"").isEmpty();
Lukas Appelhans's avatar
Lukas Appelhans committed
328 329 330 331 332 333 334
        AkabeiClient::DatabaseHandler * db = 0;
        foreach (AkabeiClient::DatabaseHandler *database, AkabeiClient::Backend::instance()->databases()) {
            if (database->database() == p->database()) {
                db = database;
                break;
            }
        }
Lisa's avatar
Lisa committed
335
        
Lukas Appelhans's avatar
Lukas Appelhans committed
336 337
        if (!db)
            continue;
Lisa's avatar
Lisa committed
338
        
Lukas Appelhans's avatar
Lukas Appelhans committed
339 340 341
        out << db->name() << '/' << p->name() << ' ' << p->version().toByteArray().data();
        if (installed)
            out << ' ' << i18n("[Installed]");
Lisa's avatar
Lisa committed
342
        
Lukas Appelhans's avatar
Lukas Appelhans committed
343 344 345
        out << endl;
        out << "    " << p->description() << endl;
    }
Lisa's avatar
Lisa committed
346
    
Lukas Appelhans's avatar
Lukas Appelhans committed
347
    out.flush();
Lisa's avatar
Lisa committed
348
    nextOperation();
Lukas Appelhans's avatar
Lukas Appelhans committed
349
}
Lukas Appelhans's avatar
Lukas Appelhans committed
350

Lukas Appelhans's avatar
Lukas Appelhans committed
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
void SyncOperation::listRepo(const QString &repo)
{
    AkabeiClient::DatabaseHandler * db = 0;
    foreach (AkabeiClient::DatabaseHandler * database, AkabeiClient::Backend::instance()->databases()) {
        if (database->name() == repo) {
            db = database;
            break;
        }
    }
    if (!db)
        return;
    QTextStream out(stdout);
    foreach (Akabei::Package * pkg, db->database()->packages()) {
        Akabei::Package::List installed = Akabei::Backend::instance()->localDatabase()->queryPackages("SELECT * FROM packages WHERE Name LIKE \"" + pkg->name() + "\"");
        out << db->name() << ' ' << pkg->name() << ' ' << pkg->version().toByteArray().data();
        if (!installed.isEmpty()) {
            if (installed.first()->version() == pkg->version())
                out << ' ' << i18n("[Installed]");
            else
                out << ' ' << i18n("[Installed: %1]", installed.first()->version().toByteArray().data());
        }
        out << endl;
    }
    out.flush();
Lisa's avatar
Lisa committed
375
    nextOperation();
Lukas Appelhans's avatar
Lukas Appelhans committed
376 377
}

Lukas Appelhans's avatar
Lukas Appelhans committed
378 379
void SyncOperation::showInformation(QUuid,QList<Akabei::Package*> packages)
{
Lisa's avatar
Lisa committed
380
    if (packages.isEmpty()) {
Lukas Appelhans's avatar
Lukas Appelhans committed
381
        return;
Lisa's avatar
Lisa committed
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
    }
    
    /*
     * If a package is present more than one time, it means it's on the local db too.
     * Take the local package only when no other choice is present.
     */
    QHash<QString, Akabei::Package *> mappedpkgs;
    foreach (Akabei::Package *p, packages) {
        mappedpkgs[p->name()] = p;
    }
    packages.clear();
    
    foreach (const QString& name, mappedpkgs.keys()) {
        if (mappedpkgs.count(name) > 1) {
            foreach (Akabei::Package *p, mappedpkgs.values(name)) {
                if (p->database() != Akabei::Backend::instance()->localDatabase()) {
                    packages << p;
                }
            }
        } else {
            packages << mappedpkgs[name];
        }
    }
    
Lukas Appelhans's avatar
Lukas Appelhans committed
406
    QTextStream out(stdout);
Lisa's avatar
Lisa committed
407 408
    
    /* TODO: discover how to disable these features: reset() doesn't work */
Lukas Appelhans's avatar
Lukas Appelhans committed
409 410
    out.setFieldWidth(30);
    out.setFieldAlignment(QTextStream::AlignLeft);
Lisa's avatar
Lisa committed
411 412 413 414 415 416 417 418 419
    
    /* Prints the information for every package */
    foreach (Akabei::Package *pkg, packages) {
        AkabeiClient::DatabaseHandler * db = 0;
        foreach (AkabeiClient::DatabaseHandler * database, AkabeiClient::Backend::instance()->databases()) {
            if (database->database() == pkg->database()) {
                db = database;
                break;
            }
Lukas Appelhans's avatar
Lukas Appelhans committed
420
        }
Lisa's avatar
Lisa committed
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
        
        if (db) {
            out << i18n("Repository") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << db->name() << endl;
        } else {
            kDebug() << pkg->database()->name();
        }
        
        out << i18n("Name") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->name() << endl;
        out << i18n("Version") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << QString(pkg->version().toByteArray().data()) << endl;
        out << i18n("URL") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->url().toString() << endl;
        out << i18n("Licenses") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->license() << endl;
        QStringList groups;
        foreach (Akabei::Group * g, pkg->groups())
            groups << g->name();
        out << i18n("Groups") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << groups.join(" ") << endl;
        out << i18n("Provides") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->provides().join(" ") << endl;
        out << i18n("Depends on") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->dependencies().join(" ") << endl;
        out << i18n("Optional dependencies") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->optionalDependencies().join(" ") << endl;
        //out << i18n("Required by:") << pkg->
        out << i18n("Replaces") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->replaces().join(" ") << endl;
        out << i18n("Installation size") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << KIO::convertSize(pkg->size()) << endl;
        out << i18n("Packager") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->packager() << endl;
        out << i18n("Architecture") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->arch() << endl;
        out << i18n("Creation time") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->buildDate().toString() << endl;
        out << i18n("MD5 sum") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->md5sum().data() << endl;
        out << i18n("Description") << qSetFieldWidth(2) << ":" << qSetFieldWidth(20) << pkg->description() << endl << endl;
        out.flush();
Lukas Appelhans's avatar
Lukas Appelhans committed
448
    }
Lisa's avatar
Lisa committed
449 450 451
    
    out.reset();
    nextOperation();
Lukas Appelhans's avatar
Lukas Appelhans committed
452 453
}

Lukas Appelhans's avatar
Lukas Appelhans committed
454 455 456
void SyncOperation::showGroup(QUuid uuid,QList<Akabei::Group*> groups)
{
    Q_UNUSED(uuid)
Lisa's avatar
Lisa committed
457 458
    
    if (groups.isEmpty()) {
Lukas Appelhans's avatar
Lukas Appelhans committed
459
        return;
Lisa's avatar
Lisa committed
460
    }
Lukas Appelhans's avatar
Lukas Appelhans committed
461 462 463 464
    Akabei::Group * group = groups.first();
    
    QTextStream out(stdout);
    QMap<QString, Akabei::Package*> sorted;
Lisa's avatar
Lisa committed
465 466
    
    foreach (Akabei::Package * pkg, group->packages()) {
Lukas Appelhans's avatar
Lukas Appelhans committed
467
        sorted[pkg->name()] = pkg;
Lisa's avatar
Lisa committed
468 469 470
    }
    
    foreach (Akabei::Package * pkg, sorted.values()) {
Lukas Appelhans's avatar
Lukas Appelhans committed
471
        out << group->name() << ' ' << pkg->name() << endl;
Lisa's avatar
Lisa committed
472 473
    }
    
Lukas Appelhans's avatar
Lukas Appelhans committed
474
    out.flush();
Lisa's avatar
Lisa committed
475 476 477 478 479 480 481 482 483
    nextOperation();
}

/*
 * Go to the next sync operation.
 * If no operation is present, we've done everythig
 */
void SyncOperation::nextOperation()
{
484
    QStringList args = m_args;
Lisa's avatar
Lisa committed
485 486 487 488 489 490 491 492
    
    /* Everything done, just exits */
    if (m_operations.isEmpty()) {
        QCoreApplication::instance()->quit();
        return;
    }
    
    if (!args.isEmpty()) {
493
        args.removeFirst();
Lisa's avatar
Lisa committed
494 495 496
    }
    
    start(m_operations, m_options, args);
Lukas Appelhans's avatar
Lukas Appelhans committed
497 498
}

499 500
void SyncOperation::updateNextDatabase()
{
Lukas Appelhans's avatar
Lukas Appelhans committed
501
    if (m_currentDatabasePos == AkabeiClient::Backend::instance()->databases().count()) {
502
        QTextStream out(stdout);
503
        out << i18n("Updating all databases finished") << endl;
504 505 506
        QList<APM::Operation> opts = m_operations;
        opts.removeAll(APM::UpdateDatabases);
        start(opts, m_options, m_args);
507 508
        return;
    }
Lukas Appelhans's avatar
Lukas Appelhans committed
509
    AkabeiClient::DatabaseHandler* db = AkabeiClient::Backend::instance()->databases().at(m_currentDatabasePos);
510 511 512
    connect(db, SIGNAL(statusChanged(AkabeiClient::DatabaseHandler::Status)), this, SLOT(databaseStatusChanged(AkabeiClient::DatabaseHandler::Status)));
    connect(db, SIGNAL(progress(int)), this, SLOT(databaseProgressChanged(int)));
    connect(db, SIGNAL(errorTriggered(int)), this, SLOT(databaseErrorTriggered(int)));
513
    db->update(m_operations.contains(APM::Force));
514 515
}

Lukas Appelhans's avatar
Lukas Appelhans committed
516 517
void SyncOperation::databaseErrorTriggered(int error)
{
Lisa's avatar
Lisa committed
518
    QTextStream err(stderr);
Lukas Appelhans's avatar
Lukas Appelhans committed
519
    //FIXME: Show proper error message
Lisa's avatar
Lisa committed
520
    err << i18n("There has been an error while updating %1!", static_cast<AkabeiClient::DatabaseHandler*>(QObject::sender())->name()) << endl;
Lukas Appelhans's avatar
Lukas Appelhans committed
521 522 523 524 525
}

void SyncOperation::databaseProgressChanged(int progress)
{
    QTextStream out(stdout);
526
    out.reset();
Lukas Appelhans's avatar
Lukas Appelhans committed
527
    out << qSetFieldWidth(m_maxDbNameLenght) << static_cast<AkabeiClient::DatabaseHandler*>(QObject::sender())->name() << qSetFieldWidth(0);
Lukas Appelhans's avatar
Lukas Appelhans committed
528 529 530 531 532 533 534 535
    out << " [";
    for (int i = 1; i != 11; i++) {
        if (progress / i >= 10) {
            out << "#";
        } else {
            out << "-";
        }
    }
Lukas Appelhans's avatar
Lukas Appelhans committed
536
    out << "] " << progress << "%                                   ";//FIXME
537 538 539
    //if (progress == 100) {
    //    out << endl;
    //} else {
Lukas Appelhans's avatar
Lukas Appelhans committed
540
        out << "\r";
541
    //}
Lukas Appelhans's avatar
Lukas Appelhans committed
542 543 544 545 546
    out.flush();
}

void SyncOperation::databaseStatusChanged(AkabeiClient::DatabaseHandler::Status status)
{
Lisa's avatar
Lisa committed
547
    if (status != AkabeiClient::DatabaseHandler::StatusFinished && status != AkabeiClient::DatabaseHandler::StatusUpToDate) {
548
        return;
Lisa's avatar
Lisa committed
549 550
    }
    
Lukas Appelhans's avatar
Lukas Appelhans committed
551
    AkabeiClient::DatabaseHandler* db = AkabeiClient::Backend::instance()->databases().at(m_currentDatabasePos);
552 553 554
    disconnect(db, SIGNAL(statusChanged(AkabeiClient::DatabaseHandler::Status)), this, SLOT(databaseStatusChanged(AkabeiClient::DatabaseHandler::Status)));
    disconnect(db, SIGNAL(progress(int)), this, SLOT(databaseProgressChanged(int)));
    disconnect(db, SIGNAL(errorTriggered(int)), this, SLOT(databaseErrorTriggered(int)));
555 556 557 558 559 560 561
    
    QTextStream out(stdout);
    if (status == AkabeiClient::DatabaseHandler::StatusUpToDate) {
        out << i18n("%1 already up to date!", db->name()) << endl;
    } else {
        out << i18n("%1 updated!", db->name()) << endl;
    }
562

Lukas Appelhans's avatar
Lukas Appelhans committed
563
    m_currentDatabasePos++;
564
    updateNextDatabase();
Lukas Appelhans's avatar
Lukas Appelhans committed
565
}