gitcmds: fix pylint violations
[git-cola.git] / cola / themes.py
bloba474ac6a7fbe3219d2580019aa0371b68482db0a
1 """Provides themes generator"""
2 from __future__ import absolute_import, division, unicode_literals
4 from qtpy import QtGui
6 from .i18n import N_
7 from .widgets import defs
8 from . import icons
9 from . import qtutils
12 class EStylesheet(object):
13 DEFAULT = 1
14 FLAT = 2
17 class Theme(object):
18 def __init__(
19 self, name, hr_name, is_dark, style_sheet=EStylesheet.DEFAULT, main_color=None
21 self.name = name
22 self.hr_name = hr_name
23 self.is_dark = is_dark
24 self.style_sheet = style_sheet
25 self.main_color = main_color
27 def build_style_sheet(self, app_palette):
28 if self.style_sheet == EStylesheet.FLAT:
29 return self.style_sheet_flat()
30 else:
31 return self.style_sheet_default(app_palette)
33 def build_palette(self, app_palette):
34 QPalette = QtGui.QPalette
35 palette_dark = app_palette.color(QPalette.Base).lightnessF() < 0.5
37 if palette_dark and self.is_dark:
38 return app_palette
39 if not palette_dark and not self.is_dark:
40 return app_palette
41 if self.is_dark:
42 bg_color = QtGui.QColor('#202025')
43 else:
44 bg_color = QtGui.QColor('#edeef3')
46 txt_color = QtGui.QColor('#777')
47 palette = QPalette(bg_color)
48 palette.setColor(QPalette.Base, bg_color)
49 palette.setColor(QPalette.Disabled, QPalette.Text, txt_color)
50 return palette
52 @staticmethod
53 def style_sheet_default(palette):
54 window = palette.color(QtGui.QPalette.Window)
55 highlight = palette.color(QtGui.QPalette.Highlight)
56 shadow = palette.color(QtGui.QPalette.Shadow)
57 base = palette.color(QtGui.QPalette.Base)
59 window_rgb = qtutils.rgb_css(window)
60 highlight_rgb = qtutils.rgb_css(highlight)
61 shadow_rgb = qtutils.rgb_css(shadow)
62 base_rgb = qtutils.rgb_css(base)
64 return """
65 QCheckBox::indicator {
66 width: %(checkbox_size)spx;
67 height: %(checkbox_size)spx;
69 QCheckBox::indicator::unchecked {
70 border: %(checkbox_border)spx solid %(shadow_rgb)s;
71 background: %(base_rgb)s;
73 QCheckBox::indicator::checked {
74 image: url(%(checkbox_icon)s);
75 border: %(checkbox_border)spx solid %(shadow_rgb)s;
76 background: %(base_rgb)s;
79 QRadioButton::indicator {
80 width: %(radio_size)spx;
81 height: %(radio_size)spx;
83 QRadioButton::indicator::unchecked {
84 border: %(radio_border)spx solid %(shadow_rgb)s;
85 border-radius: %(radio_radius)spx;
86 background: %(base_rgb)s;
88 QRadioButton::indicator::checked {
89 image: url(%(radio_icon)s);
90 border: %(radio_border)spx solid %(shadow_rgb)s;
91 border-radius: %(radio_radius)spx;
92 background: %(base_rgb)s;
95 QSplitter::handle:hover {
96 background: %(highlight_rgb)s;
99 QMainWindow::separator {
100 background: %(window_rgb)s;
101 width: %(separator)spx;
102 height: %(separator)spx;
104 QMainWindow::separator:hover {
105 background: %(highlight_rgb)s;
108 """ % dict(
109 separator=defs.separator,
110 window_rgb=window_rgb,
111 highlight_rgb=highlight_rgb,
112 shadow_rgb=shadow_rgb,
113 base_rgb=base_rgb,
114 checkbox_border=defs.border,
115 checkbox_icon=icons.check_name(),
116 checkbox_size=defs.checkbox,
117 radio_border=defs.radio_border,
118 radio_icon=icons.dot_name(),
119 radio_radius=defs.radio // 2,
120 radio_size=defs.radio,
123 def style_sheet_flat(self):
124 main_color = self.main_color
125 color = QtGui.QColor(main_color)
126 color_rgb = qtutils.rgb_css(color)
128 if self.is_dark:
129 background = '#2e2f30'
130 field = '#383a3c'
131 grayed = '#06080a'
132 button_text = '#000000'
133 field_text = '#d0d0d0'
134 darker = qtutils.hsl_css(
135 color.hslHueF(), color.hslSaturationF() * 0.3, color.lightnessF() * 1.3
137 lighter = qtutils.hsl_css(
138 color.hslHueF(), color.hslSaturationF() * 0.7, color.lightnessF() * 0.6
140 focus = qtutils.hsl_css(
141 color.hslHueF(), color.hslSaturationF() * 0.7, color.lightnessF() * 0.7
143 else:
144 background = '#edeef3'
145 field = '#ffffff'
146 grayed = '#a2a2b0'
147 button_text = '#ffffff'
148 field_text = '#000000'
149 darker = qtutils.hsl_css(
150 color.hslHueF(), color.hslSaturationF(), color.lightnessF() * 0.4
152 lighter = qtutils.hsl_css(color.hslHueF(), color.hslSaturationF() * 2, 0.92)
153 focus = color_rgb
155 return """
156 /* regular widgets */
158 background-color: %(background)s;
159 color: %(field_text)s;
160 selection-background-color: %(lighter)s;
161 alternate-background-color: %(field)s;
162 selection-color: %(field_text)s;
163 show-decoration-selected: 1;
164 spacing: 2px;
167 /* Focused widths get a thin border */
168 QTreeView:focus, QListView:focus,
169 QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {
170 border-width: 1px;
171 border-style: solid;
172 border-color: %(focus)s;
175 QWidget:disabled {
176 border-color: %(grayed)s;
177 color: %(grayed)s;
179 QDockWidget > QFrame {
180 margin: 0 2px 2px 2px;
181 min-height: 40px;
183 QPlainTextEdit, QLineEdit, QTextEdit, QAbstractItemView,
184 QAbstractSpinBox {
185 background-color: %(field)s;
186 border-color: %(grayed)s;
187 border-style: solid;
188 border-width: 1px;
190 QAbstractItemView::item:selected {
191 background-color: %(lighter)s;
193 QAbstractItemView::item:hover {
194 background-color: %(lighter)s;
196 QLabel {
197 color: %(darker)s;
198 background-color: transparent;
200 DockTitleBarWidget {
201 padding-bottom: 4px;
204 /* buttons */
205 QPushButton[flat="false"] {
206 background-color: %(button)s;
207 color: %(button_text)s;
208 border-radius: 2px;
209 border-width: 0;
210 margin-bottom: 1px;
211 min-width: 55px;
212 padding: 4px 5px;
214 QPushButton[flat="true"], QToolButton {
215 background-color: transparent;
216 border-radius: 0px;
218 QPushButton[flat="true"] {
219 margin-bottom: 10px;
221 QPushButton:hover, QToolButton:hover {
222 background-color: %(darker)s;
224 QPushButton[flat="false"]:pressed, QToolButton:pressed {
225 background-color: %(darker)s;
226 margin: 1px 1px 2px 1px;
228 QPushButton:disabled {
229 background-color: %(grayed)s;
230 color: %(field)s;
231 padding-left: 5px;
232 padding-top: 5px;
234 QPushButton[flat="true"]:disabled {
235 background-color: transparent;
238 /*menus*/
239 QMenuBar {
240 background-color: %(background)s;
241 color: %(field_text)s;
242 border-width: 0;
243 padding: 1px;
245 QMenuBar::item {
246 background: transparent;
248 QMenuBar::item:selected {
249 background: %(button)s;
251 QMenuBar::item:pressed {
252 background: %(button)s;
254 QMenu {
255 background-color: %(field)s;
257 QMenu::separator {
258 background: %(background)s;
259 height: 1px;
262 /* combo box */
263 QComboBox {
264 background-color: %(field)s;
265 border-color: %(grayed)s;
266 border-style: solid;
267 color: %(field_text)s;
268 border-radius: 0px;
269 border-width: 1px;
270 margin-bottom: 1px;
271 padding: 0 5px;
273 QComboBox::drop-down {
274 border-color: %(field_text)s %(field)s %(field)s %(field)s;
275 border-style: solid;
276 subcontrol-position: right;
277 border-width: 4px 3px 0 3px;
278 height: 0;
279 margin-right: 5px;
280 width: 0;
282 QComboBox::drop-down:hover {
283 border-color: %(button)s %(field)s %(field)s %(field)s;
285 QComboBox:item {
286 background-color: %(button)s;
287 color: %(button_text)s;
288 border-width: 0;
289 height: 22px;
291 QComboBox:item:selected {
292 background-color: %(darker)s;
293 color: %(button_text)s;
295 QComboBox:item:checked {
296 background-color: %(darker)s;
297 color: %(button_text)s;
300 /* MainWindow separator */
301 QMainWindow::separator {
302 width: %(separator)spx;
303 height: %(separator)spx;
305 QMainWindow::separator:hover {
306 background: %(focus)s;
309 /* scroll bar */
310 QScrollBar {
311 background-color: %(field)s;
312 border: 0;
314 QScrollBar::handle {
315 background: %(background)s
317 QScrollBar::handle:hover {
318 background: %(button)s
320 QScrollBar:horizontal {
321 margin: 0 11px 0 11px;
322 height: 10px;
324 QScrollBar:vertical {
325 margin: 11px 0 11px 0;
326 width: 10px;
328 QScrollBar::add-line, QScrollBar::sub-line {
329 background: %(background)s;
330 subcontrol-origin: margin;
332 QScrollBar::sub-line:horizontal { /*required by a buggy Qt version*/
333 subcontrol-position: left;
335 QScrollBar::add-line:hover, QScrollBar::sub-line:hover {
336 background: %(button)s;
338 QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
339 width: 10px;
341 QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
342 height: 10px;
344 QScrollBar:left-arrow, QScrollBar::right-arrow,
345 QScrollBar::up-arrow, QScrollBar::down-arrow {
346 border-style: solid;
347 height: 0;
348 width: 0;
350 QScrollBar:right-arrow {
351 border-color: %(background)s %(background)s
352 %(background)s %(darker)s;
353 border-width: 3px 0 3px 4px;
355 QScrollBar:left-arrow {
356 border-color: %(background)s %(darker)s
357 %(background)s %(background)s;
358 border-width: 3px 4px 3px 0;
360 QScrollBar:up-arrow {
361 border-color: %(background)s %(background)s
362 %(darker)s %(background)s;
363 border-width: 0 3px 4px 3px;
365 QScrollBar:down-arrow {
366 border-color: %(darker)s %(background)s
367 %(background)s %(background)s;
368 border-width: 4px 3px 0 3px;
370 QScrollBar:right-arrow:hover {
371 border-color: %(button)s %(button)s
372 %(button)s %(darker)s;
374 QScrollBar:left-arrow:hover {
375 border-color: %(button)s %(darker)s
376 %(button)s %(button)s;
378 QScrollBar:up-arrow:hover {
379 border-color: %(button)s %(button)s
380 %(darker)s %(button)s;
382 QScrollBar:down-arrow:hover {
383 border-color: %(darker)s %(button)s
384 %(button)s %(button)s;
387 /* tab bar (stacked & docked widgets) */
388 QTabBar::tab {
389 background: transparent;
390 border-color: %(darker)s;
391 border-width: 1px;
392 margin: 1px;
393 padding: 3px 5px;
395 QTabBar::tab:selected {
396 background: %(grayed)s;
399 /* check box */
400 QCheckBox {
401 spacing: 8px;
402 margin: 4px;
403 background-color: transparent;
405 QCheckBox::indicator {
406 background-color: %(field)s;
407 border-color: %(darker)s;
408 border-style: solid;
409 subcontrol-position: left;
410 border-width: 1px;
411 height: 13px;
412 width: 13px;
414 QCheckBox::indicator:unchecked:hover {
415 background-color: %(button)s;
417 QCheckBox::indicator:unchecked:pressed {
418 background-color: %(darker)s;
420 QCheckBox::indicator:checked {
421 background-color: %(darker)s;
423 QCheckBox::indicator:checked:hover {
424 background-color: %(button)s;
426 QCheckBox::indicator:checked:pressed {
427 background-color: %(field)s;
430 /* radio checkbox */
431 QRadioButton {
432 spacing: 8px;
433 margin: 4px;
435 QRadioButton::indicator {
436 height: 0.75em;
437 width: 0.75em;
440 /* progress bar */
441 QProgressBar {
442 background-color: %(field)s;
443 border: 1px solid %(darker)s;
445 QProgressBar::chunk {
446 background-color: %(button)s;
447 width: 1px;
450 /* spin box */
451 QAbstractSpinBox::up-button, QAbstractSpinBox::down-button {
452 background-color: transparent;
454 QAbstractSpinBox::up-arrow, QAbstractSpinBox::down-arrow {
455 border-style: solid;
456 height: 0;
457 width: 0;
459 QAbstractSpinBox::up-arrow {
460 border-color: %(field)s %(field)s %(darker)s %(field)s;
461 border-width: 0 3px 4px 3px;
463 QAbstractSpinBox::up-arrow:hover {
464 border-color: %(field)s %(field)s %(button)s %(field)s;
465 border-width: 0 3px 4px 3px;
467 QAbstractSpinBox::down-arrow {
468 border-color: %(darker)s %(field)s %(field)s %(field)s;
469 border-width: 4px 3px 0 3px;
471 QAbstractSpinBox::down-arrow:hover {
472 border-color: %(button)s %(field)s %(field)s %(field)s;
473 border-width: 4px 3px 0 3px;
476 /* dialogs */
477 QDialog > QFrame {
478 margin: 2px 2px 2px 2px;
481 /* headers */
482 QHeaderView {
483 color: %(field_text)s;
484 border-style: solid;
485 border-width: 0 0 1px 0;
486 border-color: %(grayed)s;
488 QHeaderView::section {
489 border-style: solid;
490 border-right: 1px solid %(grayed)s;
491 background-color: %(background)s;
492 color: %(field_text)s;
493 padding-left: 4px;
496 /* headers */
497 QHeaderView {
498 color: %(field_text)s;
499 border-style: solid;
500 border-width: 0 0 1px 0;
501 border-color: %(grayed)s;
503 QHeaderView::section {
504 border-style: solid;
505 border-right: 1px solid %(grayed)s;
506 background-color: %(background)s;
507 color: %(field_text)s;
508 padding-left: 4px;
511 """ % dict(
512 background=background,
513 field=field,
514 button=color_rgb,
515 darker=darker,
516 lighter=lighter,
517 grayed=grayed,
518 button_text=button_text,
519 field_text=field_text,
520 separator=defs.separator,
521 focus=focus,
525 def get_all_themes():
526 return [
527 Theme('default', N_('Default'), False, EStylesheet.DEFAULT, None),
528 Theme(
529 'flat-light-blue', N_('Flat light blue'), False, EStylesheet.FLAT, '#5271cc'
531 Theme(
532 'flat-light-red', N_('Flat light red'), False, EStylesheet.FLAT, '#cc5452'
534 Theme(
535 'flat-light-grey', N_('Flat light grey'), False, EStylesheet.FLAT, '#707478'
537 Theme(
538 'flat-light-green',
539 N_('Flat light green'),
540 False,
541 EStylesheet.FLAT,
542 '#42a65c',
544 Theme(
545 'flat-dark-blue', N_('Flat dark blue'), True, EStylesheet.FLAT, '#5271cc'
547 Theme('flat-dark-red', N_('Flat dark red'), True, EStylesheet.FLAT, '#cc5452'),
548 Theme(
549 'flat-dark-grey', N_('Flat dark grey'), True, EStylesheet.FLAT, '#aaaaaa'
551 Theme(
552 'flat-dark-green', N_('Flat dark green'), True, EStylesheet.FLAT, '#42a65c'
557 def options():
558 """Return a dictionary mapping display names to theme names"""
559 items = get_all_themes()
560 return [(item.hr_name, item.name) for item in items]
563 def find_theme(name):
564 themes = get_all_themes()
565 for item in themes:
566 if item.name == name:
567 return item
568 return themes[0]