0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 08:41:02 +08:00

[ui] fix round progress dialog positioning for Hierarchy widget; Use round progress dialogs everywhere instead of QProgressDialog

This commit is contained in:
Victor Zarubkin 2019-10-22 19:07:01 +03:00
parent f547c62182
commit 701992a63d
7 changed files with 772 additions and 95 deletions

View File

@ -1124,9 +1124,10 @@ void BlocksTreeWidget::alignProgressBar()
if (m_progress != nullptr) if (m_progress != nullptr)
{ {
const auto pos = center;//mapToGlobal(center); const auto& pos = center;
m_progress->move(pos.x() - (m_progress->width() >> 1), m_progress->move(pos.x() - (m_progress->width() >> 1),
std::max(pos.y() - (m_progress->height() >> 1), header()->height())); std::max(pos.y() - (m_progress->height() >> 1), header()->height()));
m_progress->update();
} }
m_hintLabel->move(center.x() - (m_hintLabel->width() >> 1), m_hintLabel->move(center.x() - (m_hintLabel->width() >> 1),

View File

@ -150,7 +150,7 @@ inline void clear_stream(std::stringstream& _stream)
#endif #endif
} }
static void convertPointSizes(QString& style) static void convertPointSizes(QString& style, QString from, QString to)
{ {
// Find font family // Find font family
const auto fontMatch = QRegularExpression("font-family:\\s*\\\"(.*)\\\"\\s*;").match(style); const auto fontMatch = QRegularExpression("font-family:\\s*\\\"(.*)\\\"\\s*;").match(style);
@ -162,7 +162,7 @@ static void convertPointSizes(QString& style)
//QMessageBox::information(nullptr, "Point size", QString("100pt = %1\n1pt = %2").arg(pointSizeF * 1e2).arg(pointSizeF)); //QMessageBox::information(nullptr, "Point size", QString("100pt = %1\n1pt = %2").arg(pointSizeF * 1e2).arg(pointSizeF));
// Find and convert all sizes from points to pixels // Find and convert all sizes from points to pixels
QRegularExpression re("(\\d+\\.?\\d*)ex"); QRegularExpression re(QString("(\\d+\\.?\\d*)%1").arg(from));
auto it = re.globalMatch(style); auto it = re.globalMatch(style);
std::vector<QStringList> matches; std::vector<QStringList> matches;
@ -183,8 +183,9 @@ static void convertPointSizes(QString& style)
{ {
const auto pt = capturedTexts.back().toDouble(); const auto pt = capturedTexts.back().toDouble();
const int pixels = static_cast<int>(lround(pointSizeF * pt)); const int pixels = static_cast<int>(lround(pointSizeF * pt));
style.replace(QString(" %1").arg(capturedTexts.front()), QString(" %1px").arg(pixels)); auto converted = QString("%1%2").arg(pixels).arg(to);
style.replace(QString(":%1").arg(capturedTexts.front()), QString(":%1px").arg(pixels)); style.replace(QString(" %1").arg(capturedTexts.front()), QString(" %1").arg(converted));
style.replace(QString(":%1").arg(capturedTexts.front()), QString(":%1").arg(converted));
} }
} }
@ -196,7 +197,7 @@ static void replaceOsDependentSettings(QString& style)
#if defined(_WIN32) #if defined(_WIN32)
QRegularExpression re("/\\*\\{win\\}(.*)\\*/"); QRegularExpression re("/\\*\\{win\\}(.*)\\*/");
#elif defined(__APPLE__) #elif defined(__APPLE__)
QRegularExpression re("/\\*\\{mac\\}(.*)\\*/"); QRegularExpression re("/\\*\\{osx\\}(.*)\\*/");
#else #else
QRegularExpression re("/\\*\\{lin\\}(.*)\\*/"); QRegularExpression re("/\\*\\{lin\\}(.*)\\*/");
#endif #endif
@ -232,7 +233,8 @@ static void loadTheme(const QString& _theme)
QString style = in.readAll(); QString style = in.readAll();
if (!style.isEmpty()) if (!style.isEmpty())
{ {
convertPointSizes(style); convertPointSizes(style, "ex", "px");
convertPointSizes(style, "qex", "");
replaceOsDependentSettings(style); replaceOsDependentSettings(style);
qApp->setStyleSheet(style); qApp->setStyleSheet(style);
} }
@ -1566,10 +1568,27 @@ void MainWindow::showEvent(QShowEvent* show_event)
void MainWindow::resizeEvent(QResizeEvent* event) void MainWindow::resizeEvent(QResizeEvent* event)
{ {
Parent::resizeEvent(event); Parent::resizeEvent(event);
centerDialogs();
}
void MainWindow::moveEvent(QMoveEvent* _event)
{
Parent::moveEvent(_event);
centerDialogs();
}
void MainWindow::centerDialogs()
{
const auto center = rect().center();
if (m_progress != nullptr) if (m_progress != nullptr)
{ {
const auto pos = rect().center(); m_progress->move(center.x() - (m_progress->width() >> 1), center.y() - (m_progress->height() >> 1));
m_progress->move(pos.x() - (m_progress->width() >> 1), pos.y() - (m_progress->height() >> 1)); }
if (m_listenerDialog != nullptr)
{
m_listenerDialog->move(center.x() - (m_listenerDialog->width() >> 1), center.y() - (m_listenerDialog->height() >> 1));
} }
} }
@ -1882,8 +1901,8 @@ void MainWindow::createProgressDialog(const QString& text)
destroyProgressDialog(); destroyProgressDialog();
m_progress = new RoundProgressDialog(text, this); m_progress = new RoundProgressDialog(text, this);
m_progress->setCancelButtonEnabled(true); m_progress->setObjectName(QStringLiteral("LoadProgress"));
connect(m_progress, &RoundProgressDialog::canceled, this, &This::onFileReaderCancel); connect(m_progress, &RoundProgressDialog::rejected, this, &This::onFileReaderCancel);
m_progress->setModal(true); m_progress->setModal(true);
m_progress->setValue(0); m_progress->setValue(0);
@ -1999,10 +2018,16 @@ void MainWindow::onListenerDialogClose(int _result)
{ {
case ListenerRegime::Capture: case ListenerRegime::Capture:
{ {
m_listenerDialog = new Dialog(this, QMessageBox::Information, "Receiving data...", m_listenerDialog = new RoundProgressDialog(
"This process may take some time.", QMessageBox::Cancel); QStringLiteral("Receiving data..."),
RoundProgressIndicator::Cross,
QDialog::Rejected,
this
);
m_listenerDialog->setObjectName("ReceiveProgress");
m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true); m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true);
m_listenerDialog->show(); m_listenerDialog->show();
centerDialogs();
m_listener.stopCapture(); m_listener.stopCapture();
@ -2026,11 +2051,17 @@ void MainWindow::onListenerDialogClose(int _result)
{ {
if (_result == QDialog::Accepted) if (_result == QDialog::Accepted)
{ {
m_listenerDialog = new Dialog(this, QMessageBox::Information, "Receiving data...", m_listenerDialog = new RoundProgressDialog(
"This process may take some time.", QMessageBox::Cancel); QStringLiteral("Receiving data..."),
RoundProgressIndicator::Cross,
QDialog::Rejected,
this
);
m_listenerDialog->setObjectName("ReceiveProgress");
connect(m_listenerDialog, &QDialog::finished, this, &This::onListenerDialogClose); connect(m_listenerDialog, &QDialog::finished, this, &This::onListenerDialogClose);
m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true); m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true);
m_listenerDialog->show(); m_listenerDialog->show();
centerDialogs();
} }
else else
{ {
@ -2703,20 +2734,18 @@ void MainWindow::onCaptureClicked(bool)
m_listenerTimer.start(250); m_listenerTimer.start(250);
m_listenerDialog = new Dialog(this, QMessageBox::Information, "Capturing frames..." m_listenerDialog = new RoundProgressDialog(
, "Close this dialog to stop capturing.", QMessageBox::NoButton); QStringLiteral("Capturing frames..."),
RoundProgressIndicator::Stop,
auto button = new QToolButton(m_listenerDialog); QDialog::Accepted,
button->setAutoRaise(true); this
button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); );
button->setIconSize(applicationIconsSize()); m_listenerDialog->setObjectName("CaptureProgress");
button->setIcon(QIcon(imagePath("stop")));
button->setText("Stop");
m_listenerDialog->addButton(button, QMessageBox::AcceptRole);
m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true); m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(m_listenerDialog, &QDialog::finished, this, &This::onListenerDialogClose); connect(m_listenerDialog, &QDialog::finished, this, &This::onListenerDialogClose);
m_listenerDialog->show(); m_listenerDialog->show();
centerDialogs();
} }
void MainWindow::onGetBlockDescriptionsClicked(bool) void MainWindow::onGetBlockDescriptionsClicked(bool)
@ -2743,10 +2772,11 @@ void MainWindow::onGetBlockDescriptionsClicked(bool)
return; return;
} }
m_listenerDialog = new Dialog(this, QMessageBox::Information, "Waiting for blocks...", m_listenerDialog = new RoundProgressDialog(QStringLiteral("Waiting for blocks..."), this);
"This may take some time.", QMessageBox::NoButton); m_listenerDialog->setObjectName("GetDescriptorsProgress");
m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true); m_listenerDialog->setAttribute(Qt::WA_DeleteOnClose, true);
m_listenerDialog->show(); m_listenerDialog->show();
centerDialogs();
m_listener.requestBlocksDescription(); m_listener.requestBlocksDescription();

View File

@ -276,7 +276,7 @@ protected:
class RoundProgressDialog* m_progress = nullptr; class RoundProgressDialog* m_progress = nullptr;
class BlockDescriptorsWidget* m_dialogDescTree = nullptr; class BlockDescriptorsWidget* m_dialogDescTree = nullptr;
class Dialog* m_listenerDialog = nullptr; class RoundProgressDialog* m_listenerDialog = nullptr;
QTimer m_readerTimer; QTimer m_readerTimer;
QTimer m_listenerTimer; QTimer m_listenerTimer;
QTimer m_fpsRequestTimer; QTimer m_fpsRequestTimer;
@ -314,6 +314,7 @@ public:
void showEvent(QShowEvent* event) override; void showEvent(QShowEvent* event) override;
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
void moveEvent(QMoveEvent* _event) override;
void closeEvent(QCloseEvent* close_event) override; void closeEvent(QCloseEvent* close_event) override;
void changeEvent(QEvent* event) override; void changeEvent(QEvent* event) override;
void dragEnterEvent(QDragEnterEvent* drag_event) override; void dragEnterEvent(QDragEnterEvent* drag_event) override;
@ -380,6 +381,8 @@ private:
// Private non-virtual methods // Private non-virtual methods
void centerDialogs();
void closeProgressDialogAndClearReader(); void closeProgressDialogAndClearReader();
void onLoadingFinish(profiler::block_index_t& _nblocks); void onLoadingFinish(profiler::block_index_t& _nblocks);
void onSavingFinish(); void onSavingFinish();

View File

@ -69,19 +69,37 @@
# undef max # undef max
#endif #endif
namespace
{
// According to the Qt documentation on QPainter::drawArc: an angle must be specified in 1/16th of a degree
EASY_CONSTEXPR int Deg90 = 90 * 16;
EASY_CONSTEXPR int FullCircle = 360 * 16;
} // end of namespace <noname>.
RoundProgressIndicator::RoundProgressIndicator(QWidget* parent) RoundProgressIndicator::RoundProgressIndicator(QWidget* parent)
: Parent(parent) : Parent(parent)
, m_text("0%") , m_text("0%")
, m_background(Qt::transparent) , m_background(Qt::transparent)
, m_color(Qt::green) , m_color(Qt::green)
, m_buttonColor(QColor::fromRgb(profiler::colors::Red500))
, m_buttonSize(0.33)
, m_style(Percent)
, m_buttonStyle(NoButton)
, m_buttonRole(QDialog::Rejected)
, m_angle(Deg90)
, m_indicatorWidth(px(2))
, m_crossWidth(px(1))
, m_value(0) , m_value(0)
, m_pressed(false) , m_pressed(false)
, m_cancelButtonEnabled(false)
{ {
setWindowFlags(windowFlags() | Qt::FramelessWindowHint); setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_TranslucentBackground);
setAutoFillBackground(false); setAutoFillBackground(false);
setProperty("hover", false); setProperty("hover", false);
setProperty("pressed", false);
m_animationTimer.setInterval(16);
} }
RoundProgressIndicator::~RoundProgressIndicator() RoundProgressIndicator::~RoundProgressIndicator()
@ -89,15 +107,176 @@ RoundProgressIndicator::~RoundProgressIndicator()
} }
bool RoundProgressIndicator::cancelButtonEnabled() const RoundProgressIndicator::ButtonStyle RoundProgressIndicator::buttonStyle() const
{ {
return m_cancelButtonEnabled; return m_buttonStyle;
} }
void RoundProgressIndicator::setCancelButtonEnabled(bool enabled) void RoundProgressIndicator::setButtonStyle(ButtonStyle style)
{ {
m_cancelButtonEnabled = enabled; const auto prev = m_buttonStyle;
m_buttonStyle = style;
if (prev == m_buttonStyle)
{
return;
}
const bool hover = property("hover").toBool();
if (hover)
{
update(); update();
}
}
QString RoundProgressIndicator::buttonStyleStr() const
{
switch (m_buttonStyle)
{
case NoButton:
{
return QStringLiteral("none");
}
case Cross:
{
return QStringLiteral("cross");
}
case Stop:
{
return QStringLiteral("stop");
}
default:
{
return QStringLiteral("unknown");
}
}
}
void RoundProgressIndicator::setButtonStyle(QString style)
{
style = style.toLower();
if (style == QStringLiteral("cross"))
{
setButtonStyle(Cross);
}
else if (style == QStringLiteral("stop"))
{
setButtonStyle(Stop);
}
else if (style == QStringLiteral("none") || style.isEmpty())
{
setButtonStyle(NoButton);
}
}
RoundProgressIndicator::Style RoundProgressIndicator::style() const
{
return m_style;
}
void RoundProgressIndicator::setStyle(Style style)
{
const auto prev = m_style;
m_style = style;
if (prev != m_style)
{
if (m_animationTimer.isActive())
{
m_animationTimer.stop();
disconnect(&m_animationTimer, &QTimer::timeout, this, &RoundProgressIndicator::onTimeout);
}
if (m_style == Infinite)
{
m_angle = Deg90;
connect(&m_animationTimer, &QTimer::timeout, this, &RoundProgressIndicator::onTimeout);
m_animationTimer.start();
}
update();
}
}
QString RoundProgressIndicator::styleStr() const
{
switch (m_style)
{
case Percent:
{
return QStringLiteral("percent");
}
case Infinite:
{
return QStringLiteral("infinite");
}
default:
{
return QStringLiteral("unknown");
}
}
}
void RoundProgressIndicator::setStyle(QString style)
{
style = style.toLower();
if (style == QStringLiteral("percent"))
{
setStyle(Percent);
}
else if (style == QStringLiteral("inf") || style == QStringLiteral("infinite"))
{
setStyle(Infinite);
}
}
QDialog::DialogCode RoundProgressIndicator::buttonRole() const
{
return m_buttonRole;
}
void RoundProgressIndicator::setButtonRole(QDialog::DialogCode role)
{
m_buttonRole = role;
}
QString RoundProgressIndicator::buttonRoleStr() const
{
switch (m_buttonRole)
{
case QDialog::Accepted:
{
return QStringLiteral("accept");
}
case QDialog::Rejected:
{
return QStringLiteral("reject");
}
default:
{
return QStringLiteral("unknown");
}
}
}
void RoundProgressIndicator::setButtonRole(QString style)
{
style = style.toLower();
if (style == QStringLiteral("accept"))
{
setButtonRole(QDialog::Accepted);
}
else if (style == QStringLiteral("reject"))
{
setButtonRole(QDialog::Rejected);
}
} }
int RoundProgressIndicator::value() const int RoundProgressIndicator::value() const
@ -114,6 +293,7 @@ void RoundProgressIndicator::setValue(int value)
void RoundProgressIndicator::reset() void RoundProgressIndicator::reset()
{ {
m_angle = Deg90;
m_value = 0; m_value = 0;
m_text = "0%"; m_text = "0%";
update(); update();
@ -153,15 +333,129 @@ void RoundProgressIndicator::setColor(QString color)
update(); update();
} }
QColor RoundProgressIndicator::buttonColor() const
{
return m_buttonColor;
}
void RoundProgressIndicator::setButtonColor(QColor color)
{
m_buttonColor = std::move(color);
if (m_buttonStyle == NoButton)
{
return;
}
const bool hover = property("hover").toBool();
if (hover)
{
update();
}
}
void RoundProgressIndicator::setButtonColor(QString color)
{
m_buttonColor.setNamedColor(color);
if (m_buttonStyle == NoButton)
{
return;
}
const bool hover = property("hover").toBool();
if (hover)
{
update();
}
}
qreal RoundProgressIndicator::buttonSize() const
{
return m_buttonSize;
}
void RoundProgressIndicator::setButtonSize(qreal size)
{
m_buttonSize = size;
if (m_buttonStyle == NoButton)
{
return;
}
const bool hover = property("hover").toBool();
if (hover)
{
update();
}
}
int RoundProgressIndicator::crossWidth() const
{
return m_crossWidth;
}
void RoundProgressIndicator::setCrossWidth(int width)
{
m_crossWidth = width;
if (m_buttonStyle != Cross)
{
return;
}
const bool hover = property("hover").toBool();
if (hover)
{
update();
}
}
int RoundProgressIndicator::indicatorWidth() const
{
return m_indicatorWidth;
}
void RoundProgressIndicator::setIndicatorWidth(int width)
{
m_indicatorWidth = width;
update();
}
void RoundProgressIndicator::showEvent(QShowEvent* event) void RoundProgressIndicator::showEvent(QShowEvent* event)
{ {
Parent::showEvent(event); Parent::showEvent(event);
updateSize();
}
void RoundProgressIndicator::updateSize()
{
const QFontMetrics fm(font()); const QFontMetrics fm(font());
const QString text = QStringLiteral("100%"); const QString text = QStringLiteral("100%");
const int size = std::max(fm.width(text), fm.height()) + px(4 * 4); const int margins = m_indicatorWidth * 4 + px(2);
const int size = static_cast<int>(std::max(fm.width(text), fm.height()) * profiler_gui::FONT_METRICS_FACTOR) + margins;
setFixedSize(size, size); setFixedSize(size, size);
emit sizeChanged();
}
void RoundProgressIndicator::onTimeout()
{
EASY_CONSTEXPR int Step = -8 * 16;
m_angle += Step;
if (m_angle > FullCircle)
{
m_angle -= FullCircle;
}
else if (m_angle < 0)
{
m_angle += FullCircle;
}
update();
} }
void RoundProgressIndicator::paintEvent(QPaintEvent* /*event*/) void RoundProgressIndicator::paintEvent(QPaintEvent* /*event*/)
@ -170,47 +464,95 @@ void RoundProgressIndicator::paintEvent(QPaintEvent* /*event*/)
painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(Qt::NoBrush); painter.setBrush(Qt::NoBrush);
const auto px4 = px(4); auto r = rect().adjusted(m_indicatorWidth, m_indicatorWidth, -m_indicatorWidth, -m_indicatorWidth);
auto r = rect().adjusted(px4, px4, -px4, -px4);
auto p = painter.pen(); auto p = painter.pen();
// Draw circle // Draw background circle
p.setWidth(px4); p.setWidth(m_indicatorWidth);
p.setColor(m_background); p.setColor(m_background);
painter.setPen(p); painter.setPen(p);
painter.drawArc(r, 0, 360 * 16); painter.drawEllipse(r);
// Draw current progress arc
p.setColor(m_color); p.setColor(m_color);
painter.setPen(p); painter.setPen(p);
painter.drawArc(r, 90 * 16, -1 * static_cast<int>(m_value) * 16 * 360 / 100);
if (m_style == Percent)
{
painter.drawArc(r, Deg90, -1 * static_cast<int>(m_value) * FullCircle / 100);
}
else
{
painter.drawArc(r, m_angle, -1 * FullCircle / 5);
}
const bool hover = property("hover").toBool(); const bool hover = property("hover").toBool();
if (hover && m_cancelButtonEnabled) if (hover && m_buttonStyle != NoButton)
{ {
switch (m_buttonStyle)
{
case Cross:
{
paintCrossButton(painter, r);
break;
}
case Stop:
{
paintStopButton(painter, r);
break;
}
default:
{
break;
}
}
}
else if (m_style == Percent)
{
// Draw text
p.setWidth(px(1));
p.setColor(palette().foreground().color());
painter.setPen(p);
painter.setFont(font());
painter.drawText(r, Qt::AlignCenter, m_text);
}
}
void RoundProgressIndicator::paintCrossButton(QPainter& painter, QRect& r)
{
// Draw cancel button (red cross) // Draw cancel button (red cross)
const auto hquarter = px4 + (r.width() >> 2); const auto margin = (1. - m_buttonSize) * 0.5;
const auto vquarter = px4 + (r.height() >> 2); const auto dh = m_indicatorWidth + static_cast<int>(r.width() * margin);
r.adjust(hquarter, vquarter, -hquarter, -vquarter); const auto dv = m_indicatorWidth + static_cast<int>(r.height() * margin);
r.adjust(dh, dv, -dh, -dv);
p.setWidth(px(2)); auto p = painter.pen();
p.setColor(QColor::fromRgb(m_pressed ? profiler::colors::Red900 : profiler::colors::Red500)); p.setWidth(m_crossWidth);
p.setColor(m_buttonColor);
p.setCapStyle(Qt::SquareCap); p.setCapStyle(Qt::SquareCap);
painter.setPen(p); painter.setPen(p);
painter.setBrush(Qt::NoBrush); painter.setBrush(Qt::NoBrush);
painter.drawLine(r.topLeft(), r.bottomRight()); painter.drawLine(r.topLeft(), r.bottomRight());
painter.drawLine(r.bottomLeft(), r.topRight()); painter.drawLine(r.bottomLeft(), r.topRight());
} }
else
{ void RoundProgressIndicator::paintStopButton(QPainter& painter, QRect& r)
// Draw text {
p.setWidth(px(1)); // Draw cancel button (red cross)
p.setColor(palette().foreground().color());
painter.setPen(p); const auto margin = (1. - m_buttonSize) * 0.5;
painter.drawText(r, Qt::AlignCenter, m_text); const auto dh = m_indicatorWidth + static_cast<int>(r.width() * margin);
} const auto dv = m_indicatorWidth + static_cast<int>(r.height() * margin);
r.adjust(dh, dv, -dh, -dv);
painter.setPen(Qt::NoPen);
painter.setBrush(m_buttonColor);
painter.drawRect(r);
} }
void RoundProgressIndicator::enterEvent(QEvent* event) { void RoundProgressIndicator::enterEvent(QEvent* event) {
@ -227,7 +569,7 @@ void RoundProgressIndicator::mousePressEvent(QMouseEvent* event)
{ {
Parent::mousePressEvent(event); Parent::mousePressEvent(event);
m_pressed = true; m_pressed = true;
update(); profiler_gui::updateProperty(this, "pressed", true);
} }
void RoundProgressIndicator::mouseReleaseEvent(QMouseEvent* event) void RoundProgressIndicator::mouseReleaseEvent(QMouseEvent* event)
@ -238,11 +580,11 @@ void RoundProgressIndicator::mouseReleaseEvent(QMouseEvent* event)
const bool pressed = m_pressed; const bool pressed = m_pressed;
m_pressed = false; m_pressed = false;
update(); profiler_gui::updateProperty(this, "pressed", false);
if (pressed && hover && m_cancelButtonEnabled) if (pressed && hover && m_buttonStyle != NoButton)
{ {
emit cancelButtonClicked(); emit buttonClicked(m_buttonRole);
} }
} }
@ -291,7 +633,10 @@ RoundProgressWidget::RoundProgressWidget(const QString& title, QWidget* parent)
lay->addWidget(m_title); lay->addWidget(m_title);
lay->addWidget(m_indicatorWrapper); lay->addWidget(m_indicatorWrapper);
connect(m_indicator, &RoundProgressIndicator::cancelButtonClicked, this, &RoundProgressWidget::canceled); connect(m_indicator, &RoundProgressIndicator::buttonClicked, this, &RoundProgressWidget::finished);
connect(m_indicator, &RoundProgressIndicator::sizeChanged, [this] {
adjustSize();
});
} }
RoundProgressWidget::~RoundProgressWidget() RoundProgressWidget::~RoundProgressWidget()
@ -322,7 +667,9 @@ void RoundProgressWidget::setValue(int value)
emit valueChanged(v); emit valueChanged(v);
if (v == 100) if (v == 100)
emit finished(); {
emit finished(QDialog::Accepted);
}
} }
void RoundProgressWidget::reset() void RoundProgressWidget::reset()
@ -376,23 +723,57 @@ void RoundProgressWidget::setTopTitlePosition(bool isTop)
setTitlePosition(isTop ? RoundProgressWidget::Top : RoundProgressWidget::Bottom); setTitlePosition(isTop ? RoundProgressWidget::Top : RoundProgressWidget::Bottom);
} }
bool RoundProgressWidget::cancelButtonEnabled() const RoundProgressButtonStyle RoundProgressWidget::buttonStyle() const
{ {
return m_indicator->cancelButtonEnabled(); return m_indicator->buttonStyle();
} }
void RoundProgressWidget::setCancelButtonEnabled(bool enabled) void RoundProgressWidget::setButtonStyle(RoundProgressButtonStyle style)
{ {
m_indicator->setCancelButtonEnabled(enabled); m_indicator->setButtonStyle(style);
} }
QDialog::DialogCode RoundProgressWidget::buttonRole() const
{
return m_indicator->buttonRole();
}
void RoundProgressWidget::setButtonRole(QDialog::DialogCode role)
{
m_indicator->setButtonRole(role);
}
RoundProgressStyle RoundProgressWidget::style() const
{
return m_indicator->style();
}
void RoundProgressWidget::setStyle(RoundProgressStyle style)
{
m_indicator->setStyle(style);
}
RoundProgressDialog::RoundProgressDialog(const QString& title, QWidget* parent) RoundProgressDialog::RoundProgressDialog(const QString& title, QWidget* parent)
: RoundProgressDialog(title, RoundProgressIndicator::NoButton, QDialog::Rejected, parent)
{
}
RoundProgressDialog::RoundProgressDialog(
const QString& title,
RoundProgressButtonStyle button,
QDialog::DialogCode buttonRole,
QWidget* parent
)
: Parent(parent) : Parent(parent)
, m_progress(new RoundProgressWidget(title, this)) , m_progress(new RoundProgressWidget(title, this))
, m_background(Qt::transparent) , m_background(Qt::transparent)
, m_borderRadius(px(15))
{ {
setWindowTitle(profiler_gui::DEFAULT_WINDOW_TITLE); setWindowTitle(profiler_gui::DEFAULT_WINDOW_TITLE);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
// do not merge with existing windowFlags() to let the dialog be always binded to it's parent
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_TranslucentBackground);
setAutoFillBackground(false); setAutoFillBackground(false);
@ -400,8 +781,10 @@ RoundProgressDialog::RoundProgressDialog(const QString& title, QWidget* parent)
lay->addWidget(m_progress); lay->addWidget(m_progress);
connect(m_progress, &RoundProgressWidget::valueChanged, this, &RoundProgressDialog::valueChanged); connect(m_progress, &RoundProgressWidget::valueChanged, this, &RoundProgressDialog::valueChanged);
connect(m_progress, &RoundProgressWidget::finished, this, &RoundProgressDialog::finished); connect(m_progress, &RoundProgressWidget::finished, this, &RoundProgressDialog::onFinished);
connect(m_progress, &RoundProgressWidget::canceled, this, &RoundProgressDialog::canceled);
m_progress->setButtonStyle(button);
m_progress->setButtonRole(buttonRole);
} }
RoundProgressDialog::~RoundProgressDialog() RoundProgressDialog::~RoundProgressDialog()
@ -409,6 +792,18 @@ RoundProgressDialog::~RoundProgressDialog()
} }
void RoundProgressDialog::onFinished(int role)
{
if (role == QDialog::Accepted)
{
accept();
}
else
{
reject();
}
}
QColor RoundProgressDialog::background() const QColor RoundProgressDialog::background() const
{ {
return m_background; return m_background;
@ -420,20 +815,51 @@ void RoundProgressDialog::setBackground(QColor color)
update(); update();
} }
int RoundProgressDialog::borderRadius() const
{
return m_borderRadius;
}
void RoundProgressDialog::setBorderRadius(int radius)
{
m_borderRadius = radius;
update();
}
void RoundProgressDialog::setBackground(QString color) void RoundProgressDialog::setBackground(QString color)
{ {
m_background.setNamedColor(color); m_background.setNamedColor(color);
update(); update();
} }
bool RoundProgressDialog::cancelButtonEnabled() const RoundProgressButtonStyle RoundProgressDialog::buttonStyle() const
{ {
return m_progress->cancelButtonEnabled(); return m_progress->buttonStyle();
} }
void RoundProgressDialog::setCancelButtonEnabled(bool enabled) void RoundProgressDialog::setButtonStyle(RoundProgressButtonStyle style)
{ {
m_progress->setCancelButtonEnabled(enabled); m_progress->setButtonStyle(style);
}
RoundProgressStyle RoundProgressDialog::style() const
{
return m_progress->style();
}
void RoundProgressDialog::setStyle(RoundProgressStyle style)
{
m_progress->setStyle(style);
}
QDialog::DialogCode RoundProgressDialog::buttonRole() const
{
return m_progress->buttonRole();
}
void RoundProgressDialog::setButtonRole(QDialog::DialogCode role)
{
m_progress->setButtonRole(role);
} }
void RoundProgressDialog::showEvent(QShowEvent* event) void RoundProgressDialog::showEvent(QShowEvent* event)
@ -455,5 +881,5 @@ void RoundProgressDialog::paintEvent(QPaintEvent*)
painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen); painter.setPen(Qt::NoPen);
painter.setBrush(m_background); painter.setBrush(m_background);
painter.drawRect(0, 0, width(), height()); painter.drawRoundedRect(rect(), m_borderRadius, m_borderRadius);
} }

View File

@ -54,26 +54,49 @@
#include <stdint.h> #include <stdint.h>
#include <QColor> #include <QColor>
#include <QDialog> #include <QDialog>
#include <QTimer>
#include <QWidget> #include <QWidget>
class RoundProgressIndicator : public QWidget class RoundProgressIndicator : public QWidget
{ {
Q_OBJECT Q_OBJECT
public:
enum ButtonStyle { NoButton = 0, Cross, Stop };
enum Style { Percent = 0, Infinite };
private:
using Parent = QWidget; using Parent = QWidget;
using This = RoundProgressIndicator; using This = RoundProgressIndicator;
QTimer m_animationTimer;
QString m_text; QString m_text;
QColor m_background; QColor m_background;
QColor m_color; QColor m_color;
QColor m_buttonColor;
qreal m_buttonSize;
Style m_style;
ButtonStyle m_buttonStyle;
QDialog::DialogCode m_buttonRole;
int m_angle;
int m_indicatorWidth;
int m_crossWidth;
int8_t m_value; int8_t m_value;
bool m_pressed; bool m_pressed;
bool m_cancelButtonEnabled;
public: public:
Q_PROPERTY(QColor color READ color WRITE setColor); Q_PROPERTY(QColor color READ color WRITE setColor);
Q_PROPERTY(QColor background READ background WRITE setBackground); Q_PROPERTY(QColor background READ background WRITE setBackground);
Q_PROPERTY(QColor buttonColor READ buttonColor WRITE setButtonColor);
Q_PROPERTY(qreal buttonSize READ buttonSize WRITE setButtonSize);
Q_PROPERTY(int indicatorWidth READ indicatorWidth WRITE setIndicatorWidth);
Q_PROPERTY(int crossWidth READ crossWidth WRITE setCrossWidth);
Q_PROPERTY(QString buttonStyle READ buttonStyleStr WRITE setButtonStyle);
Q_PROPERTY(QString buttonRole READ buttonRoleStr WRITE setButtonRole);
Q_PROPERTY(QString style READ styleStr WRITE setStyle);
explicit RoundProgressIndicator(QWidget* parent = nullptr); explicit RoundProgressIndicator(QWidget* parent = nullptr);
~RoundProgressIndicator() override; ~RoundProgressIndicator() override;
@ -84,13 +107,31 @@ public:
QColor background() const; QColor background() const;
QColor color() const; QColor color() const;
QColor buttonColor() const;
bool cancelButtonEnabled() const; qreal buttonSize() const;
void setCancelButtonEnabled(bool enabled); int indicatorWidth() const;
int crossWidth() const;
ButtonStyle buttonStyle() const;
QString buttonStyleStr() const;
void setButtonStyle(ButtonStyle style);
void setButtonStyle(QString style);
QDialog::DialogCode buttonRole() const;
QString buttonRoleStr() const;
void setButtonRole(QDialog::DialogCode role);
void setButtonRole(QString role);
Style style() const;
QString styleStr() const;
void setStyle(Style style);
void setStyle(QString style);
signals: signals:
void cancelButtonClicked(); void buttonClicked(int role);
void sizeChanged();
public slots: public slots:
@ -98,6 +139,15 @@ public slots:
void setBackground(QString color); void setBackground(QString color);
void setColor(QColor color); void setColor(QColor color);
void setColor(QString color); void setColor(QString color);
void setButtonColor(QColor color);
void setButtonColor(QString color);
void setButtonSize(qreal size);
void setIndicatorWidth(int width);
void setCrossWidth(int width);
private slots:
void onTimeout();
protected: protected:
@ -109,8 +159,17 @@ protected:
void mouseReleaseEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override;
private:
void updateSize();
void paintCrossButton(QPainter& painter, QRect& r);
void paintStopButton(QPainter& painter, QRect& r);
}; // end of class RoundProgressIndicator. }; // end of class RoundProgressIndicator.
using RoundProgressButtonStyle = RoundProgressIndicator::ButtonStyle;
using RoundProgressStyle = RoundProgressIndicator::Style;
class RoundProgressWidget : public QWidget class RoundProgressWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -146,8 +205,14 @@ public:
TitlePosition titlePosition() const; TitlePosition titlePosition() const;
bool isTopTitlePosition() const; bool isTopTitlePosition() const;
bool cancelButtonEnabled() const; RoundProgressButtonStyle buttonStyle() const;
void setCancelButtonEnabled(bool enabled); void setButtonStyle(RoundProgressButtonStyle style);
QDialog::DialogCode buttonRole() const;
void setButtonRole(QDialog::DialogCode role);
RoundProgressStyle style() const;
void setStyle(RoundProgressStyle style);
public slots: public slots:
@ -159,9 +224,8 @@ public slots:
signals: signals:
void valueChanged(int value); void valueChanged(int value);
void finished(); void finished(int role);
void titlePositionChanged(); void titlePositionChanged();
void canceled();
}; // end of class RoundProgressWidget. }; // end of class RoundProgressWidget.
@ -174,18 +238,33 @@ class RoundProgressDialog : public QDialog
RoundProgressWidget* m_progress; RoundProgressWidget* m_progress;
QColor m_background; QColor m_background;
int m_borderRadius;
public: public:
Q_PROPERTY(QColor background READ background WRITE setBackground); Q_PROPERTY(QColor background READ background WRITE setBackground);
Q_PROPERTY(int borderRadius READ borderRadius WRITE setBorderRadius);
explicit RoundProgressDialog(const QString& title, QWidget* parent = nullptr); explicit RoundProgressDialog(const QString& title, QWidget* parent = nullptr);
RoundProgressDialog(
const QString& title,
RoundProgressIndicator::ButtonStyle button,
QDialog::DialogCode buttonRole,
QWidget* parent = nullptr
);
~RoundProgressDialog() override; ~RoundProgressDialog() override;
QColor background() const; QColor background() const;
int borderRadius() const;
bool cancelButtonEnabled() const; RoundProgressButtonStyle buttonStyle() const;
void setCancelButtonEnabled(bool enabled); void setButtonStyle(RoundProgressButtonStyle style);
QDialog::DialogCode buttonRole() const;
void setButtonRole(QDialog::DialogCode role);
RoundProgressStyle style() const;
void setStyle(RoundProgressStyle style);
protected: protected:
@ -196,13 +275,16 @@ public slots:
void setBackground(QColor color); void setBackground(QColor color);
void setBackground(QString color); void setBackground(QString color);
void setBorderRadius(int radius);
void setValue(int value); void setValue(int value);
signals: signals:
void valueChanged(int value); void valueChanged(int value);
void finished();
void canceled(); private slots:
void onFinished(int role);
}; // end of RoundProgressDialog. }; // end of RoundProgressDialog.

View File

@ -6,6 +6,25 @@
* default.scss by pysassc tool * * default.scss by pysassc tool *
* * * *
***********************************/ ***********************************/
/**************************************************************************
* Legend *
* *
* ex - 'pt' analog for widgets. It is converted to 'px' on program start. *
* Example: '10ex' will be converted to '21px'. *
* *
* qex - same as 'ex' but with removed 'px' in resulting text. *
* It is used for 'qproperty' properties. *
* Example: '10qex' will be converted to '21'. *
* *
* OS dependent properties: *
* *
* {lin}font-weight: bold; *
* {win}height: 12ex; *
* {osx}backgound: transparent; *
* *
* Such properties will be uncommented on program start for specified OS *
* *
***************************************************************************/
* { * {
font-family: "DejaVu Sans"; font-family: "DejaVu Sans";
font-size: 10pt; font-size: 10pt;
@ -17,10 +36,50 @@
RoundProgressIndicator { RoundProgressIndicator {
qproperty-color: #3297FD; qproperty-color: #3297FD;
qproperty-background: #c4c4c4; qproperty-background: #c4c4c4;
qproperty-indicatorWidth: 2qex;
background: transparent; } background: transparent; }
RoundProgressDialog { RoundProgressDialog {
qproperty-background: rgba(255, 255, 255, 70%); } qproperty-background: rgba(255, 255, 255, 0.7);
qproperty-borderRadius: 10qex; }
RoundProgressDialog#LoadProgress {
qproperty-background: rgba(0, 0, 0, 0.5); }
RoundProgressDialog#LoadProgress RoundProgressWidget RoundProgressIndicator {
qproperty-buttonColor: white;
qproperty-buttonStyle: cross;
qproperty-buttonRole: reject;
qproperty-buttonSize: 0.4;
qproperty-crossWidth: 1;
color: white; }
RoundProgressDialog#LoadProgress RoundProgressWidget RoundProgressIndicator[pressed=true] {
qproperty-buttonColor: red; }
RoundProgressDialog#LoadProgress RoundProgressWidget QLabel {
color: white; }
RoundProgressDialog#CaptureProgress, RoundProgressDialog#ReceiveProgress {
qproperty-background: rgba(0, 0, 0, 0.5); }
RoundProgressDialog#CaptureProgress RoundProgressWidget RoundProgressIndicator, RoundProgressDialog#ReceiveProgress RoundProgressWidget RoundProgressIndicator {
qproperty-style: infinite;
qproperty-buttonColor: red;
qproperty-buttonStyle: stop;
qproperty-buttonRole: accept;
qproperty-buttonSize: 0.35;
color: white; }
RoundProgressDialog#CaptureProgress RoundProgressWidget RoundProgressIndicator[pressed=true], RoundProgressDialog#ReceiveProgress RoundProgressWidget RoundProgressIndicator[pressed=true] {
qproperty-buttonColor: darkRed; }
RoundProgressDialog#CaptureProgress RoundProgressWidget QLabel, RoundProgressDialog#ReceiveProgress RoundProgressWidget QLabel {
color: white; }
RoundProgressDialog#ReceiveProgress RoundProgressWidget RoundProgressIndicator {
qproperty-buttonColor: white;
qproperty-buttonStyle: cross;
qproperty-buttonRole: reject;
qproperty-buttonSize: 0.4;
qproperty-crossWidth: 1; }
RoundProgressDialog#ReceiveProgress RoundProgressWidget RoundProgressIndicator[pressed=true] {
qproperty-buttonColor: red; }
MainWindow, QToolBar, QDialog { MainWindow, QToolBar, QDialog {
background-color: white; } background-color: white; }

View File

@ -11,6 +11,26 @@
@return fade_out($color, 1.0 - $opacity); @return fade_out($color, 1.0 - $opacity);
} }
/**************************************************************************
* Legend *
* *
* ex - 'pt' analog for widgets. It is converted to 'px' on program start. *
* Example: '10ex' will be converted to '21px'. *
* *
* qex - same as 'ex' but with removed 'px' in resulting text. *
* It is used for 'qproperty' properties. *
* Example: '10qex' will be converted to '21'. *
* *
* OS dependent properties: *
* *
* {lin}font-weight: bold; *
* {win}height: 12ex; *
* {osx}backgound: transparent; *
* *
* Such properties will be uncommented on program start for specified OS *
* *
***************************************************************************/
// CONSTANTS ---------------------------------------------- // CONSTANTS ----------------------------------------------
$FontSize: 10pt; $FontSize: 10pt;
@ -61,11 +81,67 @@ $WindowHeaderHoverColor: lighten($BorderColor, 14%); // #e8e8e8
RoundProgressIndicator { RoundProgressIndicator {
qproperty-color: $DarkSelectionColor; qproperty-color: $DarkSelectionColor;
qproperty-background: $BorderColor; qproperty-background: $BorderColor;
qproperty-indicatorWidth: 2qex;
background: transparent; background: transparent;
} }
RoundProgressDialog { RoundProgressDialog {
qproperty-background: rgba(255, 255, 255, 70%); qproperty-background: rgb_a(#ffffff, 0.7);
qproperty-borderRadius: 10qex;
}
RoundProgressDialog#LoadProgress {
qproperty-background: rgb_a(#000000, 0.5);
RoundProgressWidget {
RoundProgressIndicator {
qproperty-buttonColor: white;
qproperty-buttonStyle: cross;
qproperty-buttonRole: reject;
qproperty-buttonSize: 0.4;
qproperty-crossWidth: 1;
color: white;
}
RoundProgressIndicator[pressed=true] {
qproperty-buttonColor: red;
}
QLabel {
color: white;
}
}
}
RoundProgressDialog#CaptureProgress, RoundProgressDialog#ReceiveProgress {
qproperty-background: rgb_a(#000000, 0.5);
RoundProgressWidget {
RoundProgressIndicator {
qproperty-style: infinite;
qproperty-buttonColor: red;
qproperty-buttonStyle: stop;
qproperty-buttonRole: accept;
qproperty-buttonSize: 0.35;
color: white;
}
RoundProgressIndicator[pressed=true] {
qproperty-buttonColor: darkRed;
}
QLabel {
color: white;
}
}
}
RoundProgressDialog#ReceiveProgress RoundProgressWidget RoundProgressIndicator {
qproperty-buttonColor: white;
qproperty-buttonStyle: cross;
qproperty-buttonRole: reject;
qproperty-buttonSize: 0.4;
qproperty-crossWidth: 1;
}
RoundProgressDialog#ReceiveProgress RoundProgressWidget RoundProgressIndicator[pressed=true] {
qproperty-buttonColor: red;
} }
MainWindow, QToolBar, QDialog { MainWindow, QToolBar, QDialog {