1 /* font_color_preferences_frame.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include <ui/qt/utils/qt_ui_utils.h>
13 #include "font_color_preferences_frame.h"
14 #include <ui/qt/models/pref_models.h>
15 #include <ui_font_color_preferences_frame.h>
16 #include <ui/qt/utils/color_utils.h>
17 #include "main_application.h"
18 #include "wsutil/array.h"
21 #include <QFontDialog>
22 #include <QColorDialog>
24 #include <epan/prefs-int.h>
26 //: These are pangrams. Feel free to replace with nonsense text that spans your alphabet.
27 //: https://en.wikipedia.org/wiki/Pangram
28 static const char *font_pangrams_
[] = {
29 QT_TRANSLATE_NOOP("FontColorPreferencesFrame", "Example GIF query packets have jumbo window sizes"),
30 QT_TRANSLATE_NOOP("FontColorPreferencesFrame", "Lazy badgers move unique waxy jellyfish packets")
32 const int num_font_pangrams_
= array_length(font_pangrams_
);
34 FontColorPreferencesFrame::FontColorPreferencesFrame(QWidget
*parent
) :
36 ui(new Ui::FontColorPreferencesFrame
),
37 colorSchemeComboBox_(nullptr)
41 #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) && (defined(Q_OS_WIN) || defined(Q_OS_MAC))
42 // This doesn't work under most Linux platforms.
43 // KDE doesn't have color scheme as a separate option from theme,
44 // and requires changing the theme. GTK4/libadwaita does have color
45 // scheme as a separate option, but Qt doesn't fully work with it.
46 // On Linux should this be invisible, disabled, or have a warning
47 // label that it probably won't work?
48 QHBoxLayout
*colorSchemeLayout
= new QHBoxLayout();
49 QLabel
*colorSchemeLabel
= new QLabel(tr("Color Scheme:"));
50 colorSchemeLayout
->addWidget(colorSchemeLabel
);
51 colorSchemeComboBox_
= new QComboBox();
52 colorSchemeComboBox_
->addItem(tr("System Default"), COLOR_SCHEME_DEFAULT
);
53 colorSchemeComboBox_
->addItem(tr("Light Mode"), COLOR_SCHEME_LIGHT
);
54 colorSchemeComboBox_
->addItem(tr("Dark Mode"), COLOR_SCHEME_DARK
);
55 connect(colorSchemeComboBox_
, &QComboBox::currentIndexChanged
,
56 this, &FontColorPreferencesFrame::colorSchemeIndexChanged
);
57 colorSchemeLayout
->addWidget(colorSchemeComboBox_
);
58 colorSchemeLayout
->addStretch();
60 ui
->verticalLayout
->insertLayout(ui
->verticalLayout
->indexOf(ui
->colorsLabel
), colorSchemeLayout
);
63 pref_color_scheme_
= prefFromPrefPtr(&prefs
.gui_color_scheme
);
64 pref_qt_gui_font_name_
= prefFromPrefPtr(&prefs
.gui_font_name
);
65 pref_active_fg_
= prefFromPrefPtr(&prefs
.gui_active_fg
);
66 pref_active_bg_
= prefFromPrefPtr(&prefs
.gui_active_bg
);
67 pref_active_style_
= prefFromPrefPtr(&prefs
.gui_active_style
);
68 pref_inactive_fg_
= prefFromPrefPtr(&prefs
.gui_inactive_fg
);
69 pref_inactive_bg_
= prefFromPrefPtr(&prefs
.gui_inactive_bg
);
70 pref_inactive_style_
= prefFromPrefPtr(&prefs
.gui_inactive_style
);
71 pref_marked_fg_
= prefFromPrefPtr(&prefs
.gui_marked_fg
);
72 pref_marked_bg_
= prefFromPrefPtr(&prefs
.gui_marked_bg
);
73 pref_ignored_fg_
= prefFromPrefPtr(&prefs
.gui_ignored_fg
);
74 pref_ignored_bg_
= prefFromPrefPtr(&prefs
.gui_ignored_bg
);
75 pref_client_fg_
= prefFromPrefPtr(&prefs
.st_client_fg
);
76 pref_client_bg_
= prefFromPrefPtr(&prefs
.st_client_bg
);
77 pref_server_fg_
= prefFromPrefPtr(&prefs
.st_server_fg
);
78 pref_server_bg_
= prefFromPrefPtr(&prefs
.st_server_bg
);
79 pref_valid_bg_
= prefFromPrefPtr(&prefs
.gui_text_valid
);
80 pref_invalid_bg_
= prefFromPrefPtr(&prefs
.gui_text_invalid
);
81 pref_deprecated_bg_
= prefFromPrefPtr(&prefs
.gui_text_deprecated
);
83 cur_font_
.fromString(prefs_get_string_value(pref_qt_gui_font_name_
, pref_stashed
));
87 FontColorPreferencesFrame::~FontColorPreferencesFrame()
92 void FontColorPreferencesFrame::showEvent(QShowEvent
*)
94 GRand
*rand_state
= g_rand_new();
95 QString pangram
= QString(font_pangrams_
[g_rand_int_range(rand_state
, 0, num_font_pangrams_
)]) + " 0123456789";
96 ui
->fontSampleLineEdit
->setText(pangram
);
97 ui
->fontSampleLineEdit
->setCursorPosition(0);
98 ui
->fontSampleLineEdit
->setMinimumWidth(mainApp
->monospaceTextSize(pangram
.toUtf8().constData()) + mainApp
->monospaceTextSize(" "));
99 g_rand_free(rand_state
);
104 void FontColorPreferencesFrame::updateWidgets()
110 QPalette default_pal
;
112 int margin
= style()->pixelMetric(QStyle::PM_LayoutLeftMargin
);
114 ui
->fontPushButton
->setText(
115 cur_font_
.family() + " " + cur_font_
.styleName() + " " +
116 QString::number(cur_font_
.pointSizeF(), 'f', 1));
117 ui
->fontSampleLineEdit
->setFont(cur_font_
);
119 QString line_edit_ss
= QStringLiteral("QLineEdit { margin-left: %1px; }").arg(margin
);
120 ui
->fontSampleLineEdit
->setStyleSheet(line_edit_ss
);
122 QString color_button_ss
=
124 " border: 1px solid palette(Dark);"
125 " background-color: %1;"
126 " margin-left: %2px;"
128 QString sample_text_ss
=
131 " background-color: %2;"
133 QString sample_text_ex_ss
=
136 " background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1 stop: 0 %3, stop: 0.5 %2, stop: 1 %3);"
139 if (colorSchemeComboBox_
) {
140 colorSchemeComboBox_
->setCurrentIndex(colorSchemeComboBox_
->findData(prefs_get_enum_value(pref_color_scheme_
, pref_stashed
)));
144 // Sample active selected item
146 colorstyle
= prefs_get_enum_value(pref_active_style_
, pref_stashed
);
148 // Make foreground and background colors
151 case COLOR_STYLE_DEFAULT
:
152 default_pal
= QApplication::palette();
153 default_pal
.setCurrentColorGroup(QPalette::Active
);
155 foreground
= default_pal
.highlightedText().color();
156 background1
= default_pal
.highlight().color();
157 background2
= default_pal
.highlight().color();
160 case COLOR_STYLE_FLAT
:
161 foreground
= ColorUtils::fromColorT(prefs_get_color_value(pref_active_fg_
, pref_stashed
));
162 background1
= ColorUtils::fromColorT(prefs_get_color_value(pref_active_bg_
, pref_stashed
));
163 background2
= ColorUtils::fromColorT(prefs_get_color_value(pref_active_bg_
, pref_stashed
));
166 case COLOR_STYLE_GRADIENT
:
167 foreground
= ColorUtils::fromColorT(prefs_get_color_value(pref_active_fg_
, pref_stashed
));
168 background1
= ColorUtils::fromColorT(prefs_get_color_value(pref_active_bg_
, pref_stashed
));
169 background2
= QColor::fromRgb(ColorUtils::alphaBlend(foreground
, background1
, COLOR_STYLE_ALPHA
));
173 ui
->activeFGPushButton
->setStyleSheet(color_button_ss
.arg(foreground
.name()).arg(margin
));
174 ui
->activeBGPushButton
->setStyleSheet(color_button_ss
.arg(background1
.name()).arg(0));
175 ui
->activeSampleLineEdit
->setStyleSheet(sample_text_ex_ss
.arg(
178 background2
.name()));
179 ui
->activeSampleLineEdit
->setFont(cur_font_
);
180 ui
->activeStyleComboBox
->setCurrentIndex(prefs_get_enum_value(pref_active_style_
, pref_stashed
));
182 // Show or hide the widgets
183 ui
->activeFGPushButton
->setVisible(colorstyle
!= COLOR_STYLE_DEFAULT
);
184 ui
->activeBGPushButton
->setVisible(colorstyle
!= COLOR_STYLE_DEFAULT
);
187 // Sample inactive selected item
189 colorstyle
= prefs_get_enum_value(pref_inactive_style_
, pref_stashed
);
191 // Make foreground and background colors
194 case COLOR_STYLE_DEFAULT
:
195 default_pal
= QApplication::palette();
196 default_pal
.setCurrentColorGroup(QPalette::Inactive
);
198 foreground
= default_pal
.highlightedText().color();
199 background1
= default_pal
.highlight().color();
200 background2
= default_pal
.highlight().color();
203 case COLOR_STYLE_FLAT
:
204 foreground
= ColorUtils::fromColorT(prefs_get_color_value(pref_inactive_fg_
, pref_stashed
));
205 background1
= ColorUtils::fromColorT(prefs_get_color_value(pref_inactive_bg_
, pref_stashed
));
206 background2
= ColorUtils::fromColorT(prefs_get_color_value(pref_inactive_bg_
, pref_stashed
));
209 case COLOR_STYLE_GRADIENT
:
210 foreground
= ColorUtils::fromColorT(prefs_get_color_value(pref_inactive_fg_
, pref_stashed
));
211 background1
= ColorUtils::fromColorT(prefs_get_color_value(pref_inactive_bg_
, pref_stashed
));
212 background2
= QColor::fromRgb(ColorUtils::alphaBlend(foreground
, background1
, COLOR_STYLE_ALPHA
));
216 ui
->inactiveFGPushButton
->setStyleSheet(color_button_ss
.arg(foreground
.name()).arg(margin
));
217 ui
->inactiveBGPushButton
->setStyleSheet(color_button_ss
.arg(background1
.name()).arg(0));
218 ui
->inactiveSampleLineEdit
->setStyleSheet(sample_text_ex_ss
.arg(
221 background2
.name()));
222 ui
->inactiveSampleLineEdit
->setFont(cur_font_
);
223 ui
->inactiveStyleComboBox
->setCurrentIndex(prefs_get_enum_value(pref_inactive_style_
, pref_stashed
));
225 // Show or hide the widgets
226 ui
->inactiveFGPushButton
->setVisible(colorstyle
!= COLOR_STYLE_DEFAULT
);
227 ui
->inactiveBGPushButton
->setVisible(colorstyle
!= COLOR_STYLE_DEFAULT
);
230 // Sample marked packet text
232 ui
->markedFGPushButton
->setStyleSheet(color_button_ss
.arg(
233 ColorUtils::fromColorT(prefs_get_color_value(pref_marked_fg_
, pref_stashed
)).name())
235 ui
->markedBGPushButton
->setStyleSheet(color_button_ss
.arg(
236 ColorUtils::fromColorT(prefs_get_color_value(pref_marked_bg_
, pref_stashed
)).name())
238 ui
->markedSampleLineEdit
->setStyleSheet(sample_text_ss
.arg(
239 ColorUtils::fromColorT(prefs_get_color_value(pref_marked_fg_
, pref_stashed
)).name(),
240 ColorUtils::fromColorT(prefs_get_color_value(pref_marked_bg_
, pref_stashed
)).name()));
241 ui
->markedSampleLineEdit
->setFont(cur_font_
);
244 // Sample ignored packet text
246 ui
->ignoredFGPushButton
->setStyleSheet(color_button_ss
.arg(
247 ColorUtils::fromColorT(prefs_get_color_value(pref_ignored_fg_
, pref_stashed
)).name())
249 ui
->ignoredBGPushButton
->setStyleSheet(color_button_ss
.arg(
250 ColorUtils::fromColorT(prefs_get_color_value(pref_ignored_bg_
, pref_stashed
)).name())
252 ui
->ignoredSampleLineEdit
->setStyleSheet(sample_text_ss
.arg(
253 ColorUtils::fromColorT(prefs_get_color_value(pref_ignored_fg_
, pref_stashed
)).name(),
254 ColorUtils::fromColorT(prefs_get_color_value(pref_ignored_bg_
, pref_stashed
)).name()));
255 ui
->ignoredSampleLineEdit
->setFont(cur_font_
);
258 // Sample "Follow Stream" client text
260 ui
->clientFGPushButton
->setStyleSheet(color_button_ss
.arg(
261 ColorUtils::fromColorT(prefs_get_color_value(pref_client_fg_
, pref_stashed
)).name())
263 ui
->clientBGPushButton
->setStyleSheet(color_button_ss
.arg(
264 ColorUtils::fromColorT(prefs_get_color_value(pref_client_bg_
, pref_stashed
)).name())
266 ui
->clientSampleLineEdit
->setStyleSheet(sample_text_ss
.arg(
267 ColorUtils::fromColorT(prefs_get_color_value(pref_client_fg_
, pref_stashed
)).name(),
268 ColorUtils::fromColorT(prefs_get_color_value(pref_client_bg_
, pref_stashed
)).name()));
269 ui
->clientSampleLineEdit
->setFont(cur_font_
);
272 // Sample "Follow Stream" server text
274 ui
->serverFGPushButton
->setStyleSheet(color_button_ss
.arg(
275 ColorUtils::fromColorT(prefs_get_color_value(pref_server_fg_
, pref_stashed
)).name())
277 ui
->serverBGPushButton
->setStyleSheet(color_button_ss
.arg(
278 ColorUtils::fromColorT(prefs_get_color_value(pref_server_bg_
, pref_stashed
)).name())
280 ui
->serverSampleLineEdit
->setStyleSheet(sample_text_ss
.arg(
281 ColorUtils::fromColorT(prefs_get_color_value(pref_server_fg_
, pref_stashed
)).name(),
282 ColorUtils::fromColorT(prefs_get_color_value(pref_server_bg_
, pref_stashed
)).name()));
283 ui
->serverSampleLineEdit
->setFont(cur_font_
);
286 // Sample valid filter
288 QColor ss_bg
= ColorUtils::fromColorT(prefs_get_color_value(pref_valid_bg_
, pref_stashed
));
289 ui
->validFilterBGPushButton
->setStyleSheet(color_button_ss
.arg(
290 ColorUtils::fromColorT(prefs_get_color_value(pref_valid_bg_
, pref_stashed
)).name())
292 ui
->validFilterSampleLineEdit
->setStyleSheet(sample_text_ss
.arg(
293 ColorUtils::contrastingTextColor(ss_bg
).name(),
297 // Sample invalid filter
299 ss_bg
= ColorUtils::fromColorT(prefs_get_color_value(pref_invalid_bg_
, pref_stashed
));
300 ui
->invalidFilterBGPushButton
->setStyleSheet(color_button_ss
.arg(
301 ColorUtils::fromColorT(prefs_get_color_value(pref_invalid_bg_
, pref_stashed
)).name())
303 ui
->invalidFilterSampleLineEdit
->setStyleSheet(sample_text_ss
.arg(
304 ColorUtils::contrastingTextColor(ss_bg
).name(),
308 // Sample warning filter
310 ss_bg
= ColorUtils::fromColorT(prefs_get_color_value(pref_deprecated_bg_
, pref_stashed
));
311 ui
->deprecatedFilterBGPushButton
->setStyleSheet(color_button_ss
.arg(
312 ColorUtils::fromColorT(prefs_get_color_value(pref_deprecated_bg_
, pref_stashed
)).name())
314 ui
->deprecatedFilterSampleLineEdit
->setStyleSheet(sample_text_ss
.arg(
315 ColorUtils::contrastingTextColor(ss_bg
).name(),
319 void FontColorPreferencesFrame::changeColor(pref_t
*pref
)
321 QColorDialog
*color_dlg
= new QColorDialog();
322 color_t
* color
= prefs_get_color_value(pref
, pref_stashed
);
324 color_dlg
->setCurrentColor(QColor(
330 connect(color_dlg
, &QColorDialog::colorSelected
, std::bind(&FontColorPreferencesFrame::colorChanged
, this, pref
, std::placeholders::_1
));
331 color_dlg
->setWindowModality(Qt::ApplicationModal
);
332 color_dlg
->setAttribute(Qt::WA_DeleteOnClose
);
336 void FontColorPreferencesFrame::colorChanged(pref_t
*pref
, const QColor
&cc
)
339 new_color
.red
= cc
.red() << 8 | cc
.red();
340 new_color
.green
= cc
.green() << 8 | cc
.green();
341 new_color
.blue
= cc
.blue() << 8 | cc
.blue();
342 prefs_set_color_value(pref
, new_color
, pref_stashed
);
346 void FontColorPreferencesFrame::colorSchemeIndexChanged(int)
348 if (colorSchemeComboBox_
) {
349 prefs_set_enum_value(pref_color_scheme_
, colorSchemeComboBox_
->currentData().toInt(), pref_stashed
);
350 // COLOR_SCHEME_DEFAULT is 0 so we don't need to check failure
355 void FontColorPreferencesFrame::on_fontPushButton_clicked()
358 QFont new_font
= QFontDialog::getFont(&ok
, cur_font_
, this, mainApp
->windowTitleString(tr("Font")));
360 prefs_set_string_value(pref_qt_gui_font_name_
, new_font
.toString().toStdString().c_str(), pref_stashed
);
361 cur_font_
= new_font
;
366 void FontColorPreferencesFrame::on_activeFGPushButton_clicked()
368 changeColor(pref_active_fg_
);
371 void FontColorPreferencesFrame::on_activeBGPushButton_clicked()
373 changeColor(pref_active_bg_
);
376 void FontColorPreferencesFrame::on_activeStyleComboBox_currentIndexChanged(int index
)
378 prefs_set_enum_value(pref_active_style_
, index
, pref_stashed
);
383 void FontColorPreferencesFrame::on_inactiveFGPushButton_clicked()
385 changeColor(pref_inactive_fg_
);
388 void FontColorPreferencesFrame::on_inactiveBGPushButton_clicked()
390 changeColor(pref_inactive_bg_
);
393 void FontColorPreferencesFrame::on_inactiveStyleComboBox_currentIndexChanged(int index
)
395 prefs_set_enum_value(pref_inactive_style_
, index
, pref_stashed
);
399 void FontColorPreferencesFrame::on_markedFGPushButton_clicked()
401 changeColor(pref_marked_fg_
);
404 void FontColorPreferencesFrame::on_markedBGPushButton_clicked()
406 changeColor(pref_marked_bg_
);
409 void FontColorPreferencesFrame::on_ignoredFGPushButton_clicked()
411 changeColor(pref_ignored_fg_
);
414 void FontColorPreferencesFrame::on_ignoredBGPushButton_clicked()
416 changeColor(pref_ignored_bg_
);
419 void FontColorPreferencesFrame::on_clientFGPushButton_clicked()
421 changeColor(pref_client_fg_
);
424 void FontColorPreferencesFrame::on_clientBGPushButton_clicked()
426 changeColor(pref_client_bg_
);
429 void FontColorPreferencesFrame::on_serverFGPushButton_clicked()
431 changeColor(pref_server_fg_
);
434 void FontColorPreferencesFrame::on_serverBGPushButton_clicked()
436 changeColor(pref_server_bg_
);
439 void FontColorPreferencesFrame::on_validFilterBGPushButton_clicked()
441 changeColor(pref_valid_bg_
);
444 void FontColorPreferencesFrame::on_invalidFilterBGPushButton_clicked()
446 changeColor(pref_invalid_bg_
);
449 void FontColorPreferencesFrame::on_deprecatedFilterBGPushButton_clicked()
451 changeColor(pref_deprecated_bg_
);