colorize badges

This commit is contained in:
Martin Marmsoler 2023-01-23 11:11:44 +01:00
parent 627f73d9fd
commit 654492377a
12 changed files with 120 additions and 29 deletions

View File

@ -77,7 +77,12 @@ theme['badge'] = {
selected = '#E1E5F2', -- the color when a list item is selected
conflicted = '#DA2ADA', -- the color of conflicted items
head = '#52A500', -- a bolder color to indicate the HEAD
notification = '#8C2026' -- the color of toolbar notifications badges
notification = '#8C2026', -- the color of toolbar notifications badges
modified = '#91973A', -- (yellow) the color of the badge when the file is modified
added = '#394734', -- (green) the color of the badge when the file was newly added
deleted = '#5E3638', -- (red) the color of the badge when the file was deleted
untracked = '#2A4944', -- (green blue) the color of the badge when the file is untracked
renamed = '#23455E' -- (blue) the color of the badge when the file is renamed
}
}

View File

@ -69,7 +69,7 @@ theme['commits'] = {
-- { normal, selected, conflicted, head, notification }
theme['badge'] = {
foreground = {
normal = '#FFFFFF',
normal = '#000000',
selected = '#6C6C6C'
},
background = {
@ -77,7 +77,12 @@ theme['badge'] = {
selected = '#FFFFFF', -- the color when a list item is selected
conflicted = '#D22222', -- the color of conflicted items
head = '#6F7379', -- a bolder color to indicate the HEAD
notification = '#FF0000' -- the color of toolbar notifications badges
notification = '#FF0000', -- the color of toolbar notifications badges
modified = '#FFEEDB', -- (yellow) the color of the badge when the file is modified
added = '#DCFFDC', -- (green) the color of the badge when the file was newly added
deleted = '#FFDCDC', -- (red) the color of the badge when the file was deleted
untracked = '#d9ead2', -- (green blue) the color of the badge when the file is untracked
renamed = '#d2e8fc' -- (blue) the color of the badge when the file is renamed
}
}

View File

@ -354,6 +354,21 @@ QColor CustomTheme::badge(BadgeRole role, BadgeState state) {
case BadgeState::Notification:
stateKey = "notification";
break;
case BadgeState::Modified:
stateKey = "modified";
break;
case BadgeState::Added:
stateKey = "added";
break;
case BadgeState::Deleted:
stateKey = "deleted";
break;
case BadgeState::Untracked:
stateKey = "untracked";
break;
case BadgeState::Renamed:
stateKey = "renamed";
break;
}
QVariantMap badge = mMap.value("badge").toMap();

View File

@ -123,8 +123,20 @@ QColor Theme::badge(BadgeRole role, BadgeState state) {
case BadgeState::Notification:
return mDark ? "#8C2026" : "#FF0000";
case BadgeState::Modified:
return mDark ? "#91973A" : "#FFEEDB";
case BadgeState::Added:
return mDark ? "#394734" : "#DCFFDC";
case BadgeState::Deleted:
return mDark ? "#5E3638" : "#FFDCDC";
case BadgeState::Untracked:
return mDark ? "#2A4944" : "#C7FFF6";
case BadgeState::Renamed:
return mDark ? "#23455E" : "#D2E8FC";
}
}
assert(false);
return QStringLiteral("");
}
QList<QColor> Theme::branchTopologyEdges() {

View File

@ -22,7 +22,18 @@ class Theme {
public:
enum class BadgeRole { Foreground, Background };
enum class BadgeState { Normal, Selected, Conflicted, Head, Notification };
enum class BadgeState {
Normal,
Selected,
Conflicted,
Head,
Notification,
Modified,
Added,
Deleted,
Untracked,
Renamed
};
enum class CommitEditor { SpellError, SpellIgnore, LengthWarning };

View File

@ -79,7 +79,9 @@ void LogDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
QRect rect = decorationRect(option, index);
if (static_cast<QMetaType::Type>(variant.type()) == QMetaType::QChar) {
Badge::paint(painter, {Badge::Label(variant.toChar())}, rect, &opt);
Badge::paint(painter,
{Badge::Label(Badge::Label::Type::Log, variant.toChar())},
rect, &opt);
} else if (variant.canConvert<int>()) {
int progress = variant.toInt();
ProgressIndicator::paint(painter, rect, "#808080", progress, opt.widget);
@ -126,7 +128,9 @@ void LogDelegate::initStyleOption(QStyleOptionViewItem *option,
QStyledItemDelegate::initStyleOption(option, index);
QVariant variant = index.data(Qt::DecorationRole);
if (static_cast<QMetaType::Type>(variant.type()) == QMetaType::QChar) {
option->decorationSize = Badge::size(option->font) - ADJUSTMENT_SIZE;
option->decorationSize =
Badge::size(option->font, Badge::Label(Badge::Label::Type::Log)) -
ADJUSTMENT_SIZE;
} else if (variant.canConvert<int>()) {
option->decorationSize = ProgressIndicator::size();
}

View File

@ -49,7 +49,9 @@ QSize Badge::sizeHint() const {
}
QSize Badge::minimumSizeHint() const {
return !mLabels.isEmpty() ? size(font(), kEllipsis) : QSize();
return !mLabels.isEmpty()
? size(font(), Label(mLabels.first().type, kEllipsis))
: QSize();
}
QSize Badge::size(const QFont &font, const QList<Label> &labels) {
@ -140,14 +142,28 @@ void Badge::paint(QPainter *painter, const Label &label, const QRect &rect,
Theme::BadgeState state = Theme::BadgeState::Normal;
if (selected && active) {
state = Theme::BadgeState::Selected;
} else if (label.text == "!") {
state = Theme::BadgeState::Conflicted;
} else if (label.bold) {
state = Theme::BadgeState::Head;
}
QColor fore = theme->badge(Theme::BadgeRole::Foreground, state);
QColor back = theme->badge(Theme::BadgeRole::Background, state);
if (label.type == Label::Type::Status) {
if (label.text == "!") {
state = Theme::BadgeState::Conflicted;
} else if (label.bold) {
state = Theme::BadgeState::Head;
} else if (label.text == 'M') {
state = Theme::BadgeState::Modified;
} else if (label.text == 'A') {
state = Theme::BadgeState::Added;
} else if (label.text == 'D') {
state = Theme::BadgeState::Deleted;
} else if (label.text == '?') {
state = Theme::BadgeState::Untracked;
} else if (label.text == 'R') {
state = Theme::BadgeState::Renamed;
}
}
const QColor fore = theme->badge(Theme::BadgeRole::Foreground, state);
const QColor back = theme->badge(Theme::BadgeRole::Background, state);
painter->setBrush(back);
painter->setPen(Qt::NoPen);

View File

@ -21,12 +21,22 @@ class QStyleOption;
class Badge : public QWidget {
public:
struct Label {
Label(const QString &text = QString(), bool bold = false, bool tag = false)
enum class Type {
Ref, // Badges in the CommitList
Log, // Badges in the Log View
Status, // Badges in the TreeView // Changed, Added, Removed, Conflicted,
// ...
Conflict, // Conflict badges in the FileWidget next to the status
LFS,
};
Label(Type t, const QString &text = QString(), bool bold = false,
bool tag = false)
: text(text), bold(bold), tag(tag) {}
QString text;
bool bold;
bool tag;
Type type;
};
Badge(const QList<Label> &labels, QWidget *parent = nullptr);
@ -38,7 +48,7 @@ public:
QSize minimumSizeHint() const override;
static QSize size(const QFont &font, const QList<Label> &labels);
static QSize size(const QFont &font, const Label &label = Label());
static QSize size(const QFont &font, const Label &label);
static int paint(QPainter *painter, const QList<Label> &labels,
const QRect &rect, QStyleOption *opt = nullptr,

View File

@ -1024,12 +1024,14 @@ private:
if (mRepo.isHeadDetached()) {
git::Reference head = mRepo.head();
mRefs[head.target().id()].append({head.name(), true});
mRefs[head.target().id()].append(
{Badge::Label::Type::Ref, head.name(), true});
}
foreach (const git::Reference &ref, mRepo.refs()) {
if (git::Commit target = ref.target())
mRefs[target.id()].append({ref.name(), ref.isHead(), ref.isTag()});
mRefs[target.id()].append(
{Badge::Label::Type::Ref, ref.name(), ref.isHead(), ref.isTag()});
}
}

View File

@ -284,7 +284,7 @@ public:
connect(&mWatcher, &QFutureWatcher<QString>::finished, this, [this] {
QString result = mWatcher.result();
if (result.contains('+'))
mRefs->appendLabel({result, false, true});
mRefs->appendLabel({Badge::Label::Type::Ref, result, false, true});
});
// Respond to reference changes.
@ -303,7 +303,8 @@ public:
QList<Badge::Label> refs;
foreach (const git::Commit &commit, commits) {
foreach (const git::Reference &ref, commit.refs())
refs.append({ref.name(), ref.isHead(), ref.isTag()});
refs.append(
{Badge::Label::Type::Ref, ref.name(), ref.isHead(), ref.isTag()});
}
mRefs->setLabels(refs);

View File

@ -67,8 +67,9 @@ _FileWidget::Header::Header(const git::Diff &diff, const git::Patch &patch,
// Add LFS buttons.
if (lfs) {
Badge *lfsBadge =
new Badge({Badge::Label(FileWidget::tr("LFS"), true)}, this);
Badge *lfsBadge = new Badge(
{Badge::Label(Badge::Label::Type::LFS, FileWidget::tr("LFS"), true)},
this);
buttons->addWidget(lfsBadge);
QToolButton *lfsLockButton = new QToolButton(this);
@ -186,8 +187,8 @@ _FileWidget::Header::Header(const git::Diff &diff, const git::Patch &patch,
void _FileWidget::Header::updatePatch(const git::Patch &patch) {
auto status = patch.status();
QList<Badge::Label> labels = {
Badge::Label(QChar(git::Diff::statusChar(status)))};
QList<Badge::Label> labels = {Badge::Label(
Badge::Label::Type::Status, QChar(git::Diff::statusChar(status)))};
git::Patch::LineStats lineStats = patch.lineStats();
mStats->setStats(lineStats);
@ -248,13 +249,16 @@ void _FileWidget::Header::updatePatch(const git::Patch &patch) {
}
if (!ours.isEmpty() && ours == theirs) {
labels.append(Badge::Label(tr("both: %1").arg(ours)));
labels.append(
Badge::Label(Badge::Label::Type::Conflict, tr("both: %1").arg(ours)));
} else {
if (!ours.isEmpty()) {
labels.append(Badge::Label(tr("ours: %1").arg(ours)));
labels.append(Badge::Label(Badge::Label::Type::Conflict,
tr("ours: %1").arg(ours)));
}
if (!theirs.isEmpty()) {
labels.append(Badge::Label(tr("theirs: %1").arg(theirs)));
labels.append(Badge::Label(Badge::Label::Type::Conflict,
tr("theirs: %1").arg(theirs)));
}
}
}

View File

@ -44,7 +44,8 @@ void ViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
// Draw badges.
QString status = index.data(TreeModel::StatusRole).toString();
if (!status.isEmpty()) {
QSize size = Badge::size(painter->font());
QSize size =
Badge::size(painter->font(), Badge::Label(Badge::Label::Type::Status));
int width = size.width();
int height = size.height();
@ -55,7 +56,9 @@ void ViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
int x = opt.rect.x() + opt.rect.width();
int y = opt.rect.y() + (opt.rect.height() / 2);
QRect rect(x - width, y - (height / 2), width, height);
Badge::paint(painter, {Badge::Label(status.at(i))}, rect, &opt);
Badge::paint(painter,
{Badge::Label(Badge::Label::Type::Status, status.at(i))},
rect, &opt);
// Adjust rect.
opt.rect.adjust(0, 0, -width - 3, 0);
@ -69,6 +72,9 @@ QSize ViewDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const {
// Increase spacing.
QSize size = QItemDelegate::sizeHint(option, index);
size.setHeight(Badge::size(option.font).height() + 4);
size.setHeight(
Badge::size(option.font, Badge::Label(Badge::Label::Type::Status))
.height() +
4);
return size;
}