1 #include <QDebug>
2 #include <QJsonObject>
3 #include <QJsonArray>
4 #include <QMap>
5 #include <QPainter>
6 #include <QPainterPath>
7 #include <QFontMetrics>
8 #include <QScreen>
9 #include <QJsonArray>
10 #include <QScrollBar>
11 #include <QApplication>
12 #include <QSvgRenderer>
13 #include <QMouseEvent>
14 #include <QSortFilterProxyModel>
15 
16 #include "common/Configuration.h"
17 #include "common/ColorThemeWorker.h"
18 #include "common/Helpers.h"
19 
20 #include "widgets/ColorThemeListView.h"
21 
22 constexpr int allFieldsRole = Qt::UserRole + 2;
23 
24 struct OptionInfo {
25     QString info;
26     QString displayingtext;
27 };
28 
29 extern const QMap<QString, OptionInfo> optionInfoMap__;
30 
ColorOptionDelegate(QObject * parent)31 ColorOptionDelegate::ColorOptionDelegate(QObject* parent) : QStyledItemDelegate (parent)
32 {
33     resetButtonPixmap = getPixmapFromSvg(":/img/icons/reset.svg", qApp->palette().text().color());
34     connect(qApp, &QGuiApplication::paletteChanged, this,
35             [this](){
36         resetButtonPixmap = getPixmapFromSvg(":/img/icons/reset.svg", qApp->palette().text().color());
37     });
38 }
39 
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const40 void ColorOptionDelegate::paint(QPainter *painter,
41                                 const QStyleOptionViewItem &option,
42                                 const QModelIndex &index) const
43 {
44     int margin = this->margin;
45     painter->save();
46     painter->setFont(option.font);
47     painter->setRenderHint(QPainter::Antialiasing);
48 
49     ColorOption currCO = index.data(Qt::UserRole).value<ColorOption>();
50 
51     int penWidth = painter->pen().width();
52     int fontHeight = painter->fontMetrics().height();
53     QPoint tl = option.rect.topLeft();
54 
55     QRect optionNameRect;
56     optionNameRect.setTopLeft(tl + QPoint(margin, penWidth));
57     optionNameRect.setWidth(option.rect.width() - margin * 2);
58     optionNameRect.setHeight(fontHeight);
59 
60     QRect optionRect;
61     optionRect.setTopLeft(optionNameRect.bottomLeft() + QPoint(margin / 2, margin / 2));
62     optionRect.setWidth(option.rect.width() - (optionRect.topLeft() - tl).x() * 2);
63     optionRect.setHeight(option.rect.height() - (optionRect.topLeft() - tl).y() - margin);
64 
65     QRect colorRect;
66     colorRect.setTopLeft(optionRect.topLeft() + QPoint(margin / 4, margin / 4));
67     colorRect.setBottom(optionRect.bottom() - margin / 4);
68     colorRect.setWidth(colorRect.height());
69 
70     QRect descTextRect;
71     descTextRect.setTopLeft(colorRect.topRight() + QPoint(margin, colorRect.height() / 2 - fontHeight / 2));
72     descTextRect.setWidth(optionRect.width() - (descTextRect.left() - optionRect.left()) - margin);
73     descTextRect.setHeight(fontHeight);
74 
75     bool paintResetButton = false;
76     QRect resetButtonRect;
77 
78     if (option.state & (QStyle::State_Selected | QStyle::State_MouseOver)) {
79         QBrush br;
80         QPen pen;
81         if (option.state.testFlag(QStyle::State_Selected)) {
82             QColor c = qApp->palette().highlight().color();
83             c.setAlphaF(0.4);
84             br = c;
85             pen = QPen(qApp->palette().highlight().color(), margin / 2);
86             if (currCO.changed) {
87                 paintResetButton = true;
88                 descTextRect.setWidth(descTextRect.width() - descTextRect.height() - margin / 2);
89                 resetButtonRect.setTopLeft(descTextRect.topRight() + QPoint(margin, 0));
90                 resetButtonRect.setWidth(descTextRect.height());
91                 resetButtonRect.setHeight(descTextRect.height());
92                 resetButtonRect.setSize(resetButtonRect.size() * 1.0);
93             }
94         } else {
95 #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
96             QColor placeholderColor = qApp->palette().placeholderText().color();
97 #else
98             QColor placeholderColor = qApp->palette().text().color();
99             placeholderColor.setAlphaF(0.5);
100 #endif
101             QColor c = placeholderColor;
102             c.setAlphaF(0.2);
103             br = c;
104             pen = QPen(placeholderColor.darker(), margin / 2);
105         }
106 
107         painter->fillRect(option.rect, br);
108 
109         painter->setPen(pen);
110         int pw = painter->pen().width() / 2;
111         QPoint top = option.rect.topLeft() + QPoint(pw, pw);
112         QPoint bottom = option.rect.bottomLeft() - QPoint(-pw, pw - 1);
113         painter->drawLine(top, bottom);
114     }
115 
116     if (paintResetButton) {
117         painter->drawPixmap(resetButtonRect, resetButtonPixmap);
118         auto self = const_cast<ColorOptionDelegate*>(this);
119         self->resetButtonRect = resetButtonRect;
120     }
121     if (option.rect.contains(this->resetButtonRect) && this->resetButtonRect != resetButtonRect) {
122         auto self = const_cast<ColorOptionDelegate*>(this);
123         self->resetButtonRect = QRect(0,0,0,0);
124     }
125 
126     painter->setPen(qApp->palette().text().color());
127 
128     QString name = painter->fontMetrics().elidedText(
129                        optionInfoMap__[currCO.optionName].displayingtext,
130                        Qt::ElideRight, optionNameRect.width());
131     painter->drawText(optionNameRect, name);
132 
133     QPainterPath roundedOptionRect;
134     roundedOptionRect.addRoundedRect(optionRect, fontHeight / 4, fontHeight / 4);
135     painter->setPen(qApp->palette().text().color());
136     painter->drawPath(roundedOptionRect);
137 
138     QPainterPath roundedColorRect;
139     roundedColorRect.addRoundedRect(colorRect, fontHeight / 4, fontHeight / 4);
140     // Create chess-like pattern of black and white squares
141     // and fill background of roundedColorRect with it
142     if (currCO.color.alpha() < 255) {
143         const int c1 = static_cast<int>(8);
144         const int c2 = c1 / 2;
145         QPixmap p(c1, c1);
146         QPainter paint(&p);
147         paint.fillRect(0, 0, c1, c1, Qt::white);
148         paint.fillRect(0, 0, c2, c2, Qt::black);
149         paint.fillRect(c2, c2, c2, c2, Qt::black);
150         QBrush b;
151         b.setTexture(p);
152         painter->fillPath(roundedColorRect, b);
153     }
154     painter->setPen(currCO.color);
155     painter->fillPath(roundedColorRect, currCO.color);
156 
157     QString desc = painter->fontMetrics().elidedText(
158                        currCO.optionName + ": " +
159                        optionInfoMap__[currCO.optionName].info, Qt::ElideRight,
160                        descTextRect.width());
161     painter->setPen(qApp->palette().text().color());
162     painter->setBrush(qApp->palette().text());
163     painter->drawText(descTextRect, desc);
164 
165     painter->restore();
166 }
167 
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index) const168 QSize ColorOptionDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
169 {
170     qreal margin = this->margin;
171     qreal fontHeight = option.fontMetrics.height();
172     qreal h = QPen().width();
173     h += fontHeight; // option name
174     h += margin / 2; // margin between option rect and option name
175     h += margin / 4; // margin betveen option rect and color rect
176     h += fontHeight; // color rect
177     h += margin / 4; // margin betveen option rect and color rect
178     h += margin; // last margin
179 
180     Q_UNUSED(index)
181     return QSize(-1, qRound(h));
182 }
183 
getResetButtonRect() const184 QRect ColorOptionDelegate::getResetButtonRect() const
185 {
186     return resetButtonRect;
187 }
188 
getPixmapFromSvg(const QString & fileName,const QColor & after) const189 QPixmap ColorOptionDelegate::getPixmapFromSvg(const QString& fileName, const QColor& after) const
190 {
191     QFile file(fileName);
192     if (!file.open(QIODevice::ReadOnly)) {
193         return QPixmap();
194     }
195     QString data = file.readAll();
196     data.replace(QRegularExpression("#[0-9a-fA-F]{6}"), QString("%1").arg(after.name()));
197 
198     QSvgRenderer svgRenderer(data.toUtf8());
199     QPixmap pix(QSize(qApp->fontMetrics().height(), qApp->fontMetrics().height()));
200     pix.fill(Qt::transparent);
201 
202     QPainter pixPainter(&pix);
203     svgRenderer.render(&pixPainter);
204 
205     return pix;
206 }
207 
ColorThemeListView(QWidget * parent)208 ColorThemeListView::ColorThemeListView(QWidget *parent) :
209     QListView (parent)
210 {
211     QSortFilterProxyModel* proxy = new QSortFilterProxyModel(this);
212     ColorSettingsModel* model = new ColorSettingsModel(this);
213     proxy->setSourceModel(model);
214     model->updateTheme();
215     setModel(proxy);
216     proxy->setFilterRole(allFieldsRole);
217     proxy->setFilterCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
218     proxy->setSortRole(Qt::DisplayRole);
219     proxy->setSortCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
220     setItemDelegate(new ColorOptionDelegate(this));
221     setResizeMode(ResizeMode::Adjust);
222 
223     QJsonArray rgb = colorSettingsModel()->getTheme()
224                      .object().find("gui.background").value().toArray();
225     if (rgb.size() == 3) {
226         backgroundColor = QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt());
227     } else {
228         backgroundColor = palette().base().color();
229     }
230 
231     connect(&blinkTimer, &QTimer::timeout, this, &ColorThemeListView::blinkTimeout);
232 
233     blinkTimer.setInterval(400);
234     blinkTimer.start();
235 
236     setMouseTracking(true);
237 }
238 
currentChanged(const QModelIndex & current,const QModelIndex & previous)239 void ColorThemeListView::currentChanged(const QModelIndex &current,
240                                          const QModelIndex &previous)
241 {
242     ColorOption prev = previous.data(Qt::UserRole).value<ColorOption>();
243     Config()->setColor(prev.optionName, prev.color);
244     if (ThemeWorker().radare2SpecificOptions.contains(prev.optionName)) {
245         Core()->cmdRaw(QString("ec %1 %2").arg(prev.optionName).arg(prev.color.name()));
246     }
247 
248     QListView::currentChanged(current, previous);
249     emit itemChanged(current.data(Qt::UserRole).value<ColorOption>().color);
250 }
251 
dataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight,const QVector<int> & roles)252 void ColorThemeListView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
253                                       const QVector<int>& roles)
254 {
255     ColorOption curr = topLeft.data(Qt::UserRole).value<ColorOption>();
256     if (curr.optionName == "gui.background") {
257         backgroundColor = curr.color;
258     }
259     QListView::dataChanged(topLeft, bottomRight, roles);
260     emit itemChanged(curr.color);
261     emit dataChanged(curr);
262 }
263 
mouseReleaseEvent(QMouseEvent * e)264 void ColorThemeListView::mouseReleaseEvent(QMouseEvent* e)
265 {
266     if (qobject_cast<ColorOptionDelegate*>(itemDelegate())->getResetButtonRect().contains(e->pos())) {
267         ColorOption co = currentIndex().data(Qt::UserRole).value<ColorOption>();
268         co.changed = false;
269         QJsonArray rgb = ThemeWorker().getTheme(
270                              Config()->getColorTheme()).object()[co.optionName].toArray();
271         co.color = QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt());
272         model()->setData(currentIndex(), QVariant::fromValue(co));
273         QCursor c;
274         c.setShape(Qt::CursorShape::ArrowCursor);
275         setCursor(c);
276     }
277 }
278 
mouseMoveEvent(QMouseEvent * e)279 void ColorThemeListView::mouseMoveEvent(QMouseEvent* e)
280 {
281     if (qobject_cast<ColorOptionDelegate*>(itemDelegate())->getResetButtonRect().contains(e->pos())) {
282         QCursor c;
283         c.setShape(Qt::CursorShape::PointingHandCursor);
284         setCursor(c);
285     } else if (cursor().shape() == Qt::CursorShape::PointingHandCursor) {
286         QCursor c;
287         c.setShape(Qt::CursorShape::ArrowCursor);
288         setCursor(c);
289     }
290 }
291 
colorSettingsModel() const292 ColorSettingsModel* ColorThemeListView::colorSettingsModel() const
293 {
294     return static_cast<ColorSettingsModel *>(static_cast<QSortFilterProxyModel *>(model())->sourceModel());
295 }
296 
blinkTimeout()297 void ColorThemeListView::blinkTimeout()
298 {
299     static enum { Normal, Invisible } state = Normal;
300     state = state == Normal ? Invisible : Normal;
301     backgroundColor.setAlphaF(1);
302 
303     auto updateColor = [](const QString &name, const QColor &color) {
304         Config()->setColor(name, color);
305         if (ThemeWorker().radare2SpecificOptions.contains(name)) {
306             Core()->cmdRaw(QString("ec %1 %2").arg(name).arg(color.name()));
307         }
308     };
309 
310     ColorOption curr = currentIndex().data(Qt::UserRole).value<ColorOption>();
311     switch (state) {
312     case Normal:
313         updateColor(curr.optionName, curr.color);
314         break;
315     case Invisible:
316         updateColor(curr.optionName, backgroundColor);
317         break;
318     }
319     emit blink();
320 }
321 
ColorSettingsModel(QObject * parent)322 ColorSettingsModel::ColorSettingsModel(QObject *parent) : QAbstractListModel (parent) { }
323 
data(const QModelIndex & index,int role) const324 QVariant ColorSettingsModel::data(const QModelIndex &index, int role) const
325 {
326     if (!index.isValid()) {
327       return QVariant();
328     }
329 
330     if (index.row() < 0 || index.row() >= theme.size()) {
331       return QVariant();
332     }
333 
334     if (role == Qt::DisplayRole) {
335         return QVariant::fromValue(optionInfoMap__[theme.at(index.row()).optionName].displayingtext);
336     }
337 
338     if (role == Qt::UserRole) {
339         return QVariant::fromValue(theme.at(index.row()));
340     }
341 
342     if (role == Qt::ToolTipRole) {
343         return QVariant::fromValue(optionInfoMap__[theme.at(index.row()).optionName].info);
344     }
345 
346     if (role == allFieldsRole) {
347         const QString name = theme.at(index.row()).optionName;
348         return QVariant::fromValue(optionInfoMap__[name].displayingtext + " " +
349                 optionInfoMap__[theme.at(index.row()).optionName].info + " " +
350                 name);
351     }
352 
353 
354     return QVariant();
355 }
356 
setData(const QModelIndex & index,const QVariant & value,int role)357 bool ColorSettingsModel::setData(const QModelIndex& index, const QVariant& value, int role)
358 {
359     if (!index.isValid() || role != Qt::EditRole) {
360         return false;
361     }
362 
363     ColorOption currOpt = value.value<ColorOption>();
364     theme[index.row()] = currOpt;
365     emit dataChanged(index, index);
366     return true;
367 }
368 
updateTheme()369 void ColorSettingsModel::updateTheme()
370 {
371     theme.clear();
372     QJsonObject obj = ThemeWorker().getTheme(Config()->getColorTheme()).object();
373 
374     for (auto it = obj.constBegin(); it != obj.constEnd(); it++) {
375         QJsonArray rgb = it.value().toArray();
376         if (rgb.size() != 4) {
377             continue;
378         }
379         theme.push_back({it.key(), QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt(), rgb[3].toInt()), false});
380     }
381 
382     std::sort(theme.begin(), theme.end(), [](const ColorOption& f, const ColorOption& s) {
383         QString s1 = optionInfoMap__[f.optionName].displayingtext;
384         QString s2 = optionInfoMap__[s.optionName].displayingtext;
385         int r = s1.compare(s2, Qt::CaseSensitivity::CaseInsensitive);
386         return r < 0;
387     });
388     if (!theme.isEmpty()) {
389         dataChanged(index(0), index(theme.size() - 1));
390     }
391 }
392 
getTheme() const393 QJsonDocument ColorSettingsModel::getTheme() const
394 {
395     QJsonObject obj;
396     int r, g, b, a;
397     for (auto &it : theme) {
398         it.color.getRgb(&r, &g, &b, &a);
399         obj.insert(it.optionName, QJsonArray({r, g, b, a}));
400     }
401     return QJsonDocument(obj);
402 }
403 
404 const QMap<QString, OptionInfo> optionInfoMap__ = {
405 {
406     "comment", {
407         QObject::tr("Color of comment generated by radare2"),
408         QObject::tr("Comment")
409     }
410 },
411 {
412     "usrcmt", {
413         QObject::tr("Comment created by user"),
414         QObject::tr("Color of user Comment")
415     }
416 },
417 {
418     "args", {
419         "",
420         "args"
421     }
422 },
423 {
424     "fname", {
425         QObject::tr("Color of names of functions"),
426         QObject::tr("Function name")
427     }
428 },
429 {
430     "floc", {
431         QObject::tr("Color of function location"),
432         QObject::tr("Function location")
433     }
434 },
435 {
436     "fline", {
437         QObject::tr("Color of ascii line in left side that shows what opcodes are belong to function"),
438         QObject::tr("Function line")
439     }
440 },
441 {
442     "flag", {
443         QObject::tr("Color of flags (similar to bookmarks for offset)"),
444         QObject::tr("Flag")
445     }
446 },
447 {
448     "label", {
449         "",
450         QObject::tr("Label")
451     }
452 },
453 {
454     "help", {
455         "",
456         QObject::tr("Help")
457     }
458 },
459 {
460     "flow", {
461         QObject::tr("Color of lines showing jump destination"),
462         QObject::tr("Flow")
463     }
464 },
465 {
466     "flow2", {
467         "",
468         QObject::tr("flow2")
469     }
470 },
471 {
472     "prompt", {
473         QObject::tr("Info"),
474         QObject::tr("prompt")
475     }
476 },
477 {
478     "offset", {
479         QObject::tr("Color of offsets"),
480         QObject::tr("Offset")
481     }
482 },
483 {
484     "input", {
485         QObject::tr("Info"),
486         QObject::tr("input")
487     }
488 },
489 {
490     "invalid", {
491         QObject::tr("Invalid opcode color"),
492         QObject::tr("invalid")
493     }
494 },
495 {
496     "other", {
497         "",
498         QObject::tr("other")
499     }
500 },
501 {
502     "b0x00", {
503         QObject::tr("0x00 opcode color"),
504         "b0x00"
505     }
506 },
507 {
508     "b0x7f", {
509         QObject::tr("0x7f opcode color"),
510         "b0x7f"
511     }
512 },
513 {
514     "b0xff", {
515         QObject::tr("0xff opcode color"),
516         "b0xff"
517     }
518 },
519 {
520     "math", {
521         QObject::tr("Color of arithmetic opcodes (add, div, mul etc)"),
522         QObject::tr("Arithmetic")
523     }
524 },
525 {
526     "bin", {
527         QObject::tr("Color of binary operations (and, or, xor etc)."),
528         QObject::tr("Binary")
529     }
530 },
531 {
532     "btext", {
533         QObject::tr("Color of object names, commas between operators, squared brackets and operators "
534             "inside them."),
535         QObject::tr("Text")
536     }
537 },
538 {
539     "push", {
540         QObject::tr("push opcode color"),
541         "push"
542     }
543 },
544 {
545     "pop", {
546         QObject::tr("pop opcode color"),
547         "pop"
548     }
549 },
550 {
551     "crypto", {
552         QObject::tr("Cryptographic color"),
553         "crypto"
554     }
555 },
556 {
557     "jmp", {
558         QObject::tr("jmp instructions color"),
559         "jmp"
560     }
561 },
562 {
563     "cjmp", {
564         QObject::tr("Color of conditional jump opcodes such as je, jg, jne etc"),
565         QObject::tr("Conditional jump")
566     }
567 },
568 {
569     "call", {
570         QObject::tr("call instructions color (ccall, rcall, call etc)"),
571         "call"
572     }
573 },
574 {
575     "nop", {
576         QObject::tr("nop opcode color"),
577         "nop"
578     }
579 },
580 {
581     "ret", {
582         QObject::tr("ret opcode color"),
583         "ret"
584     }
585 },
586 {
587     "trap", {
588         QObject::tr("Color of interrupts"),
589         QObject::tr("Interrupts")
590     }
591 },
592 {
593     "swi", {
594         QObject::tr("swi opcode color"),
595         "swi"
596     }
597 },
598 {
599     "cmp", {
600         QObject::tr("Color of compare instructions such as test and cmp"),
601         QObject::tr("Compare instructions")
602     }
603 },
604 {
605     "reg", {
606         QObject::tr("Registers color"),
607         QObject::tr("Register")
608     }
609 },
610 {
611     "creg", {
612         "",
613         "creg"
614     }
615 },
616 {
617     "num", {
618         QObject::tr("Color of numeric constants and object pointers"),
619         QObject::tr("Constants")
620     }
621 },
622 {
623     "mov", {
624         QObject::tr("Color of move instructions such as mov, movd, lea etc"),
625         QObject::tr("Move instructions")
626     }
627 },
628 {
629     "func_var", {
630         QObject::tr("Function variable color"),
631         QObject::tr("Function variable")
632     }
633 },
634 {
635     "func_var_type", {
636         QObject::tr("Function variable (local or argument) type color"),
637         QObject::tr("Variable type")
638     }
639 },
640 {
641     "func_var_addr", {
642         QObject::tr("Function variable address color"),
643         QObject::tr("Variable address")
644     }
645 },
646 {
647     "widget_bg", {
648         "",
649         "widget_bg"
650     }
651 },
652 {
653     "widget_sel", {
654         "",
655         "widget_sel"
656     }
657 },
658 {
659     "ai.read", {
660         "",
661         "ai.read"
662     }
663 },
664 {
665     "ai.write", {
666         "",
667         "ai.write"
668     }
669 },
670 {
671     "ai.exec", {
672         "",
673         "ai.exec"
674     }
675 },
676 {
677     "ai.seq", {
678         "",
679         "ai.seq"
680     }
681 },
682 {
683     "ai.ascii", {
684         "",
685         "ai.ascii"
686     }
687 },
688 {
689     "graph.box", {
690         "",
691         "graph.box"
692     }
693 },
694 {
695     "graph.box2", {
696         "",
697         "graph.box2"
698     }
699 },
700 {
701     "graph.box3", {
702         "",
703         "graph.box3"
704     }
705 },
706 {
707     "graph.box4", {
708         "",
709         "graph.box4"
710     }
711 },
712 {
713     "graph.true", {
714         QObject::tr("In graph view jump arrow true"),
715         QObject::tr("Arrow true")
716     }
717 },
718 {
719     "graph.false", {
720         QObject::tr("In graph view jump arrow false"),
721         QObject::tr("Arrow false")
722     }
723 },
724 {
725     "graph.trufae", {
726         QObject::tr("In graph view jump arrow (no condition)"),
727         QObject::tr("Arrow")
728     }
729 },
730 {
731     "graph.current", {
732         "",
733         "graph.current"
734     }
735 },
736 {
737     "graph.traced", {
738         "",
739         "graph.traced"
740     }
741 },
742 {
743     "gui.overview.node", {
744         QObject::tr("Background color of Graph Overview's node"),
745         QObject::tr("Graph Overview node")
746     }
747 },
748 {
749     "gui.overview.fill", {
750         QObject::tr("Fill color of Graph Overview's selection"),
751         QObject::tr("Graph Overview fill")
752     }
753 },
754 {
755     "gui.overview.border", {
756         QObject::tr("Border color of Graph Overview's selection"),
757         QObject::tr("Graph Overview border")
758     }
759 },
760 {
761     "gui.cflow", {
762         "",
763         "gui.cflow"
764     }
765 },
766 {
767     "gui.dataoffset", {
768         "",
769         "gui.dataoffset"
770     }
771 },
772 {
773     "gui.background", {
774         QObject::tr("General background color"),
775         QObject::tr("Background")
776     }
777 },
778 {
779     "gui.alt_background", {
780         QObject::tr("Background color of non-focused graph node"),
781         QObject::tr("Node background")
782     }
783 },
784 {
785     "gui.disass_selected", {
786         QObject::tr("Background of current graph node"),
787         QObject::tr("Current graph node")
788     }
789 },
790 {
791     "gui.border", {
792       QObject::tr("Color of node border in graph view"),
793       QObject::tr("Node border")
794     }
795 },
796 {
797     "lineHighlight", {
798         QObject::tr("Selected line background color"),
799         QObject::tr("Line highlight")
800     }
801 },
802 {
803     "wordHighlight", {
804         QObject::tr("Background color of selected word"),
805         QObject::tr("Word higlight")
806     }
807 },
808 {
809     "gui.main", {
810         QObject::tr("Main function color"),
811         QObject::tr("Main")
812     }
813 },
814 {
815     "gui.imports", {
816         "",
817         "gui.imports"
818     }
819 },
820 {
821     "highlightPC", {
822         "",
823         "highlightPC"
824     }
825 },
826 {
827     "gui.navbar.err", {
828         "",
829         "gui.navbar.err"
830     }
831 },
832 {
833     "gui.navbar.seek", {
834         "",
835         "gui.navbar.seek"
836     }
837 },
838 {
839     "angui.navbar.str", {
840         "",
841         "angui.navbar.str"
842     }
843 },
844 {
845     "gui.navbar.pc", {
846         "",
847         "gui.navbar.pc"
848     }
849 },
850 {
851     "gui.navbar.sym", {
852         "",
853         "gui.navbar.sym"
854     }
855 },
856 {
857     "gui.navbar.code", {
858         QObject::tr("Code section color in navigation bar"),
859         QObject::tr("Navbar code")
860     }
861 },
862 {
863     "gui.navbar.empty", {
864         QObject::tr("Empty section color in navigation bar"),
865         QObject::tr("Navbar empty")
866     }
867 },
868 {
869     "ucall", {
870         "",
871         QObject::tr("ucall")
872     }
873 },
874 {
875     "ujmp", {
876         "",
877         QObject::tr("ujmp")
878     }
879 },
880 {
881     "gui.breakpoint_background", {
882         "",
883         QObject::tr("Breakpoint background")
884     }
885 }
886 };
887