core: make getcwd() fail-safe
[git-cola.git] / cola / icons.py
blob0956842cea54887d720def1643e187e68ff13767
1 """The only file where icon filenames are mentioned"""
3 from __future__ import absolute_import, division, unicode_literals
4 import mimetypes
5 import os
7 from qtpy import QtGui
8 from qtpy import QtWidgets
10 from . import qtcompat
11 from . import resources
12 from .compat import ustr
13 from .decorators import memoize
14 from .i18n import N_
17 KNOWN_FILE_MIME_TYPES = [
18 ('text', 'file-code.svg'),
19 ('image', 'file-media.svg'),
20 ('octet', 'file-binary.svg'),
23 KNOWN_FILE_EXTENSIONS = {
24 '.bash': 'file-code.svg',
25 '.c': 'file-code.svg',
26 '.cpp': 'file-code.svg',
27 '.css': 'file-code.svg',
28 '.cxx': 'file-code.svg',
29 '.h': 'file-code.svg',
30 '.hpp': 'file-code.svg',
31 '.hs': 'file-code.svg',
32 '.html': 'file-code.svg',
33 '.java': 'file-code.svg',
34 '.js': 'file-code.svg',
35 '.ksh': 'file-code.svg',
36 '.lisp': 'file-code.svg',
37 '.perl': 'file-code.svg',
38 '.pl': 'file-code.svg',
39 '.py': 'file-code.svg',
40 '.rb': 'file-code.svg',
41 '.rs': 'file-code.svg',
42 '.sh': 'file-code.svg',
43 '.zsh': 'file-code.svg',
47 def install(themes):
48 for theme in themes:
49 icon_dir = resources.icon_dir(theme)
50 qtcompat.add_search_path('icons', icon_dir)
53 def icon_themes():
54 return (
55 (N_('Default'), 'default'),
56 (N_('Dark Theme'), 'dark'),
57 (N_('Light Theme'), 'light'),
61 def name_from_basename(basename):
62 """Prefix the basename with "icons:" so that git-cola's icons are found
64 "icons" is registered with Qt's resource system during install().
66 """
67 return 'icons:' + basename
70 @memoize
71 def from_name(name):
72 """Return a QIcon from an absolute filename or "icons:basename.svg" name"""
73 return QtGui.QIcon(name)
76 def icon(basename):
77 """Given a basename returns a QIcon from the corresponding cola icon"""
78 return from_name(name_from_basename(basename))
81 @memoize
82 def from_theme(name, fallback=None):
83 """Grab an icon from the current theme with a fallback
85 Support older versions of Qt checking for fromTheme's availability.
87 """
88 if hasattr(QtGui.QIcon, 'fromTheme'):
89 base, _ = os.path.splitext(name)
90 if fallback:
91 qicon = QtGui.QIcon.fromTheme(base, icon(fallback))
92 else:
93 qicon = QtGui.QIcon.fromTheme(base)
94 if not qicon.isNull():
95 return qicon
96 return icon(fallback or name)
99 def basename_from_filename(filename):
100 """Returns an icon name based on the filename"""
101 mimetype = mimetypes.guess_type(filename)[0]
102 if mimetype is not None:
103 mimetype = mimetype.lower()
104 for filetype, icon_name in KNOWN_FILE_MIME_TYPES:
105 if filetype in mimetype:
106 return icon_name
107 extension = os.path.splitext(filename)[1]
108 return KNOWN_FILE_EXTENSIONS.get(extension.lower(), 'file-text.svg')
111 def from_filename(filename):
112 basename = basename_from_filename(filename)
113 return from_name(name_from_basename(basename))
116 def mkicon(value, default=None):
117 if value is None and default is not None:
118 value = default()
119 elif value and isinstance(value, (str, ustr)):
120 value = QtGui.QIcon(value)
121 return value
124 def from_style(key):
125 """Maintain a cache of standard icons and return cache entries."""
126 style = QtWidgets.QApplication.instance().style()
127 return style.standardIcon(key)
130 def status(filename, deleted, is_staged, untracked):
131 if deleted:
132 icon_name = 'circle-slash-red.svg'
133 elif is_staged:
134 icon_name = 'staged.svg'
135 elif untracked:
136 icon_name = 'question-plain.svg'
137 else:
138 icon_name = basename_from_filename(filename)
139 return icon_name
142 # Icons creators and SVG file references
144 def add():
145 return from_theme('list-add', fallback='plus.svg')
148 def alphabetical():
149 return icon('a-z-order.svg')
152 def branch():
153 return icon('git-branch.svg')
156 def check_name():
157 return name_from_basename('check.svg')
160 def close():
161 return icon('x.svg')
164 def cola():
165 return icon('git-cola.svg')
168 def commit():
169 return icon('document-save-symbolic.svg')
172 def compare():
173 return icon('git-compare.svg')
176 def configure():
177 return from_theme('configure', fallback='gear.svg')
180 def copy():
181 return from_theme('edit-copy.svg')
184 def default_app():
185 return icon('telescope.svg')
188 def dot_name():
189 return name_from_basename('primitive-dot.svg')
192 def download():
193 return icon('file-download.svg')
196 def discard():
197 return icon('trashcan.svg')
200 # folder vs directory: directory is opaque, folder is just an outline
201 # directory is used for the File Browser, where more contrast with the file
202 # icons are needed.
204 def folder():
205 return icon('folder.svg')
208 def directory():
209 return icon('file-directory.svg')
212 def diff():
213 return icon('diff.svg')
216 def edit():
217 return icon('pencil.svg')
220 def ellipsis():
221 return icon('ellipsis.svg')
224 def external():
225 return icon('link-external.svg')
228 def file_code():
229 return icon('file-code.svg')
232 def file_text():
233 return icon('file-text.svg')
236 def file_zip():
237 return icon('file-zip.svg')
240 def fold():
241 return icon('fold.svg')
244 def merge():
245 return icon('git-merge.svg')
248 def modified():
249 return icon('modified.svg')
252 def modified_name():
253 return name_from_basename('modified.svg')
256 def new():
257 return icon('folder-new.svg')
260 def ok():
261 return icon('check.svg')
264 def open_directory():
265 return icon('folder.svg')
268 def partial_name():
269 return name_from_basename('partial.svg')
272 def pull():
273 return icon('repo-pull.svg')
276 def push():
277 return icon('repo-push.svg')
280 def question():
281 return icon('question.svg')
284 def remove():
285 return from_theme('list-remove', fallback='circle-slash.svg')
288 def repo():
289 return icon('repo.svg')
292 def reverse_chronological():
293 return icon('last-first-order.svg')
296 def save():
297 return icon('desktop-download.svg')
300 def search():
301 return icon('search.svg')
304 def select_all():
305 return from_theme('edit-select-all.svg')
308 def staged():
309 return icon('staged.svg')
312 def staged_name():
313 return name_from_basename('staged.svg')
316 def star():
317 return icon('star.svg')
320 def sync():
321 return icon('sync.svg')
324 def tag():
325 return icon('tag.svg')
328 def undo():
329 return from_theme('edit-undo', fallback='edit-undo.svg')
332 def unfold():
333 return icon('unfold.svg')
336 def visualize():
337 return icon('eye.svg')
340 def upstream_name():
341 return name_from_basename('upstream.svg')
344 def zoom_fit_best():
345 return icon('zoom-fit-best.svg')
348 def zoom_in():
349 return icon('zoom-in.svg')
352 def zoom_out():
353 return icon('zoom-out.svg')