qt: Make use of GUIUtil themed colors/styles (#3561)

* qt: Update theme colors in GUIUtil

- Adds ThemedColor::GREEN
- Changes ThemedColor::NEGATIVE to ThemedColor::RED
- Color adjustments to align with css colors

* qt: Give links a more eye friendly blue

* qt: Use themed colors in net traffic graph

* qt: Use themed styles/color in overview page

* qt: Use themed stylesheets in Intro

* qt: Modified QR code image painting to match the theme colors
This commit is contained in:
dustinface 2020-07-14 15:11:07 +02:00 committed by GitHub
parent 83420a18cf
commit 78dc8c354d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 94 additions and 52 deletions

View File

@ -131,42 +131,52 @@ static std::set<QWidget*> setFixedPitchFontUpdates;
static std::map<QWidget*, int> mapFontSizeUpdates;
static const std::map<ThemedColor, QColor> themedColors = {
{ ThemedColor::DEFAULT, QColor(0, 0, 0) },
{ ThemedColor::DEFAULT, QColor(85, 85, 85) },
{ ThemedColor::UNCONFIRMED, QColor(128, 128, 128) },
{ ThemedColor::NEGATIVE, QColor(255, 0, 0) },
{ ThemedColor::BLUE, QColor(0, 141, 228) },
{ ThemedColor::RED, QColor(168, 72, 50) },
{ ThemedColor::GREEN, QColor(8, 110, 3) },
{ ThemedColor::BAREADDRESS, QColor(140, 140, 140) },
{ ThemedColor::TX_STATUS_OPENUNTILDATE, QColor(64, 64, 255) },
{ ThemedColor::TX_STATUS_OFFLINE, QColor(192, 192, 192) },
{ ThemedColor::TX_STATUS_DANGER, QColor(200, 100, 100) },
{ ThemedColor::TX_STATUS_LOCKED, QColor(0, 128, 255) },
{ ThemedColor::TX_STATUS_DANGER, QColor(168, 72, 50) },
{ ThemedColor::TX_STATUS_LOCKED, QColor(28, 117, 188) },
{ ThemedColor::BACKGROUND_WIDGET, QColor(234, 234, 236) },
{ ThemedColor::BORDER_WIDGET, QColor(220, 220, 220) },
{ ThemedColor::QR_PIXEL, QColor(85, 85, 85) },
};
static const std::map<ThemedColor, QColor> themedDarkColors = {
{ ThemedColor::DEFAULT, QColor(170, 170, 170) },
{ ThemedColor::UNCONFIRMED, QColor(204, 204, 204) },
{ ThemedColor::NEGATIVE, QColor(255, 69, 0) },
{ ThemedColor::DEFAULT, QColor(199, 199, 199) },
{ ThemedColor::UNCONFIRMED, QColor(170, 170, 170) },
{ ThemedColor::BLUE, QColor(0, 89, 154) },
{ ThemedColor::RED, QColor(168, 72, 50) },
{ ThemedColor::GREEN, QColor(8, 110, 3) },
{ ThemedColor::BAREADDRESS, QColor(140, 140, 140) },
{ ThemedColor::TX_STATUS_OPENUNTILDATE, QColor(64, 64, 255) },
{ ThemedColor::TX_STATUS_OFFLINE, QColor(192, 192, 192) },
{ ThemedColor::TX_STATUS_DANGER, QColor(200, 100, 100) },
{ ThemedColor::TX_STATUS_LOCKED, QColor(0, 128, 255) },
{ ThemedColor::TX_STATUS_DANGER, QColor(168, 72, 50) },
{ ThemedColor::TX_STATUS_LOCKED, QColor(28, 117, 188) },
{ ThemedColor::BACKGROUND_WIDGET, QColor(45, 45, 46) },
{ ThemedColor::BORDER_WIDGET, QColor(74, 74, 75) },
{ ThemedColor::QR_PIXEL, QColor(199, 199, 199) },
};
static const std::map<ThemedStyle, QString> themedStyles = {
{ ThemedStyle::TS_INVALID, "background:#FF8080;" },
{ ThemedStyle::TS_ERROR, "color:red;" },
{ ThemedStyle::TS_SUCCESS, "color:green;" },
{ ThemedStyle::TS_COMMAND, "color:#006060;" },
{ ThemedStyle::TS_PRIMARY, "color:black;" },
{ ThemedStyle::TS_SECONDARY, "color:#808080;" },
{ ThemedStyle::TS_INVALID, "background:#e87b68;" },
{ ThemedStyle::TS_ERROR, "color:#a84832;" },
{ ThemedStyle::TS_SUCCESS, "color:#096e03;" },
{ ThemedStyle::TS_COMMAND, "color:#1c75bc;" },
{ ThemedStyle::TS_PRIMARY, "color:#333;" },
{ ThemedStyle::TS_SECONDARY, "color:#444;" },
};
static const std::map<ThemedStyle, QString> themedDarkStyles = {
{ ThemedStyle::TS_INVALID, "background:#ff4500;" },
{ ThemedStyle::TS_ERROR, "color:#ff4500;" },
{ ThemedStyle::TS_SUCCESS, "color:green;" },
{ ThemedStyle::TS_COMMAND, "color:#0cc;" },
{ ThemedStyle::TS_PRIMARY, "color:#ccc;" },
{ ThemedStyle::TS_INVALID, "background:#a84832;" },
{ ThemedStyle::TS_ERROR, "color:#a84832;" },
{ ThemedStyle::TS_SUCCESS, "color:#096e03;" },
{ ThemedStyle::TS_COMMAND, "color:#1c75bc;" },
{ ThemedStyle::TS_PRIMARY, "color:#c7c7c7;" },
{ ThemedStyle::TS_SECONDARY, "color:#aaa;" },
};

View File

@ -39,8 +39,12 @@ namespace GUIUtil
DEFAULT,
/* Transaction list -- unconfirmed transaction */
UNCONFIRMED,
/* Transaction list -- negative amount */
NEGATIVE,
/* Theme related blue color */
BLUE,
/* Eye-friendly red color, e.g. Transaction list -- negative amount */
RED,
/* Eye-friendly green color */
GREEN,
/* Transaction list -- bare address (without label) */
BAREADDRESS,
/* Transaction list -- TX status decoration - open until date */
@ -51,6 +55,12 @@ namespace GUIUtil
TX_STATUS_DANGER,
/* Transaction list -- TX status decoration - LockedByInstantSend color */
TX_STATUS_LOCKED,
/* Background used for some widgets. Its slightly darker than the wallets frame background. */
BACKGROUND_WIDGET,
/* Border color used for some widgets. Its slightly brighter than BACKGROUND_WIDGET. */
BORDER_WIDGET,
/* Pixel color of generated QR codes. */
QR_PIXEL,
};
/* Enumeration of possible "styles" */

View File

@ -252,7 +252,7 @@ void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable
break;
case FreespaceChecker::ST_ERROR:
ui->errorMessage->setText(tr("Error") + ": " + message);
ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
ui->errorMessage->setStyleSheet(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_ERROR));
break;
}
/* Indicate number of bytes available */
@ -264,7 +264,7 @@ void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable
if(bytesAvailable < requiredSpace * GB_BYTES)
{
freeString += " " + tr("(of %1 GB needed)").arg(requiredSpace);
ui->freeSpace->setStyleSheet("QLabel { color: #800000 }");
ui->freeSpace->setStyleSheet(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_ERROR));
} else {
ui->freeSpace->setStyleSheet("");
}

View File

@ -63,7 +63,7 @@ public:
qint64 amount = index.data(TransactionTableModel::AmountRole).toLongLong();
bool confirmed = index.data(TransactionTableModel::ConfirmedRole).toBool();
QVariant value = index.data(Qt::ForegroundRole);
QColor foreground = option.palette.color(QPalette::Text);
QColor foreground = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::DEFAULT);
if(value.canConvert<QBrush>())
{
QBrush brush = qvariant_cast<QBrush>(value);
@ -83,7 +83,7 @@ public:
if(amount < 0)
{
foreground = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::NEGATIVE);
foreground = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::RED);
}
else if(!confirmed)
{
@ -385,8 +385,9 @@ void OverviewPage::updatePrivateSendProgress()
strAmountAndRounds = strPrivateSendAmount + " / " + tr("%n Rounds", "", privateSendClient.nPrivateSendRounds);
} else {
QString strMaxToAnonymize = BitcoinUnits::formatHtmlWithUnit(nDisplayUnit, nMaxToAnonymize, false, BitcoinUnits::separatorAlways);
ui->labelAmountRounds->setToolTip(tr("Not enough compatible inputs to mix <span style='color:red;'>%1</span>,<br>"
"will mix <span style='color:red;'>%2</span> instead")
ui->labelAmountRounds->setToolTip(tr("Not enough compatible inputs to mix <span style='%1'>%2</span>,<br>"
"will mix <span style='%1'>%3</span> instead")
.arg(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_ERROR))
.arg(strPrivateSendAmount)
.arg(strMaxToAnonymize));
strMaxToAnonymize = strMaxToAnonymize.remove(strMaxToAnonymize.indexOf("."), BitcoinUnits::decimals(nDisplayUnit) + 1);
@ -511,8 +512,8 @@ void OverviewPage::privateSendStatus()
if(settings.value("fLowKeysWarning").toBool()) {
QString strWarn = tr("Very low number of keys left since last automatic backup!") + "<br><br>" +
tr("We are about to create a new automatic backup for you, however "
"<span style='color:red;'> you should always make sure you have backups "
"saved in some safe place</span>!") + "<br><br>" +
"<span style='%1'> you should always make sure you have backups "
"saved in some safe place</span>!").arg(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_COMMAND)) + "<br><br>" +
tr("Note: You can turn this message off in options.");
ui->labelPrivateSendEnabled->setToolTip(strWarn);
LogPrint(BCLog::PRIVATESEND, "OverviewPage::privateSendStatus -- Very low number of keys left since last automatic backup, warning user and trying to create new backup...\n");

View File

@ -15,6 +15,7 @@
#include <QMenu>
#include <QMimeData>
#include <QMouseEvent>
#include <QPainter>
#include <QPixmap>
#if QT_VERSION < 0x050000
#include <QUrl>
@ -158,20 +159,27 @@ void QRDialog::update()
}
ui->lblQRCode->setToolTip(strQRCode);
QImage myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
myImage.fill(0xffffff);
myImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
unsigned char *p = code->data;
for (int y = 0; y < code->width; y++)
{
for (int x = 0; x < code->width; x++)
{
myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
myImage.setPixel(x + 4, y + 4, ((*p & 1) ? GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL).rgb() : GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET).rgb()));
p++;
}
}
QRcode_free(code);
QImage qrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE, QImage::Format_RGB32);
qrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BORDER_WIDGET));
QPainter painter(&qrImage);
QRect paddedRect = qrImage.rect().adjusted(1, 1, -1, -1);
painter.fillRect(paddedRect, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
painter.drawImage(1, 1, myImage.scaled(QR_IMAGE_SIZE - 2, QR_IMAGE_SIZE - 2));
ui->labelQRCodeTitle->setText(strQRCodeTitle);
ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300));
ui->lblQRCode->setPixmap(QPixmap::fromImage(qrImage));
ui->button_saveImage->setEnabled(true);
}
#endif

View File

@ -139,7 +139,8 @@ void ReceiveRequestDialog::update()
html += "<html>";
html += "<b>"+tr("Payment information")+"</b><br>";
html += "<b>"+tr("URI")+"</b>: ";
html += "<a href=\""+uri+"\">" + GUIUtil::HtmlEscape(uri) + "</a><br>";
html += QString("<a style=\"%1\"href=\"").arg(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_COMMAND)) +
uri + "\">" + GUIUtil::HtmlEscape(uri) + "</a><br>";
html += "<b>"+tr("Address")+"</b>: " + GUIUtil::HtmlEscape(info.address) + "<br>";
if(info.amount)
html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getDisplayUnit(), info.amount) + "<br>";
@ -165,31 +166,33 @@ void ReceiveRequestDialog::update()
return;
}
QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
qrImage.fill(0xffffff);
qrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
unsigned char *p = code->data;
for (int y = 0; y < code->width; y++)
{
for (int x = 0; x < code->width; x++)
{
qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL).rgb() : GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET).rgb()));
p++;
}
}
QRcode_free(code);
QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE+20, QImage::Format_RGB32);
qrAddrImage.fill(0xffffff);
qrAddrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BORDER_WIDGET));
QPainter painter(&qrAddrImage);
painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));
QRect paddedRect = qrAddrImage.rect().adjusted(1, 1, -1, -1);
painter.fillRect(paddedRect, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
painter.drawImage(1, 1, qrImage.scaled(QR_IMAGE_SIZE - 2, QR_IMAGE_SIZE - 2));
QFont font = GUIUtil::fixedPitchFont();
QRect paddedRect = qrAddrImage.rect();
// calculate ideal font size
qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 20, info.address, font);
font.setPointSizeF(font_size);
painter.setFont(font);
paddedRect.setHeight(QR_IMAGE_SIZE+12);
paddedRect.setHeight(QR_IMAGE_SIZE);
painter.setPen(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL));
painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, info.address);
painter.end();

View File

@ -4,6 +4,7 @@
#include <qt/trafficgraphwidget.h>
#include <qt/clientmodel.h>
#include <qt/guiutil.h>
#include <boost/bind.hpp>
@ -77,11 +78,12 @@ namespace
void TrafficGraphWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(rect(), Qt::black);
QRect drawRect = rect();
painter.fillRect(drawRect, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
if(fMax <= 0.0f) return;
QColor axisCol(Qt::gray);
QColor axisCol(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::DEFAULT));
QColor axisCol2;
int h = height() - YMARGIN * 2;
painter.setPen(axisCol);
@ -120,28 +122,36 @@ void TrafficGraphWidget::paintEvent(QPaintEvent *)
if(!queue.empty()) {
QPainterPath pIn;
QColor green = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::GREEN);
QColor lucentGreen = green;
lucentGreen.setAlpha(128);
paintPath(pIn, queue, boost::bind(chooseIn,_1));
painter.fillPath(pIn, QColor(0, 255, 0, 128));
painter.setPen(Qt::green);
painter.fillPath(pIn, lucentGreen);
painter.setPen(green);
painter.drawPath(pIn);
QPainterPath pOut;
QColor red = GUIUtil::getThemedQColor(GUIUtil::ThemedColor::RED);
QColor lucentRed = red;
lucentRed.setAlpha(128);
paintPath(pOut, queue, boost::bind(chooseOut,_1));
painter.fillPath(pOut, QColor(255, 0, 0, 128));
painter.setPen(Qt::red);
painter.fillPath(pOut, lucentRed);
painter.setPen(red);
painter.drawPath(pOut);
}
// draw text on top of everything else
QRect textRect = painter.boundingRect(QRect(XMARGIN, YMARGIN + h - (h * val / fMax) - yMarginText, 0, 0), Qt::AlignLeft, QString("%1 %2").arg(val).arg(units));
textRect.translate(0, -textRect.height());
painter.fillRect(textRect, Qt::black);
painter.fillRect(textRect, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
painter.setPen(axisCol);
painter.drawText(textRect, Qt::AlignLeft, QString("%1 %2").arg(val).arg(units));
if(fMax / val <= 3.0f) {
QRect textRect2 = painter.boundingRect(QRect(XMARGIN, YMARGIN + h - (h * val2 / fMax) - yMarginText, 0, 0), Qt::AlignLeft, QString("%1 %2").arg(val2).arg(units));
textRect2.translate(0, -textRect2.height());
painter.fillRect(textRect2, Qt::black);
painter.fillRect(textRect2, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
painter.setPen(axisCol2);
painter.drawText(textRect2, Qt::AlignLeft, QString("%1 %2").arg(val2).arg(units));
}

View File

@ -660,7 +660,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
}
if(index.column() == Amount && (rec->credit+rec->debit) < 0)
{
return GUIUtil::getThemedQColor(GUIUtil::ThemedColor::NEGATIVE);
return GUIUtil::getThemedQColor(GUIUtil::ThemedColor::RED);
}
if(index.column() == ToAddress)
{

View File

@ -61,7 +61,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, HelpMode helpMode) :
// Make URLs clickable
QRegExp uri("<(.*)>", Qt::CaseSensitive, QRegExp::RegExp2);
uri.setMinimal(true); // use non-greedy matching
licenseInfoHTML.replace(uri, "<a href=\"\\1\">\\1</a>");
licenseInfoHTML.replace(uri, QString("<a style=\"%1\"href=\"\\1\">\\1</a>").arg(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_COMMAND)));
// Replace newlines with HTML breaks
licenseInfoHTML.replace("\n", "<br>");
@ -169,8 +169,8 @@ your funds will already be mixed. No additional waiting is required.</li> \
This means those 1000 addresses last for about 100 mixing events. When 900 of them are used, your wallet must create more addresses. \
It can only do this, however, if you have automatic backups enabled.<br> \
Consequently, users who have backups disabled will also have PrivateSend disabled. <hr>\
For more information, see the <a href=\"https://docs.dash.org/en/stable/wallets/dashcore/privatesend-instantsend.html\">PrivateSend documentation</a>."
));
For more information, see the <a style=\"%1\" href=\"https://docs.dash.org/en/stable/wallets/dashcore/privatesend-instantsend.html\">PrivateSend documentation</a>."
).arg(GUIUtil::getThemedStyleQString(GUIUtil::ThemedStyle::TS_COMMAND)));
ui->aboutMessage->setWordWrap(true);
ui->helpMessage->setVisible(false);
}