Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Reorganize clone dialog #36

Open
wants to merge 41 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d014c4a
copied progress dialog from "Repository" module (ProgressDlg) to libM…
antis81 Apr 25, 2015
9529a75
add ProgressWdgt, preparing for unified progress dialog
antis81 Apr 21, 2015
5f36edf
redesign ProgressDlg to visualize the progress of multiple activities
antis81 Apr 25, 2015
0971628
use assignment operator instead of copy c'tor
antis81 Apr 25, 2015
edad915
restart timer when active while changing the interval
antis81 Apr 25, 2015
26abca7
set text according to state of progress (running/finished)
antis81 Apr 25, 2015
3c33fc9
removed obsolete method ProgressDlg::remoteMessage
antis81 Apr 25, 2015
8a1831e
minor cleanup in ProgressDlg
antis81 Apr 27, 2015
8ee8f51
ProgressDlg: moved initializers back to c'tor
antis81 Apr 27, 2015
3a34436
ProgressDlg: removed customized palette for log view
antis81 Apr 27, 2015
aed4564
ProgressDlg: minor cleanup
antis81 Apr 27, 2015
8e1dcdb
ProgressDlg: add methods isDone() and setCanClose()
antis81 Apr 27, 2015
d6add32
ProgressDlg: move asserts
antis81 Apr 27, 2015
c3bb441
ProgressDlg: remove invalid activities from progress updating
antis81 Apr 27, 2015
51ce155
add ProgressDlg::setError()
antis81 Apr 27, 2015
4e2de0c
ProgressDlg: prevent accept() or reject() before activities are finished
antis81 Apr 27, 2015
cb2425b
PrgressDlg: frequently update close buttons
antis81 Apr 27, 2015
8eb42bf
ProgressDlg: set step percentage to 100% when finished
antis81 Apr 27, 2015
9139128
ProgressDlg: mark finished and error state of an activity by coloring…
antis81 Apr 27, 2015
c6aa567
ProgressDlg: fixed erase activities
antis81 Apr 27, 2015
415425d
ProgressDlg: make internal progress widgets use the cells background …
antis81 May 1, 2015
ad5433b
ProgressDlg: a progress widget has no "running" state; an "active" fl…
antis81 May 1, 2015
72f0db4
ProgressDlg: refine the appearance of progress bars by using the acti…
antis81 May 1, 2015
ce0fda4
ProgressDlg: add an assert, because currently the activity widget *mu…
antis81 May 7, 2015
e5cf9da
ProgressDlg: inline the info text in the progress bar
antis81 May 8, 2015
f5dc6dd
ProgressDlg: use C++11 enum class
antis81 May 8, 2015
800a368
ProgressDlg: remove "running" and "finished" text
antis81 May 8, 2015
b50fd0c
ProgressDlg: add a more descriptive "failed" text
antis81 May 8, 2015
c1b5baa
ProgressDlg: only the activity has a finished slot
antis81 May 8, 2015
5a601a8
Repository Module: reimplemented CloneDlg that inherits ExpandableDlg
antis81 Apr 25, 2015
00c2e3d
replaced old ProgressDlg in "Repository" module with the central one
antis81 Apr 25, 2015
96e228a
Remotes Module / Repository Module: moved clone action to "Remotes" m…
antis81 May 10, 2015
2cbbeed
Clone: removed incompatible code to unified ProgressDlg
antis81 Apr 21, 2015
60f92fd
Use the reimplemented ProgressDlg in CloneDlg, making it functional a…
antis81 Apr 21, 2015
903b9bd
clone dialog: adjust finished signal to ProgressDlg
antis81 Apr 27, 2015
1d13d73
clone dialog: use QStringLiteral
antis81 Apr 27, 2015
23bcc4f
minor textual changes in clone dialog
antis81 Apr 27, 2015
3a1cd4e
CloneDlg: use QStringLiteral
antis81 May 8, 2015
cedc2df
CloneDlg: remove signal/slot connections of steps
antis81 May 8, 2015
97f394d
CloneDlg: signal/slot connection for checkout progress is only requir…
antis81 May 8, 2015
6bf58e3
CloneDlg: corrected description of "index" step
antis81 May 10, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Libs/libMacGitverCore/App/MgvPrimaryWindowActions.hid
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ Ui MgvPrimaryWindowActions {
StatusToolTip "Repository related functions.";

MergePlace RepositoryMenuMP;
Separator;

MergePlace CloneMP;
Separator;

Action RepositoryQuit {
Expand Down
5 changes: 5 additions & 0 deletions Libs/libMacGitverCore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ SET( SRC_FILES
Widgets/FlatTreeComboBox.cpp
Widgets/FlatTreeModel.cpp
Widgets/FlatTreeDelegate.cpp
Widgets/ProgressDlg.cpp
Widgets/SHA1Input.cpp
Widgets/ShortCommitModel.cpp
Widgets/RepoStateWidget.cpp
Expand Down Expand Up @@ -102,6 +103,7 @@ SET( PUB_HDR_FILES
Widgets/FlatTreeComboBox.h
Widgets/FlatTreeModel.h
Widgets/FlatTreeDelegate.h
Widgets/ProgressDlg.hpp
Widgets/SHA1Input.h
Widgets/ShortCommitModel.h
Widgets/TreeViewCtxMenu.hpp
Expand Down Expand Up @@ -149,6 +151,9 @@ SET( UI_FILES
RepoMan/Config/RepoManConfigPage.ui

Widgets/ExpandableDlg.ui
Widgets/ProgressDlg.ui

Widgets/ProgressWdgt.ui
)

SET( HID_FILES
Expand Down
254 changes: 254 additions & 0 deletions Libs/libMacGitverCore/Widgets/ProgressDlg.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@

#include "ProgressDlg.hpp"
#include "ui_ProgressDlg.h"
#include "ui_ProgressWdgt.h"

#include <QCloseEvent>
#include <QPushButton>
#include <QStringBuilder>

namespace Private
{

class ProgressWdgt : public QWidget, public Ui::ProgressWdgt
{
public:
enum class Result { Undefined = 0, Ok, Error };

typedef QMap< QString, QPointer<ProgressWdgt> > Steps;

public:
ProgressWdgt(const QString& description)
: mActive(true)
, mPercentage(0.)
{
setupUi(this);
setAttribute(Qt::WA_NoSystemBackground);
resultChanged(Result::Undefined);
progressBar->setMinimum(0);
progressBar->setMaximum(100);
txtHeader->setText( description );
}

public:
void resultChanged(Result result)
{
QColor barColor;

switch (result) {
case Result::Ok:
barColor = QColor(0x55, 0xFF, 0x55);
break;

case Result::Error:
barColor = QColor(0xFF, 0x55, 0x55);
break;

case Result::Undefined:
default:
barColor = QColor(0x99, 0x99, 0x99);
break;
}

progressBar->setStyleSheet(
QStringLiteral(
"QProgressBar{"
"text-align: center;"
"border: 2px solid silver;"
"border-radius: 5px;"
"background: QLinearGradient("
"x1: 0, y1: 0, x2: 0, y2: 1,"
"stop: 0 %1,"
"stop: 1 %2);"
"}")
.arg(barColor.darker(150).name()).arg(barColor.name()) %

QStringLiteral(
"QProgressBar::chunk{"
"background: QLinearGradient("
"x1: 0, y1: 0, x2: 0, y2: 1,"
"stop: 0 %1,"
"stop: 1 %2);"
"}")
.arg(barColor.lighter(150).name()).arg(barColor.name())
);
}

public:
bool mActive;
qreal mPercentage;

Steps mSteps;
};

}


ProgressDlg::ProgressDlg()
: BlueSky::Dialog()
, ui( new Ui::ProgressDlg )
, mDone( false )
{
ui->setupUi( this );

QPushButton* close = ui->buttonBox->button(QDialogButtonBox::Close);
close->setEnabled( false );
connect(close, &QPushButton::clicked, this, &ProgressDlg::close);

connect(&mUpdater, &QTimer::timeout, this, &ProgressDlg::updateActivities);
mUpdater.start(250);
}

ProgressDlg::~ProgressDlg()
{
delete ui;
}

int ProgressDlg::updateInterval() const
{
return mUpdater.interval();
}

void ProgressDlg::setUpdateInterval(int msec)
{
if (mUpdater.isActive()) {
// restart timer with the new interval
mUpdater.start(msec);
}
else {
mUpdater.setInterval(msec);
}
}

void ProgressDlg::addActivity(const QString& description, QObject* activity,
const StepInfo::List& steps)
{
Q_ASSERT(activity);

Private::ProgressWdgt* a = new Private::ProgressWdgt(description);
mActivities[activity] = a;

QTreeWidgetItem* activityItem(new QTreeWidgetItem);
ui->treeProgress->addTopLevelItem(activityItem);
ui->treeProgress->setItemWidget(activityItem, 0, a);

foreach (const StepInfo& sir, steps) {
Private::ProgressWdgt* s = new Private::ProgressWdgt(sir.desc);
a->mSteps[sir.name] = s;

QTreeWidgetItem* stepItem(new QTreeWidgetItem);
activityItem->addChild(stepItem);
ui->treeProgress->setItemWidget(stepItem, 0, s);
}
}

void ProgressDlg::setStatusInfo(QObject* activity, const QString& step,
const QString& text)
{
Private::ProgressWdgt* s = findStep(activity, step);
Q_ASSERT(s);

s->progressBar->setFormat(text);
}

void ProgressDlg::setPercentage(QObject* activity, const QString& step,
qreal percent)
{
Private::ProgressWdgt* s = findStep(activity, step);
Q_ASSERT(s);

s->mPercentage = qMin( qMax(percent, 0.), 1. ) * 100.;

if (s->mPercentage >= 100.) {
s->resultChanged(Private::ProgressWdgt::Result::Ok);
}
}

void ProgressDlg::closeEvent( QCloseEvent* ev )
{
if( !mDone )
{
ev->ignore();
return;
}

QDialog::closeEvent( ev );
}

void ProgressDlg::finished(QObject* activity)
{
Private::ProgressWdgt* a = mActivities[activity];
Q_ASSERT(a);

a->mActive = false;
a->resultChanged(Private::ProgressWdgt::Result::Ok);
}

void ProgressDlg::setError(QObject* activity, const QString& message)
{
Private::ProgressWdgt* a = mActivities[activity];
Q_ASSERT(a);
a->mActive = false;
a->progressBar->setFormat(tr("Failed. See tool tip for details."));
a->setToolTip(tr("<b>Activity failed.</b><hr/>%1").arg(message));
a->resultChanged(Private::ProgressWdgt::Result::Error);
}

void ProgressDlg::updateActivities()
{
Activities::Iterator it = mActivities.begin();
while ( it != mActivities.end() ) {
Private::ProgressWdgt* a = *it;
Q_ASSERT(a);

a->mPercentage = 0.;

foreach (Private::ProgressWdgt* s, a->mSteps) {
s->progressBar->setValue(qRound(s->mPercentage));
qreal stepPercent = s->mPercentage / a->mSteps.size();
a->mPercentage += qMin( qMax(stepPercent, 0.), 100.);
}

a->progressBar->setValue(qRound(a->mPercentage));

// remove invalid activities after updating
if (!it.key()) {
it = mActivities.erase(it);
}
else {
++it;
}
}

setCanClose();
}

void ProgressDlg::accept()
{
if (isDone()) {
BlueSky::Dialog::accept();
}
}

void ProgressDlg::reject()
{
if (isDone()) {
BlueSky::Dialog::reject();
}
}

Private::ProgressWdgt* ProgressDlg::findStep(QObject* activity, const QString& step) const
{
Private::ProgressWdgt* a = mActivities[activity];
return step.isEmpty() || !a ? nullptr : a->mSteps[step];
}

void ProgressDlg::setCanClose()
{
const bool wasDone = mDone;
mDone = isDone();

if (mDone != wasDone) {
ui->buttonBox->button( QDialogButtonBox::Close )->setEnabled( mDone );
}
}
87 changes: 87 additions & 0 deletions Libs/libMacGitverCore/Widgets/ProgressDlg.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@

#pragma once

#include "libMacGitverCore/MacGitverApi.hpp"
#include "libBlueSky/Dialog.hpp"

#include <QMap>
#include <QPointer>
#include <QTimer>

namespace Private
{
class ProgressWdgt;
};

namespace Ui
{
class ProgressDlg;
};

class MGV_CORE_API ProgressDlg : public BlueSky::Dialog
{
Q_OBJECT

public:
struct StepInfo
{
typedef QVector<StepInfo> List;

QString name;
QString desc;
};

typedef QMap< QPointer<QObject>, QPointer<Private::ProgressWdgt> > Activities;

public:
ProgressDlg();
~ProgressDlg();

public:
int updateInterval() const;
void setUpdateInterval(int msec);

void addActivity(const QString& description, QObject* activity,
const StepInfo::List& steps);

void setStatusInfo(QObject* activity, const QString& step,
const QString& text);
void setPercentage(QObject* activity, const QString& step, qreal percent);

void finished(QObject* activity);

void setError(QObject* activity, const QString& message);

public:
// virtual slots
void accept();
void reject();

private slots:
void updateActivities();

protected:
void closeEvent( QCloseEvent* ev );

private:
Private::ProgressWdgt* findStep(QObject* activity, const QString& step) const;

bool isDone() const;
void setCanClose();

private:
Ui::ProgressDlg* ui;

private:
bool mDone;
QString mBaseLog;
QString mRawRemoteMessage;
Activities mActivities;

QTimer mUpdater;
};

inline bool ProgressDlg::isDone() const
{
return mActivities.isEmpty();
}
Loading