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 ¤t,
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