Merge branch 'merge-no-commit'
[git-cola.git] / cola / icons.py
blob50ec6c44d3cba14a91cd0fd03ec56d538de84e15
1 """The only file where icon filenames are mentioned"""
3 import mimetypes
4 import os
6 from PyQt4 import QtGui
8 from cola import qtcompat
9 from cola import resources
10 from cola.compat import ustr
11 from cola.decorators import memoize
14 KNOWN_FILE_MIME_TYPES = [
15 ('text', 'file-code.svg'),
16 ('image', 'file-media.svg'),
17 ('python', 'file-code.svg'),
18 ('ruby', 'file-code.svg'),
19 ('shell', 'file-code.svg'),
20 ('perl', 'file-code.svg'),
21 ('octet', 'file-binary.svg'),
24 KNOWN_FILE_EXTENSIONS = {
25 '.java': 'file-code.svg',
26 '.groovy': 'file-code.svg',
27 '.cpp': 'file-code.svg',
28 '.c': 'file-code.svg',
29 '.h': 'file-code.svg',
30 '.cxx': 'file-code.svg',
34 def install():
35 icon_dir = resources.icon_dir()
36 qtcompat.add_search_path('icons', icon_dir)
39 def name_from_basename(basename):
40 """Prefix the basename with "icons:" so that git-cola's icons are found
42 "icons" is registered with Qt's resource system during install().
44 """
45 return 'icons:' + basename
48 @memoize
49 def from_name(name):
50 """Return a QIcon from an absolute filename or "icons:basename.svg" name"""
51 return QtGui.QIcon(name)
54 def icon(basename):
55 """Given a basename returns a QIcon from the corresponding cola icon"""
56 return from_name(name_from_basename(basename))
59 @memoize
60 def from_theme(name, fallback=None):
61 """Grab an icon from the current theme with a fallback
63 Support older versions of Qt checking for fromTheme's availability.
65 """
66 if hasattr(QtGui.QIcon, 'fromTheme'):
67 base, ext = os.path.splitext(name)
68 if fallback:
69 qicon = QtGui.QIcon.fromTheme(base, icon(fallback))
70 else:
71 qicon = QtGui.QIcon.fromTheme(base)
72 if not qicon.isNull():
73 return qicon
74 return icon(fallback or name)
77 def basename_from_filename(filename):
78 """Returns an icon name based on the filename"""
79 mimetype = mimetypes.guess_type(filename)[0]
80 if mimetype is not None:
81 mimetype = mimetype.lower()
82 for filetype, icon_name in KNOWN_FILE_MIME_TYPES:
83 if filetype in mimetype:
84 return icon_name
85 extension = os.path.splitext(filename)[1]
86 return KNOWN_FILE_EXTENSIONS.get(extension.lower(), 'file-text.svg')
89 def from_filename(filename):
90 basename = basename_from_filename(filename)
91 return from_name(name_from_basename(basename))
94 def mkicon(icon, default=None):
95 if icon is None and default is not None:
96 icon = default()
97 elif icon and isinstance(icon, (str, ustr)):
98 icon = QtGui.QIcon(icon)
99 return icon
102 @memoize
103 def from_style(key):
104 """Maintain a cache of standard icons and return cache entries."""
105 style = QtGui.QApplication.instance().style()
106 return style.standardIcon(key)
109 def status(filename, deleted, staged, untracked):
110 if deleted:
111 icon_name = 'circle-slash-red.svg'
112 elif staged:
113 icon_name = 'staged.svg'
114 elif untracked:
115 icon_name = 'question-plain.svg'
116 else:
117 icon_name = basename_from_filename(filename)
118 return icon_name
121 # Icons creators and SVG file references
123 def add():
124 return from_theme('list-add', fallback='plus.svg')
127 def branch():
128 return icon('git-branch.svg')
131 def check_name():
132 return name_from_basename('check.svg')
135 def close():
136 return icon('x.svg')
139 def cola():
140 return from_theme('git-cola.svg')
143 def compare():
144 return icon('git-compare.svg')
147 def configure():
148 return from_theme('configure', fallback='gear.svg')
151 def copy():
152 return from_theme('edit-copy.svg')
155 def default_app():
156 return icon('telescope.svg')
159 def dot_name():
160 return name_from_basename('primitive-dot.svg')
163 def download():
164 return icon('file-download.svg')
167 def discard():
168 return icon('trashcan.svg')
170 # folder vs directory: directory is opaque, folder is just an outline
171 # directory is used for the File Browser, where more contrast with the file
172 # icons are needed.
174 def folder():
175 return icon('folder.svg')
177 def directory():
178 return icon('file-directory.svg')
181 def diff():
182 return icon('diff.svg')
185 def edit():
186 return icon('pencil.svg')
189 def ellipsis():
190 return icon('ellipsis.svg')
193 def external():
194 return icon('link-external.svg')
197 def file_code():
198 return icon('file-code.svg')
201 def file_text():
202 return icon('file-text.svg')
205 def file_zip():
206 return icon('file-zip.svg')
209 def fold():
210 return icon('fold.svg')
213 def merge():
214 return icon('git-merge.svg')
217 def modified_name():
218 return name_from_basename('modified.svg')
221 def new():
222 return icon('folder-new.svg')
225 def ok():
226 return icon('check.svg')
229 def open_directory():
230 return icon('folder.svg')
233 def partial_name():
234 return name_from_basename('partial.svg')
237 def pull():
238 return icon('repo-pull.svg')
241 def push():
242 return icon('repo-push.svg')
245 def question():
246 return icon('question.svg')
249 def remove():
250 return from_theme('list-remove', fallback='circle-slash.svg')
253 def repo():
254 return icon('repo.svg')
257 def save():
258 return icon('desktop-download.svg')
261 def search():
262 return icon('search.svg')
265 def select_all():
266 return from_theme('edit-select-all.svg')
269 def staged():
270 return icon('staged.svg')
273 def staged_name():
274 return name_from_basename('staged.svg')
277 def star():
278 return icon('star.svg')
281 def sync():
282 return icon('sync.svg')
285 def tag():
286 return icon('tag.svg')
289 def undo():
290 return from_theme('edit-undo', fallback='edit-undo.svg')
293 def unfold():
294 return icon('unfold.svg')
297 def visualize():
298 return icon('eye.svg')
301 def upstream_name():
302 return name_from_basename('upstream.svg')
305 def zoom_fit_best():
306 return from_theme('zoom-fit-best.svg')
309 def zoom_in():
310 return from_theme('zoom-in.svg')
313 def zoom_out():
314 return from_theme('zoom-out.svg')