PeriDyno 1.0.0
Loading...
Searching...
No Matches
StyleTools.cpp
Go to the documentation of this file.
1/*
2 TabToolbar - a small utility library for Qt, providing tabbed toolbars
3 Copyright (C) 2018 Oleksii Sierov
4
5 TabToolbar is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TabToolbar is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with TabToolbar. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include <QApplication>
19#include <QFile>
20#include <QLocale>
21#include <QMap>
22#include <QMetaProperty>
23#include <QScreen>
24#include <QStyle>
25#include <QSysInfo>
26#include <QtGlobal>
27#include <QWidget>
28#if (QT_VERSION <= QT_VERSION_CHECK(5, 10, 0))
29#include <QDesktopWidget>
30#endif
31#include <stdexcept>
32#include <cstddef>
33
34#include "StyleTools.h"
35
36namespace tt
37{
38
39static std::unique_ptr<QMap<QString, TStyleCreator>> styleMap;
40
41static QString GetStyleTemplate()
42{
43 static QString styleTemplate;
44 if(!styleTemplate.isEmpty())
45 return styleTemplate;
46
47 //QFile f(":/qdarkstyle/dark/darkstyle.qss");
48 //QFile f(":/dyno/DarkStyle.qss");
49 QFile f(":/dyno/DefaultStyle.qss");
50 f.open(QFile::ReadOnly);
51 styleTemplate = f.readAll();
52 return styleTemplate;
53}
54
55static QString FormatColor(const QColor& col)
56{
57 return QString("rgba(%1, %2, %3, %4)")
58 .arg(col.red())
59 .arg(col.green())
60 .arg(col.blue())
61 .arg(col.alpha());
62}
63
64static QString FormatColor(const Colors& colors)
65{
66 const std::size_t sz = colors.size();
67 if(sz == 1)
68 return FormatColor(colors[0].value);
69
70 QString result = "qlineargradient(x1:0, y1:1, x2:0, y2:0";
71 for(const Color& col : colors)
72 result += QString(", stop:") + QString::number(col.coefficient) + " " + FormatColor(col.value);
73 result += ")";
74
75 return result;
76}
77
78static void FillStyle(QString& style, const StyleParams& params)
79{
80 style.clear();
81 if(params.UseTemplateSheet)
82 style = GetStyleTemplate();
83 style += params.AdditionalStyleSheet;
84
85 int numProps = params.metaObject()->propertyCount();
86 for(int i=0; i<numProps; i++)
87 {
88 const QMetaProperty prop = params.metaObject()->property(i);
89 if(QString(prop.name()) == "objectName")
90 continue;
91 if(prop.type() == QVariant::Bool)
92 continue;
93 const QString propStr = QString("%") + prop.name() + "%";
94 if(!style.contains(propStr))
95 continue;
96 style.replace(propStr, "%1");
97
98 const QVariant property = params.property(prop.name());
99 switch(prop.type())
100 {
101 case QVariant::String:
102 style = style.arg(property.toString() + "px");
103 break;
104 case QVariant::Int:
105 style = style.arg(property.toInt());
106 break;
107 case QVariant::UserType:
108 {
109 const Colors& colors = property.value<Colors>();
110 if(colors.size() == 0)
111 throw std::runtime_error("Some property has no colors!");
112 style = style.arg(FormatColor(colors));
113 break;
114 }
115 default:
116 throw std::runtime_error("Unknown property type in style!");
117 }
118 }
119}
120
121bool IsStyleRegistered(const QString& styleName)
122{
123 return styleMap->contains(styleName);
124}
125
126std::unique_ptr<StyleParams> CreateStyle(const QString& styleName)
127{
128 if (styleMap == nullptr)
129 {
130 struct TPalette
131 {
132 TPalette()
133 {
134 const QPalette p;
135 light = p.light().color();
136 midlight = p.midlight().color();
137 dark = p.dark().color();
138 window = p.window().color();
139 text = p.text().color();
140 highlight = p.highlight().color();
141 htext = p.highlightedText().color();
142 }
143
144 QColor htext;
145 QColor highlight;
146 QColor light;
147 QColor midlight;
148 QColor dark;
149 QColor window;
150 QColor text;
151 };
152
153 auto clampColor = [](int v)
154 {
155 if (v < 0)
156 return 0;
157 if (v > 255)
158 return 255;
159 return v;
160 };
161 auto lcomb = [clampColor](const QColor& c1, const QColor& c2, float f)
162 {
163 const float fi = 1.0f - f;
164 return QColor(clampColor(c1.red() *f + c2.red() *fi),
165 clampColor(c1.green()*f + c2.green()*fi),
166 clampColor(c1.blue() *f + c2.blue() *fi),
167 clampColor(c1.alpha()*f + c2.alpha()*fi));
168 };
169 auto dimmed = [lcomb](const QColor& c, float factor)
170 {
171 return lcomb(c, Qt::black, 1.0f - factor);
172 };
173 auto coeff = [clampColor](const QColor& c, float cr, float cg, float cb)
174 {
175 return QColor(clampColor(c.red() * cr), clampColor(c.green() * cg), clampColor(c.blue() * cb));
176 };
177 auto add = [clampColor](const QColor& c1, const QColor& c2)
178 {
179 return QColor(clampColor(c1.red() + c2.red()),
180 clampColor(c1.green() + c2.green()),
181 clampColor(c1.blue() + c2.blue()),
182 clampColor(c1.alpha() + c2.alpha()));
183 };
184 auto toBase = [](const QColor& c)
185 {
186 const int minColor = std::min(std::min(c.red(), c.green()), c.blue());
187 return QColor(c.red() - minColor,
188 c.green() - minColor,
189 c.blue() - minColor);
190 };
191
192 RegisterStyle(g_styleKool, [lcomb, dimmed]()
193 {
194 const TPalette p;
195 StyleParams* params = new StyleParams();
196
197 params->UseTemplateSheet = true;
198 params->AdditionalStyleSheet = "";
199 params->TabBorderRadius = 0;
200 params->TabFontColor = p.text;
201 params->ToolbarBackgroundColor = p.window;
202 params->BorderColor = dimmed(p.light, 0.25f);
203 params->GroupNameColor = lcomb(p.text, p.midlight, 0.4f);
204
205 params->TabSpecialColor = { {0.0f, dimmed(p.highlight, 0.2f)},
206 {1.0f, p.highlight} };
207
208 params->TabSpecialHoverColor = { {0.0f, params->TabSpecialColor[1].value},
209 {1.0f, params->TabSpecialColor[0].value} };
210
211 params->TabSpecialHoverBorderColor = p.highlight;
212 params->TabSpecialHoverBorderColorSide = params->TabSpecialHoverBorderColor;
213 params->TabSpecialBorderColor = p.highlight;
214 params->TabSpecialBorderColorSide = params->TabSpecialBorderColor;
215 params->TabSpecialFontColor = p.htext;
216
217 params->TabUnselectedHoverBorderColorTop =
218 params->TabHoverBorderColorTop = p.highlight;
219
220 params->TabUnselectedHoverBorderColorSide =
221 params->TabHoverBorderColorSide = { {0.0f, params->BorderColor},
222 {0.1f, params->BorderColor},
223 {0.7f, params->TabHoverBorderColorTop},
224 {1.0f, params->TabHoverBorderColorTop} };
225
226 params->PaneColor = { {0.0f, dimmed(p.light, 0.1f)},
227 {0.7f, p.light},
228 {1.0f, p.light} };
229
230 params->TabSelectedColor = p.light;
231
232 params->TabUnselectedColor = lcomb(params->ToolbarBackgroundColor, params->TabSelectedColor[0].value, 0.5f);
233
234 params->SeparatorColor = { {0.0f, Qt::transparent},
235 {0.05f, Qt::transparent},
236 {0.1f, params->BorderColor},
237 {0.9f, params->BorderColor},
238 {0.95f, Qt::transparent},
239 {1.0f, Qt::transparent} };
240
241 params->HorizontalFrameBackgroundColor = params->PaneColor;
242 for (auto& c : params->HorizontalFrameBackgroundColor)
243 c.value.setAlpha(100);
244 params->HorizontalFrameBorderColor = params->BorderColor;
245 params->HorizontalFrameBorderSize = 2;
246 params->TabSpacing = 3;
247
248 params->HideArrowColor = lcomb(p.text, p.midlight, 0.4f);
249 return params;
250 });
251
252 RegisterStyle(g_styleVienna, [lcomb, dimmed, coeff, add, toBase]()
253 {
254 const TPalette p;
255 const QColor vienna = (p.window.lightnessF() > 0.5f ? QColor(51, 153, 255) : QColor(25, 40, 70));
256 StyleParams* params = new StyleParams();
257
258 params->UseTemplateSheet = true;
259 params->AdditionalStyleSheet = "";
260 params->TabBorderRadius = 2;
261 params->TabFontColor = lcomb(p.text, vienna, 0.588f);
262 params->ToolbarBackgroundColor = add(dimmed(p.window, 0.07f), toBase(dimmed(vienna, 0.892f)));
263 const float dimmCoeff = (p.window.lightnessF() > 0.5f ? 0.225f : 0.5f);
264 params->BorderColor = add(dimmed(p.window, dimmCoeff), toBase(dimmed(vienna, 0.838f)));
265 params->GroupNameColor = lcomb(p.text, params->ToolbarBackgroundColor, 0.484f);
266
267 params->PaneColor = { {0.0f, params->ToolbarBackgroundColor},
268 {0.5f, params->ToolbarBackgroundColor},
269 {0.75f, lcomb(params->ToolbarBackgroundColor, p.light, 0.5f)},
270 {1.0f, p.light} };
271
272 params->TabSpecialColor = { {0.0f, add(dimmed(p.window, 0.7125f), coeff(toBase(dimmed(p.highlight, 0.294f)), 1.0f, 1.29f, 1.0f))},
273 {0.6f, add(dimmed(p.window, 0.891f), coeff(toBase(dimmed(p.highlight, 0.46f)), 1.0f, 0.69f, 1.0f))},
274 {0.6001f, add(dimmed(p.window, 0.825f), coeff(toBase(dimmed(p.highlight, 0.362f)), 1.0f, 0.815f, 1.0f))},
275 {1.0f, add(dimmed(p.window, 0.7125f), coeff(toBase(dimmed(p.highlight, 0.416f)), 1.0f, 0.924f, 1.0f))} };
276
277 params->TabSpecialHoverColor = { {0.0f, coeff(params->TabSpecialColor[0].value, 2.17f, 1.48f, 1.197f)},
278 {0.6f, coeff(params->TabSpecialColor[1].value, 0.653f, 1.218f, 1.286f)},
279 {0.6001f, coeff(params->TabSpecialColor[2].value, 1.69f, 1.326f, 1.191f)},
280 {1.0f, coeff(params->TabSpecialColor[3].value, 1.768f, 1.44f, 1.255f)} };
281
282 params->TabSpecialHoverBorderColor =
283 params->TabSpecialBorderColor = add(dimmed(p.window, 0.729f), coeff(toBase(dimmed(p.highlight, 0.392f)), 1.0f, 0.66f, 1.0f));
284 params->TabSpecialHoverBorderColorSide =
285 params->TabSpecialBorderColorSide = params->TabSpecialBorderColor;
286 params->TabSpecialFontColor = p.htext;
287
288 params->TabUnselectedHoverBorderColorTop =
289 params->TabHoverBorderColorTop = QColor(255, 183, 0);
290
291 params->TabUnselectedHoverBorderColorSide =
292 params->TabHoverBorderColorSide = { {0.0f, params->BorderColor},
293 {0.3f, QColor(255, 183, 0)},
294 {1.0f, QColor(255, 183, 0)} };
295
296 params->TabUnselectedColor = add(dimmed(p.window, 0.02f), toBase(dimmed(vienna, 0.9264f)));
297
298 params->TabSelectedColor = p.light;
299
300 params->SeparatorColor = { {0.0f, Qt::transparent},
301 {0.075f, Qt::transparent},
302 {0.0751f, add(dimmed(p.window, 0.3125f), toBase(dimmed(vienna, 0.789f)))},
303 {0.925f, add(dimmed(p.window, 0.3125f), toBase(dimmed(vienna, 0.789f)))},
304 {0.9251f, Qt::transparent},
305 {1.0f, Qt::transparent} };
306
307 params->HorizontalFrameBackgroundColor =
308 { {0.0f, add(dimmed(p.window, 0.033f), coeff(toBase(dimmed(vienna, 0.9362f)), 1.0f, 1.38f, 1.0f))},
309 {0.6f, add(dimmed(p.window, 0.05f), coeff(toBase(dimmed(vienna, 0.8333f)), 1.0f, 0.588f, 1.0f))},
310 {0.6001f, add(p.window, coeff(toBase(dimmed(vienna, 0.9166f)), 1.0f, 0.82f, 1.0f))},
311 {1.0f, p.light} };
312
313 params->HorizontalFrameBorderColor = params->BorderColor;
314 params->HorizontalFrameBorderSize = 2;
315 params->TabSpacing = 4;
316
317 params->HideArrowColor = lcomb(p.text, p.light, 0.62f);
318 return params;
319 });
320
321 RegisterStyle(g_styleThreshold, [lcomb, dimmed, coeff]()
322 {
323 const TPalette p;
324 StyleParams* params = new StyleParams();
325
326 params->UseTemplateSheet = true;
327 params->AdditionalStyleSheet = "";
328 params->TabBorderRadius = 0;
329 params->TabFontColor = p.text;
330 params->ToolbarBackgroundColor = p.light;
331 const float paneDimmCoeff = (p.window.lightnessF() > 0.5f ? 0.03529f : 0.1f);
332 params->PaneColor = dimmed(p.light, paneDimmCoeff);
333 const float borderDimmCoeff = (p.window.lightnessF() > 0.5f ? 0.15f : 0.3f);
334 params->BorderColor = dimmed(params->ToolbarBackgroundColor, borderDimmCoeff);
335 params->GroupNameColor = lcomb(p.text, p.light, 0.43f);
336
337 params->TabSpecialColor = coeff(p.highlight, 0.5f, 0.8f, 0.8f);
338 params->TabSpecialHoverColor = coeff(p.highlight, 0.8f, 0.9f, 0.88f);
339 params->TabSpecialHoverBorderColor =
340 params->TabSpecialBorderColor = params->TabSpecialColor;
341 params->TabSpecialHoverBorderColorSide =
342 params->TabSpecialBorderColorSide = params->TabSpecialColor;
343 params->TabSpecialFontColor = p.htext;
344
345 params->TabUnselectedHoverBorderColorTop = dimmed(params->PaneColor, 0.04f);
346 params->TabHoverBorderColorTop = params->BorderColor;
347 params->TabUnselectedHoverBorderColorSide = params->TabUnselectedHoverBorderColorTop;
348
349 params->TabHoverBorderColorSide = params->BorderColor;
350
351 const float unselectedDimmCoeff = (p.window.lightnessF() > 0.5f ? 0.008f : 0.1f);
352 params->TabUnselectedColor = dimmed(params->ToolbarBackgroundColor, unselectedDimmCoeff);
353
354 params->TabSelectedColor = params->PaneColor;
355
356 params->SeparatorColor = { {0.0f, Qt::transparent},
357 {0.05f, Qt::transparent},
358 {0.051f, params->BorderColor},
359 {0.95f, params->BorderColor},
360 {0.951f, Qt::transparent},
361 {1.0f, Qt::transparent} };
362
363 params->HorizontalFrameBackgroundColor = Qt::transparent;
364 params->HorizontalFrameBorderColor = Qt::transparent;
365 params->HorizontalFrameBorderSize = 0;
366 params->TabSpacing = 2;
367
368 params->HideArrowColor = lcomb(p.text, p.light, 0.62f);
369 return params;
370 });
371
372 RegisterStyle("White Mercy", [dimmed]()
373 {
374 StyleParams* params = CreateStyle(g_styleThreshold).release();
375 params->TabUnselectedColor = params->PaneColor;
376 params->PaneColor = params->ToolbarBackgroundColor;
377 params->TabSelectedColor = params->PaneColor;
378 params->BorderColor = dimmed(params->BorderColor, 0.1f);
379 params->TabHoverBorderColorTop = params->BorderColor;
380 params->TabHoverBorderColorSide = params->BorderColor;
381 params->SeparatorColor = { {0.0f, Qt::transparent},
382 {0.05f, Qt::transparent},
383 {0.051f, params->BorderColor},
384 {0.95f, params->BorderColor},
385 {0.951f, Qt::transparent},
386 {1.0f, Qt::transparent} };
387 return params;
388 });
389 }
390
391
392 auto creator = styleMap->find(styleName);
393 if(creator == styleMap->end())
394 throw std::runtime_error(styleName.toStdString() + " - style is not registered!");
395
396 StyleParams* style = (*creator)();
397 style->setObjectName(styleName);
398 return std::unique_ptr<StyleParams>(style);
399}
400
401QString GetSheetForStyle(const StyleParams& style)
402{
403 QString styleString;
404 FillStyle(styleString, style);
405 return styleString;
406}
407
408void RegisterStyle(const QString& styleName, const TStyleCreator& creator)
409{
410 if(!styleMap)
411 styleMap.reset(new QMap<QString, TStyleCreator>());
412 if(styleMap->contains(styleName))
413 throw std::runtime_error(styleName.toStdString() + " - style already registered!");
414
415 styleMap->insert(styleName, creator);
416}
417
418void UnregisterStyle(const QString& styleName)
419{
420 styleMap->remove(styleName);
421}
422
424{
425 return styleMap->keys();
426}
427
429{
430#if defined(Q_OS_UNIX)
431 return g_styleKool;
432#elif defined(Q_OS_WIN)
433 QString versionStr = QSysInfo::kernelVersion();
434 const int dotIndex = versionStr.indexOf('.');
435 if(dotIndex != -1)
436 versionStr = versionStr.left(dotIndex + 2);
437 versionStr.replace('.', '0');
438 bool ok = false;
439 const double versionDouble = QLocale().toDouble(versionStr, &ok);
440 if(!ok)
441 return g_styleKool;
442 if(versionDouble >= 602)
443 return g_styleThreshold;
444 return g_styleVienna;
445#endif
446}
447
448float GetScaleFactor(const QWidget& widget)
449{
450#if (QT_VERSION <= QT_VERSION_CHECK(5, 10, 0))
451 auto scrNumber = QApplication::desktop()->screenNumber(widget.mapToGlobal(QPoint(0,0)));
452 auto screens = QGuiApplication::screens();
453 QScreen* scr = screens.at(scrNumber);
454#else
455 QScreen* scr = QGuiApplication::screenAt(widget.mapToGlobal(QPoint(0,0)));
456#endif
457 const float defaultDpi = 96.0f;
458 return scr->logicalDotsPerInchY() / defaultDpi;
459}
460
461int GetPixelMetric(QStyle::PixelMetric metric)
462{
463 switch(metric)
464 {
465 case QStyle::PM_SmallIconSize:
466 return 16;
467 case QStyle::PM_LargeIconSize:
468 return 32;
469 default:
470 return QApplication::style()->pixelMetric(metric);
471 }
472}
473
474}//namespace tt
TVectorType::size_type size() const
Definition Styles.h:67
bool UseTemplateSheet
Definition Styles.h:127
QString AdditionalStyleSheet
Definition Styles.h:128
Definition Builder.h:33
TT_API const QString g_styleVienna
Definition Styles.cpp:25
void RegisterStyle(const QString &styleName, const TStyleCreator &creator)
static QString FormatColor(const QColor &col)
bool IsStyleRegistered(const QString &styleName)
QString GetDefaultStyle()
TT_API const QString g_styleThreshold
Definition Styles.cpp:26
static void FillStyle(QString &style, const StyleParams &params)
static QString GetStyleTemplate()
int GetPixelMetric(QStyle::PixelMetric metric)
float GetScaleFactor(const QWidget &widget)
QStringList GetRegisteredStyles()
QString GetSheetForStyle(const StyleParams &style)
std::unique_ptr< StyleParams > CreateStyle(const QString &styleName)
static std::unique_ptr< QMap< QString, TStyleCreator > > styleMap
TT_API const QString g_styleKool
Definition Styles.cpp:24
void UnregisterStyle(const QString &styleName)
std::function< StyleParams *()> TStyleCreator
Definition StyleTools.h:31