icons: use a better icon for "Commit"
[git-cola.git] / cola / icons.py
blob9496d42890d44be7567a9b12c76d5dcd20b179e0
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
16 KNOWN_FILE_MIME_TYPES = [
17 ('text', 'file-code.svg'),
18 ('image', 'file-media.svg'),
19 ('octet', 'file-binary.svg'),
22 KNOWN_FILE_EXTENSIONS = {
23 '.bash': 'file-code.svg',
24 '.c': 'file-code.svg',
25 '.cpp': 'file-code.svg',
26 '.css': 'file-code.svg',
27 '.cxx': 'file-code.svg',
28 '.h': 'file-code.svg',
29 '.hpp': 'file-code.svg',
30 '.hs': 'file-code.svg',
31 '.html': 'file-code.svg',
32 '.java': 'file-code.svg',
33 '.js': 'file-code.svg',
34 '.ksh': 'file-code.svg',
35 '.lisp': 'file-code.svg',
36 '.perl': 'file-code.svg',
37 '.pl': 'file-code.svg',
38 '.py': 'file-code.svg',
39 '.rb': 'file-code.svg',
40 '.rs': 'file-code.svg',
41 '.sh': 'file-code.svg',
42 '.zsh': 'file-code.svg',
46 def install(icon_themes):
47 for theme in icon_themes:
48 icon_dir = resources.icon_dir(theme)
49 qtcompat.add_search_path('icons', icon_dir)
52 def name_from_basename(basename):
53 """Prefix the basename with "icons:" so that git-cola's icons are found
55 "icons" is registered with Qt's resource system during install().
57 """
58 return 'icons:' + basename
61 @memoize
62 def from_name(name):
63 """Return a QIcon from an absolute filename or "icons:basename.svg" name"""
64 return QtGui.QIcon(name)
67 def icon(basename):
68 """Given a basename returns a QIcon from the corresponding cola icon"""
69 return from_name(name_from_basename(basename))
72 @memoize
73 def from_theme(name, fallback=None):
74 """Grab an icon from the current theme with a fallback
76 Support older versions of Qt checking for fromTheme's availability.
78 """
79 if hasattr(QtGui.QIcon, 'fromTheme'):
80 base, _ = os.path.splitext(name)
81 if fallback:
82 qicon = QtGui.QIcon.fromTheme(base, icon(fallback))
83 else:
84 qicon = QtGui.QIcon.fromTheme(base)
85 if not qicon.isNull():
86 return qicon
87 return icon(fallback or name)
90 def basename_from_filename(filename):
91 """Returns an icon name based on the filename"""
92 mimetype = mimetypes.guess_type(filename)[0]
93 if mimetype is not None:
94 mimetype = mimetype.lower()
95 for filetype, icon_name in KNOWN_FILE_MIME_TYPES:
96 if filetype in mimetype:
97 return icon_name
98 extension = os.path.splitext(filename)[1]
99 return KNOWN_FILE_EXTENSIONS.get(extension.lower(), 'file-text.svg')
102 def from_filename(filename):
103 basename = basename_from_filename(filename)
104 return from_name(name_from_basename(basename))
107 def mkicon(value, default=None):
108 if value is None and default is not None:
109 value = default()
110 elif value and isinstance(value, (str, ustr)):
111 value = QtGui.QIcon(value)
112 return value
115 def from_style(key):
116 """Maintain a cache of standard icons and return cache entries."""
117 style = QtWidgets.QApplication.instance().style()
118 return style.standardIcon(key)
121 def status(filename, deleted, is_staged, untracked):
122 if deleted:
123 icon_name = 'circle-slash-red.svg'
124 elif is_staged:
125 icon_name = 'staged.svg'
126 elif untracked:
127 icon_name = 'question-plain.svg'
128 else:
129 icon_name = basename_from_filename(filename)
130 return icon_name
133 # Icons creators and SVG file references
135 def add():
136 return from_theme('list-add', fallback='plus.svg')
139 def branch():
140 return icon('git-branch.svg')
143 def check_name():
144 return name_from_basename('check.svg')
147 def close():
148 return icon('x.svg')
151 def cola():
152 return icon('git-cola.svg')
155 def commit():
156 return icon('document-save-symbolic.svg')
159 def compare():
160 return icon('git-compare.svg')
163 def configure():
164 return from_theme('configure', fallback='gear.svg')
167 def copy():
168 return from_theme('edit-copy.svg')
171 def default_app():
172 return icon('telescope.svg')
175 def dot_name():
176 return name_from_basename('primitive-dot.svg')
179 def download():
180 return icon('file-download.svg')
183 def discard():
184 return icon('trashcan.svg')
187 # folder vs directory: directory is opaque, folder is just an outline
188 # directory is used for the File Browser, where more contrast with the file
189 # icons are needed.
191 def folder():
192 return icon('folder.svg')
195 def directory():
196 return icon('file-directory.svg')
199 def diff():
200 return icon('diff.svg')
203 def edit():
204 return icon('pencil.svg')
207 def ellipsis():
208 return icon('ellipsis.svg')
211 def external():
212 return icon('link-external.svg')
215 def file_code():
216 return icon('file-code.svg')
219 def file_text():
220 return icon('file-text.svg')
223 def file_zip():
224 return icon('file-zip.svg')
227 def fold():
228 return icon('fold.svg')
231 def merge():
232 return icon('git-merge.svg')
235 def modified_name():
236 return name_from_basename('modified.svg')
239 def new():
240 return icon('folder-new.svg')
243 def ok():
244 return icon('check.svg')
247 def open_directory():
248 return icon('folder.svg')
251 def partial_name():
252 return name_from_basename('partial.svg')
255 def pull():
256 return icon('repo-pull.svg')
259 def push():
260 return icon('repo-push.svg')
263 def question():
264 return icon('question.svg')
267 def remove():
268 return from_theme('list-remove', fallback='circle-slash.svg')
271 def repo():
272 return icon('repo.svg')
275 def save():
276 return icon('desktop-download.svg')
279 def search():
280 return icon('search.svg')
283 def select_all():
284 return from_theme('edit-select-all.svg')
287 def staged():
288 return icon('staged.svg')
291 def staged_name():
292 return name_from_basename('staged.svg')
295 def star():
296 return icon('star.svg')
299 def sync():
300 return icon('sync.svg')
303 def tag():
304 return icon('tag.svg')
307 def undo():
308 return from_theme('edit-undo', fallback='edit-undo.svg')
311 def unfold():
312 return icon('unfold.svg')
315 def visualize():
316 return icon('eye.svg')
319 def upstream_name():
320 return name_from_basename('upstream.svg')
323 def zoom_fit_best():
324 return icon('zoom-fit-best.svg')
327 def zoom_in():
328 return icon('zoom-in.svg')
331 def zoom_out():
332 return icon('zoom-out.svg')