Commit e19b1590 authored by Lukas Appelhans's avatar Lukas Appelhans

New ProgressBar class and used everywhere

parent 18c2044a
......@@ -34,6 +34,7 @@ include_directories(BEFORE SYSTEM
${AKABEICORE_INCLUDE_DIR})
set(apm_SRCS
progressbar.cpp
fieldnames.cpp
queueoperation.cpp
upgradeoperation.cpp
......
/* This file is part of the Chakra project
Copyright (C) 2012 Lukas Appelhans <l.appelhans@gmx.de>
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 "progressbar.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <QTime>
#include <klocale.h>
int getcols()
{
struct winsize ws;
ioctl(1, TIOCGWINSZ, &ws);
return ws.ws_col;
}
ProgressBar::ProgressBar()
{
}
ProgressBar::~ProgressBar()
{
}
QString ProgressBar::line()
{
QString line;
const unsigned int hashlen = getcols();
unsigned int length = 0;
if (m_columns & Status) {
line.append(m_status);
length += m_status.length();
}
QString details;
QString longDetails;
if (m_columns & Details) {
QMap<QString, QString>::iterator i = m_details.begin();
QMap<QString, QString>::iterator end = m_details.end();
details.append("| ");
longDetails.append("| ");
for (; i != end; i++) {
details.append(i.key());
longDetails.append(i.key() + "(" + i.value() + ") ");
}
}
QString progress;
if (m_columns & Progress) {
progress.append("| " + m_desc + " [");
progress.append("%1]" + QString::number(m_percentage) + "% ");
}
QString eta;
if (m_columns & Eta) {//Only check at the beginning of the phase whether to show it or not
eta = "| " + m_eta.toString("m:ss") + i18n(" remaining");
}
length += progress.length();
int maxToBeUsed = hashlen - 8; //- 8 for percentage
if (maxToBeUsed > (length + longDetails.length())) {
line.append(longDetails);
length += longDetails.length();
} else if (maxToBeUsed > (length + details.length())) {
line.append(details);
length += details.length();
}
line.append(progress);
if (maxToBeUsed > (length + eta.length())) {
line.append(eta);
length += eta.length();
}
if (!progress.isEmpty()) {
const int pBar = hashlen - length + 2;//+2 is the %1 we will replace :)
const unsigned int hash = m_percentage * pBar / 100;
QString pBarOut;
for (unsigned int i = pBar; i > 1; --i) {
/* if special progress bar enabled */
if (i > pBar - hash) {
pBarOut += "#";
} else {
pBarOut += "-";
}
}
line.replace("%1", pBarOut);
length += (pBarOut.length() - 1);
}
line.append("\r");
while (length < hashlen) {
line.append(QChar(0x20));
length += 1;
}
return line;
}
QString ProgressBar::showEndMessage(const QString& message)
{
const unsigned int hashlen = getcols();
QString line = message;
unsigned int length = message.length();
while (length < hashlen) {
line.append(QChar(0x20));
length += 1;
}
return line;
}
void ProgressBar::setColumns(Columns columns)
{
m_columns = columns;
}
void ProgressBar::setStatus(const QString& status)
{
m_status = status;
}
void ProgressBar::setDetails(const QMap< QString, QString >& details)
{
m_details = details;
}
void ProgressBar::setProgressDescription(const QString& desc)
{
m_desc = desc;
}
void ProgressBar::setProgress(int percentage)
{
m_percentage = percentage;
}
void ProgressBar::setEta(const QTime &eta)
{
m_eta = eta;
}
/* This file is part of the Chakra project
Copyright (C) 2012 Lukas Appelhans <l.appelhans@gmx.de>
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.
*/
#ifndef PROGRESSBAR_H
#define PROGRESSBAR_H
#include <QFlags>
#include <QString>
#include <QMap>
#include <QTime>
class ProgressBar
{
public:
enum Column {
Status = 0x01,
Details = 0x02,
Progress = 0x04,
Eta = 0x08
};
Q_DECLARE_FLAGS(Columns, Column);
ProgressBar();
virtual ~ProgressBar();
void setColumns(Columns columns);
void setStatus(const QString &status);
void setDetails(const QMap<QString, QString> &details);
void setProgressDescription(const QString &desc);
void setProgress(int percentage);
void setEta(const QTime &eta);
QString showEndMessage(const QString &message);
QString line();
private:
Columns m_columns;
QString m_status;
QMap<QString, QString> m_details;
QString m_desc;
int m_percentage;
QTime m_eta;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(ProgressBar::Columns)
#endif // PROGRESSBAR_H
......@@ -9,6 +9,7 @@
*/
#include "queueoperation.h"
#include "progressbar.h"
#include <akabeiclientbackend.h>
#include <akabeiclienttransactionhandler.h>
......@@ -28,14 +29,6 @@
#include <QCoreApplication>
#include <akabeidatabase.h>
int getcols()
{
struct winsize ws;
ioctl(1, TIOCGWINSZ, &ws);
return ws.ws_col;
}
QueueOperation::QueueOperation(APM::OperationName operation, QHash<APM::OptionName, QStringList> options, QObject * parent)
: QObject(parent),
m_operation(operation),
......@@ -307,97 +300,32 @@ QString currentPhase()
void QueueOperation::showProgress()
{
AkabeiClient::TransactionProgress * tp = AkabeiClient::Backend::instance()->transactionHandler()->transactionProgress();
//I'm sorry that this method looks a bit complicated, but I really see no other way for this... :/
int progress = tp->progress();
const unsigned int hashlen = getcols();
QString status = currentPhase();
//TODO: Only update if necessary
m_bar.setColumns(ProgressBar::Status | ProgressBar::Details | ProgressBar::Progress | ProgressBar::Eta);
m_bar.setProgress(tp->progress());
m_bar.setStatus(currentPhase());
m_bar.setProgressDescription(i18n("Total progress:"));
m_bar.setEta(tp->estimatedTime());
QMap<QString, QString> details;
QMap<Akabei::Package*, AkabeiClient::DownloadInformation> downloadInformation;
if (tp->phase() == AkabeiClient::TransactionProgress::Downloading)
downloadInformation = tp->downloadInformation();
QMap<Akabei::Package*, int> progresses = tp->currentPackages();
QMap<Akabei::Package*, int>::iterator i = progresses.begin();
QMap<Akabei::Package*, int>::iterator end = progresses.end();
QStringList additional;
int counter = 1;
int additionalLenght = 0;
QString pkgs;
for (; i != end; i++) {
QString pkgOutput = " | " + i.key()->name() + "%" + QString::number(counter);
QString add;
add = QString(" " + QString(i.key()->version().toByteArray().data()));
if (tp->phase() == AkabeiClient::TransactionProgress::Downloading) {
add.append(" (" + QString::number(i.value()) + "%/" + QString::number((downloadInformation[i.key()].downloadSpeed() / 1024)) + "KiB/s)");
details.insert(i.key()->name(), QString::number(i.value()) + "% / " + QString::number((downloadInformation[i.key()].downloadSpeed() / 1024)) + "KiB/s");
} else {
add.append(" (" + QString::number(i.value()) + "%)");
details.insert(i.key()->name(), QString::number(i.value()) + "%");
}
additional << add;
additionalLenght += add.length();
pkgs += pkgOutput;
counter++;
}
QString startOut = " | " + i18n("Total progress:") + " [";
QString endOut = "] " + QString::number(progress) + "%";
QString etaOut;
if (tp->estimatedTime() != QTime(0, 0)) //Only check at the beginning of the phase whether to show it or not
etaOut = " " + tp->estimatedTime().toString("m:ss") + i18n(" remaining");
int pBarLength = startOut.length() + endOut.length() + 10 + etaOut.length();
bool showPBar = false;
QString output;
output += status;
int length = output.length();
if ((output.length() + pBarLength) < hashlen) {
length = length + pBarLength;
showPBar = true;
}
if ((length + pkgs.length() - (additional.count() * 2)) <= hashlen) {
counter = 1;
foreach (const QString &add, additional) {
if ((length + pkgs.length() + add.length() - 2) <= hashlen) { //-2 is the argument e.g. "%1"
pkgs.replace("%" + QString::number(counter), add);
} else {
pkgs.replace("%" + QString::number(counter), QString());
}
counter++;
}
output += pkgs;
}
if (showPBar) {
QString pBarOut = startOut;
int pBar = qMax(10, (int)(hashlen - output.length() - endOut.length() - startOut.length() - etaOut.length()));
const unsigned int hash = progress * pBar / 100;
for (unsigned int i = pBar; i > 1; --i) {
/* if special progress bar enabled */
if (i > pBar - hash) {
pBarOut += "#";
} else {
pBarOut += "-";
}
}
pBarOut += endOut;
output += pBarOut;
output += etaOut;
}
m_bar.setDetails(details);
QTextStream out(stdout);
out.reset();
out << output;
if (progress == 100) {
out << endl;//FIXME: endl after phase ends, but prolly not at 100%
} else {
out << "\r";
}
out << m_bar.line();
out.flush();
}
......
......@@ -15,6 +15,7 @@
#include <akabeiclient_global.h>
#include <akabeicore_global.h>
#include "apm.h"
#include "progressbar.h"
#include <akabeierror.h>
#include <akabeipackage.h>
......@@ -49,6 +50,7 @@ private:
APM::OperationName m_operation;
QHash<APM::OptionName, QStringList> m_options;
AkabeiClient::Transaction *m_transaction;
ProgressBar m_bar;
};
#endif // QUEUEOPERATION_H
......@@ -358,16 +358,18 @@ void SyncOperation::updateNextDatabase()
void SyncOperation::databaseErrorTriggered(Akabei::Error::List errors)
{
QTextStream err(stderr);
err << i18n("There has been an error while updating %1: ", static_cast<AkabeiClient::DatabaseHandler*>(QObject::sender())->name());
QString message = i18n("There has been an error while updating %1: ", static_cast<AkabeiClient::DatabaseHandler*>(QObject::sender())->name());
foreach (Akabei::Error error, errors)
err << error.description() << endl;
message.append(error.description());
err << m_bar.showEndMessage(message) << endl;
}
void SyncOperation::databaseProgressChanged(int progress)
{
QTextStream out(stdout);
out.reset();
out << qSetFieldWidth(m_maxDbNameLenght) << static_cast<AkabeiClient::DatabaseHandler*>(QObject::sender())->name() << qSetFieldWidth(0);
/**out << qSetFieldWidth(m_maxDbNameLenght) << static_cast<AkabeiClient::DatabaseHandler*>(QObject::sender())->name() << qSetFieldWidth(0);
out << " [";
for (int i = 1; i != 11; i++) {
if (progress / i >= 10) {
......@@ -382,7 +384,12 @@ void SyncOperation::databaseProgressChanged(int progress)
//} else {
out << "\r";
//}
out.flush();
out.flush();*/
m_bar.setColumns(ProgressBar::Progress);
m_bar.setProgressDescription(static_cast<AkabeiClient::DatabaseHandler*>(QObject::sender())->name());
m_bar.setProgress(progress);
out << m_bar.line();
}
void SyncOperation::databaseStatusChanged(AkabeiClient::DatabaseHandler::Status status)
......@@ -400,11 +407,11 @@ void SyncOperation::databaseStatusChanged(AkabeiClient::DatabaseHandler::Status
QTextStream out(stdout);
if (status == AkabeiClient::DatabaseHandler::StatusUpToDate) {
out << i18n("%1 already up to date!", db->name()) << endl;
out << m_bar.showEndMessage(i18n("%1 already up to date!", db->name())) << endl;
} else if (status == AkabeiClient::DatabaseHandler::StatusError) {
out << i18n("%1 could not be updated!", db->name()) << endl;
out << m_bar.showEndMessage(i18n("%1 could not be updated!", db->name())) << endl;
} else {
out << i18n("%1 updated!", db->name()) << endl;
out << m_bar.showEndMessage(i18n("%1 updated!", db->name())) << endl;
}
m_currentDatabasePos++;
......
......@@ -14,6 +14,7 @@
#include <QObject>
#include <QUuid>
#include "apm.h"
#include "progressbar.h"
#include <akabeierror.h>
#include <akabeiclientdatabasehandler.h>
......@@ -52,6 +53,7 @@ private:
QHash<APM::OptionName, QStringList> m_options;
QStringList m_args;
QUuid queryId;
ProgressBar m_bar;
signals:
void syncFinished();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment