Skip to content

Commit 26284d6

Browse files
committed
Fixing error handling and adding tests
1 parent 7021689 commit 26284d6

File tree

6 files changed

+392
-13
lines changed

6 files changed

+392
-13
lines changed

__tests__/data/PhantomStyle.json

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
{
2+
"Id": "phantomstyle",
3+
"Name": "PhantomStyle",
4+
"Version": "15.0.1",
5+
"CompatVersion": "15.0.0",
6+
"Vendor": "Cristian Adam",
7+
"VendorId": "cristianadam",
8+
"Copyright": "(C) 2019 Andrew Richards, Cristian Adam, Copyright (C) The Qt Company Ltd. and other contributors.",
9+
"License": "GNU LGPL 2.1",
10+
"Description": "PhantomStyle for Qt Creator",
11+
"LongDescription": [
12+
"> And some say it's still using desktop computers, even to this day ",
13+
"",
14+
"",
15+
"![phantom screenshot light](https://raw.githubusercontent.com/wiki/randrew/phantomstyle/images/phantom_demo_1x_light_3.png)",
16+
"",
17+
"![phantom screenshot dark](https://raw.githubusercontent.com/wiki/randrew/phantomstyle/images/phantom_demo_1x_dark_3.png)",
18+
"",
19+
"[More screenshots](https://github.com/randrew/phantomstyle/wiki/Comparison-Screenshots)",
20+
"",
21+
"## Phantom Style",
22+
"",
23+
"Phantom is a QStyle for Qt which began as an overhaul of QFusionStyle. Similar",
24+
"to Fusion, it's designed to be a looks-the-same cross-platform style. It looks",
25+
"native to nobody, but familiar to many. It has the visual appearance of a",
26+
"traditional GUI, and does not adopt a \"modern flat\" style. Compared to Fusion,",
27+
"it has many fixes, objective improvements, and subjective improvements:",
28+
"",
29+
"* [Usage](#usage)",
30+
"* [Compatibility](#compatibility)",
31+
"* [Changes from QFusionStyle](#changes-from-qfusionstyle)",
32+
"* [License](#license)",
33+
"* [TODO](#todo)",
34+
"",
35+
"## Usage",
36+
"",
37+
"### Built into an application",
38+
"",
39+
"Add `src/phantom/phantom.pri` to your qmake .pro file for your project. There",
40+
"are no additional dependencies. It's also safe to construct a PhantomStyle",
41+
"object before instantiating a QApplication, because it doesn't interact with",
42+
"the environment or anything else.",
43+
"",
44+
"### As a QStylePlugin",
45+
"",
46+
"A style plugin is available: [phantomstyleplugin.pro](src/styleplugin/phantomstyleplugin.pro)",
47+
"",
48+
"## Compatibility",
49+
"",
50+
"Tested on Qt 5.9 and later, but should work on earlier versions as well. Builds",
51+
"with MSVC (tested with 2017), GCC and clang.",
52+
"",
53+
"Uses `auto` from C++11, so C++11 is needed. C++14 and later are not needed.",
54+
"",
55+
"## Changes from QFusionStyle",
56+
"",
57+
"* Fixed many code and logic errors: unaligned reads/writes, dead and",
58+
" unreachable code paths, redundant allocations, unused variables.",
59+
"",
60+
"* Fixed many drawing mistakes: filled regions which are never seen, off-by-1",
61+
" and misalignment, unnecessary QPainter transformations, unnecessary use of",
62+
" anti-aliasing for solid rectangles, misaligned arrows in scrollbar buttons",
63+
" and spinboxes, garbage lines and artifacts in the grooves of scrollbars.",
64+
"",
65+
"* Fixed bad drawing at high DPI: QPen lines which are misaligned, incorrect",
66+
" line thickness, broken and interrupted lines between connected elements (tabs",
67+
" and tab bars, etc.), misaligned or disconnect outlines and their associated",
68+
" inner fills, incorrect scaling of certain parts of a shape and others",
69+
" unscaled, unnecessary use of QPen anti-aliased lines to draw straight",
70+
" rectangles of constant width.",
71+
"",
72+
"* Fixed bad drawing in right-to-left layout: borders and outlines on the wrong",
73+
" side of rectangles (headers in item views, spinboxes, line edit borders),",
74+
" edges and off-by-1 adjustments made to bounding rectangles (tab frame and tab",
75+
" shapes, menu bar rulers, toolbar separators, grip handles), misalignment of",
76+
" icons and shapes (indicators in menu items, check boxes, radio button",
77+
" labels), clipped and invisible text (progress bar labels.)",
78+
"",
79+
"* Fixed broken metrics and sizing calculations for menu items, which over time",
80+
" lead to QFusionStyle having to have more and more \"safety space\" added to the",
81+
" horizontal size of menu items to avoid clipping stuff off. Phantom has",
82+
" correct sizing of menu items, and doesn't make menus any wider than",
83+
" necessary.",
84+
"",
85+
"* Replaced many constant sizes and pixel metrics with font-based calculations:",
86+
" menu items (and more) now derive their metrics from the font being used, so",
87+
" that they look more consistent across platforms which may use fonts for menus",
88+
" that are distinct from other widgets. A constant, even when DPI scaled, may",
89+
" give too little or too much space when the font size varies across a larger",
90+
" range than you predicted.",
91+
"",
92+
"* Removed all use of QPixmapCache.",
93+
"",
94+
" * QFusionStyle would aggressively cache the results of drawing certain shapes",
95+
" (buttons shapes, for example) based on the input parameters of the style",
96+
" option (size, state, palette, etc.) While this would speed up subsequent",
97+
" repaints with the same input parameters, the initial painting is slower.",
98+
"",
99+
" * QFusionStyle's use of QPixmapCache would lead to full occupancy of the",
100+
" global QPixmapCache almost immediately: create a window with a few buttons,",
101+
" then drag-resize the window. Within a few moments, all 10 megabytes of the",
102+
" default QPixmapCache have been filled. Not only does this bloat memory",
103+
" usage if the QPixmapCache would otherwise not have been used, but it causes",
104+
" legitimate uses of the QPixmapCache to have their contents evicted on a",
105+
" regular basis.",
106+
"",
107+
" * QFusionStyle's use of QPixmapCache requires allocating and deallocating",
108+
" string keys alongside what should have been simple painting operations.",
109+
"",
110+
" * QFusionStyle's generated cache keys were too fragile: in several cases, the",
111+
" cached pixmap would never be re-used, because the calculated cache key",
112+
" would never be the same on subsequent calls to draw the widget.",
113+
"",
114+
" * PhantomStyle draws significantly faster than QFusionStyle, and the caching",
115+
" is no longer needed.",
116+
"",
117+
"* Removed all use of gradients and explicit alpha blending.",
118+
"",
119+
" * QPainter has no color management, and on pixel buffers, blends in unmanaged",
120+
" 8-bit color. This means that blending operations between two colors (for",
121+
" example, a gradient, or an alpha blend of one color on top of another)",
122+
" produce unintuitive results. While your gradient that you chose and tested",
123+
" with a light color scheme might appear fine, when used with a QPalette with",
124+
" darker colors, the results may have far too little or too much contrast.",
125+
" Hue shifting and unintended darkening or lightening also may occur.",
126+
"",
127+
" * QPainter has no dithering capabilities, so banding would occur.",
128+
"",
129+
" * QPainter's gradients and alpha blending are slow.",
130+
"",
131+
" * The alpha blending done by QFusionStyle was almost always between two",
132+
" constant colors that were known ahead of time, such as a shadow on top of a",
133+
" base color, or a groupbox background on top of a window. The resulting",
134+
" blended color could instead simply be calculated ahead of time and painted",
135+
" as a solid rectangle, which is faster and can be color-corrected.",
136+
"",
137+
" * Overuse of gradients makes QFusionStyle look like it's from a specific time",
138+
" period (mid-2000s) instead of no time period at all.",
139+
"",
140+
" * Note that hue shifting and lightness shifting will still occur on the edges",
141+
" of anti-aliased shapes, like roundrect corners. This can only be solved by",
142+
" QPainter being changed to perform color-correct blending.",
143+
"",
144+
"* Changed derived color calculations to use CIELUV-like colorspace",
145+
"",
146+
" * QColor's .darker() and .lighter() were used by QFusionStyle to calculate",
147+
" derived colors from another color. For example, outlines on a box, or",
148+
" highlights on the inside of edges. QColor's .darker(), .lighter(),",
149+
" .lightness(), and other functions have no rigor or defined meaning -- the",
150+
" numbers are arbitrary and the output is unpredictable except when the",
151+
" input color is similar to whatever the programmer or designer tested it",
152+
" with. Using .lighter(120) on a near-black color will produce a different",
153+
" amount of contrast than .lighter(120) on a brighter color.",
154+
"",
155+
" * PhantomStyle instead uses a pseudo-CIELUV colorspace to derive its",
156+
" colors, provided by some core code from the hsluv-c library. While not",
157+
" perfect, it's a significant improvement, and allows PhantomStyle to more",
158+
" consistently work with both light and dark QPalettes.",
159+
"",
160+
"* Removed many implicit QPen and QBrush allocations caused by calling",
161+
" setBrush() and setPen() with QColor arguments. Instead, QPen and QBrush",
162+
" instances are now persisted in a small cache (in small flat array, not a",
163+
" QHash) that uses an accurate QPalette hash key calculation.",
164+
" (QPalette::cacheKey() is not used, because it is prone to changing even when",
165+
" the underlying values are the same.) This saves many, many small heap",
166+
" allocations that would occur when QFusionStyle was performing painting",
167+
" operations.",
168+
"",
169+
"* Disabled animations.",
170+
"",
171+
" * Though there are not many uses of animations in QtWidgets, they could cause",
172+
" problems. For example, dragging a QToolBar from its location in a",
173+
" QMainWindow to another location would attempt to animate the layout changes",
174+
" in the UI. But for complicated UIs in a large window, this would be too",
175+
" slow to re-layout and repaint in realtime, and the UI would freeze up",
176+
" during the time it should have been animating. This could cause the drop",
177+
" zone detection to give incorrect results, and then the UI would both",
178+
" stutter spastically *and* repeatedly freeze up during the drag operation.",
179+
"",
180+
"* Disabled and removed most mouse-over/hover repainting.",
181+
"",
182+
" * QFusionStyle, for many widgets, would paint with different colors when the",
183+
" user moused over certain elements, like buttons. However, on modern",
184+
" composited desktops and especially when combined with event coalescing and",
185+
" hardware-accelerated mouse drawing that skips the main compositing path,",
186+
" this would cause the repainting of widgets to appear to occur long after",
187+
" the mouse had already passed over the widget. The result would be a subtle",
188+
" and persistent feeling of lag throughout in the UI.",
189+
" ",
190+
" * For some widgets, QFusionStyle's alternate painting in the mouseover state",
191+
" was either not noticeable or identical, resulting in redundant repainting",
192+
" and event dispatching as the user moved their mouse cursor across the UI.",
193+
"",
194+
" * `Qt::WA_Hover` and alternate painting is still used where it makes good",
195+
" sense: menu items, tool buttons, and a few other cases.",
196+
"",
197+
"* Fixed style hints which affected the operation of QMenus.",
198+
"",
199+
" * QFusionStyle specified \"sloppy\" submenu closing via",
200+
" `SH_Menu_SloppySubMenus`, but didn't also specify that the submenus should",
201+
" not be closed after a timeout if nothing else is moused over",
202+
" (`SH_Menu_SubMenuDontStartSloppyOnLeave`). It also did not specify",
203+
" `SH_Menu_SubMenuUniDirection` and several other hints which should have",
204+
" been specified, which would cause the reactions of a QMenu to appear to lag",
205+
" behind the user's movements or to close submenus unnecessarily.",
206+
"",
207+
"* Fixed QMenuBar items not being highlighted when in alt-key navigation mode.",
208+
"",
209+
" * QFusionStyle specified the style hint allowing alt-key navigation for menu",
210+
" bars (`SH_MenuBar_AltKeyNavigation`) but did not actually draw the focused",
211+
" or highlighted menu bar item after the user had tapped the alt key. This",
212+
" would cause Windows and Linux users to assume that alt key navigation did",
213+
" not work in the program (because it had no visible indication that alt key",
214+
" navigation mode had been entered) when in fact it actually did have an",
215+
" effect, and would also cause the subsequent keypress on the keyboard to be",
216+
" eaten by the QMenuBar.",
217+
"",
218+
"* Altered the metrics of many widgets so that they align correctly.",
219+
"",
220+
" * Combo boxes are now the same height as push buttons, instead of being",
221+
" off-by-1-or-2.",
222+
"",
223+
" * Spinboxes are now the same height as line edits.",
224+
"",
225+
" * Decorations in item view items are now the same height as a line of text by",
226+
" default, so that decorated and undecorated items do not have differing row",
227+
" heights. (Manual specification of decoration size still works.)",
228+
"",
229+
" * Check marks and radio indicators are now visible alongside the icons in",
230+
" menu items, if both are specified.",
231+
"",
232+
"* The border around the \"current\" item in an item view is now drawn in a way",
233+
" that is actually visible, and is only drawn if necessary. The \"current\" focus",
234+
" rect will not be drawn if there there is only one item selected and the",
235+
" selected item is also the current item.",
236+
"",
237+
"* Added editable, compile-time parameters that control the styling of various",
238+
" things by editing a single constant in the source file:",
239+
"",
240+
" * Ratios for font-derived spacing and margins in menu items, line edits,",
241+
" check boxes, etc.",
242+
"",
243+
" * Separate and controllable roundrect radius for many widgets: group boxes,",
244+
" buttons, tool buttons, etc.",
245+
"",
246+
" * An alternate, faster code path using solid rect fills instead of",
247+
" anti-aliased roundrect is taken when a widget's rounding is set to 0 or",
248+
" near-0.",
249+
"",
250+
" * Internal \"sunken\" shadows on some large widgets (line edit, spinbox,",
251+
" progress bar) can be enabled or disabled.",
252+
"",
253+
" * Internal shadow can also be enabled or disabled for checkboxes and radio",
254+
" buttons.",
255+
"",
256+
" * Shadows in scrollbars can be enabled or disabled.",
257+
"",
258+
" * Tree view branch indicators can be made flush to the margin of the view",
259+
" (Classic Mac OS style) or aligned to the text of the item.",
260+
"",
261+
" * Item view decorations can be included in the visibly selected region or",
262+
" not.",
263+
"",
264+
" * Auto-raise for tool buttons in a tool bar by default can be enabled or",
265+
" disabled.",
266+
"",
267+
" * Use of QMenu or the Windows-style disclosure menu for combo boxes can be",
268+
" enabled or disabled.",
269+
"",
270+
" * Default decoration sizes based on fonts for item views can be enabled or",
271+
" disabled (when disabled, uses the default small pixmap size.)",
272+
"",
273+
"* No use of private Qt classes or code.",
274+
"",
275+
"* No warnings when building with -Wall.",
276+
"",
277+
"## License",
278+
"",
279+
"LGPL 2.1.",
280+
"",
281+
"I would prefer to give it a more permissive license, or the same license that",
282+
"the official code Qt has, which allows commercial projects to use the code",
283+
"without LGPL restrictions if they have a Qt license. However, I don't know how",
284+
"to do this, and I don't have time at the moment to figure it out. Please",
285+
"contact me or open a ticket if you can help with this. The PhantomStyle code",
286+
"originally started as a copy-and-paste of the Fusion code, but nearly none of",
287+
"the Fusion code remains at this point (just some stuff for drawing MDI window",
288+
"decorations and QDial.)",
289+
"",
290+
"## TODO",
291+
"",
292+
"* More screenshots",
293+
"* Several things haven't been fully tested (MDI windows, tick marks on sliders,",
294+
" a few more I can't think of.)",
295+
"* Probably lots of bugs",
296+
"",
297+
"```",
298+
"Phantom Style",
299+
"Copyright (C) 2019 Andrew Richards",
300+
"",
301+
"This library is free software; you can redistribute it and/or",
302+
"modify it under the terms of the GNU Library General Public",
303+
"License as published by the Free Software Foundation; either",
304+
"version 2 of the License, or (at your option) any later version.",
305+
"",
306+
"This library is distributed in the hope that it will be useful,",
307+
"but WITHOUT ANY WARRANTY; without even the implied warranty of",
308+
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU",
309+
"Library General Public License for more details.",
310+
"",
311+
"You should have received a copy of the GNU Library General Public",
312+
"License along with this library; if not, write to the",
313+
"Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,",
314+
"Boston, MA 02110-1301, USA.",
315+
"```"
316+
],
317+
"Url": "https://github.com/cristianadam/phantomstyle",
318+
"DocumentationUrl": "",
319+
"Dependencies": [{ "Id": "core", "Version": "15.0.1" }]
320+
}

0 commit comments

Comments
 (0)