browser: Rebrand the 'Classic' tool as 'Browser'
[git-cola.git] / cola / main / view.py
blobd174a9cdc69c0db47b6d9e23ac57bf7ae8297e18
1 """This view provides the main git-cola user interface.
2 """
3 import os
5 from PyQt4 import QtCore
6 from PyQt4 import QtGui
7 from PyQt4.QtCore import Qt
8 from PyQt4.QtCore import SIGNAL
10 import cola
11 from cola import core
12 from cola import gitcmds
13 from cola import guicmds
14 from cola import merge
15 from cola import settings
16 from cola import signals
17 from cola import gitcfg
18 from cola import qtutils
19 from cola import qtcompat
20 from cola import qt
21 from cola import resources
22 from cola import stash
23 from cola import utils
24 from cola import version
25 from cola.bookmarks import manage_bookmarks
26 from cola.classic import cola_classic
27 from cola.classic import classic_widget
28 from cola.dag import git_dag
29 from cola.git import git
30 from cola.prefs import diff_font
31 from cola.prefs import PreferencesModel
32 from cola.prefs import preferences
33 from cola.qt import create_button
34 from cola.qt import create_dock
35 from cola.qt import create_menu
36 from cola.qtutils import add_action
37 from cola.qtutils import connect_action
38 from cola.qtutils import connect_action_bool
39 from cola.qtutils import connect_button
40 from cola.qtutils import emit
41 from cola.qtutils import log
42 from cola.qtutils import relay_signal
43 from cola.qtutils import tr
44 from cola.widgets import cfgactions
45 from cola.widgets import remote
46 from cola.widgets import standard
47 from cola.widgets.about import launch_about_dialog
48 from cola.widgets.about import show_shortcuts
49 from cola.widgets.archive import GitArchiveDialog
50 from cola.widgets.commitmsg import CommitMessageEditor
51 from cola.widgets.compare import compare_branches
52 from cola.widgets.createtag import create_tag
53 from cola.widgets.createbranch import create_new_branch
54 from cola.widgets.diff import DiffEditor
55 from cola.widgets.recent import browse_recent
56 from cola.widgets.status import StatusWidget
57 from cola.widgets.search import search
60 class MainView(standard.MainWindow):
61 def __init__(self, model, parent):
62 super(MainView, self).__init__(parent)
63 # Default size; this is thrown out when save/restore is used
64 self.resize(987, 610)
65 self.model = model
66 self.prefs_model = prefs_model = PreferencesModel()
68 # Internal field used by import/export_state().
69 # Change this whenever dockwidgets are removed.
70 self.widget_version = 1
72 # Keeps track of merge messages we've seen
73 self.merge_message_hash = ''
75 self.setAcceptDrops(True)
76 self.setAttribute(Qt.WA_MacMetalStyle)
78 # Dockwidget options
79 qtcompat.set_common_dock_options(self)
81 cfg = gitcfg.instance()
82 self.classic_dockable = cfg.get('cola.browserdockable')
84 if self.classic_dockable:
85 self.classicdockwidget = create_dock('Browser', self)
86 self.classicwidget = classic_widget(self)
87 self.classicdockwidget.setWidget(self.classicwidget)
89 # "Actions" widget
90 self.actionsdockwidget = create_dock('Action', self)
91 self.actionsdockwidgetcontents = qt.QFlowLayoutWidget(self)
92 layout = self.actionsdockwidgetcontents.layout()
93 self.stage_button = create_button(text='Stage', layout=layout)
94 self.unstage_button = create_button(text='Unstage', layout=layout)
95 self.rescan_button = create_button(text='Rescan', layout=layout)
96 self.fetch_button = create_button(text='Fetch...', layout=layout)
97 self.push_button = create_button(text='Push...', layout=layout)
98 self.pull_button = create_button(text='Pull...', layout=layout)
99 self.stash_button = create_button(text='Stash...', layout=layout)
100 layout.addStretch()
101 self.actionsdockwidget.setWidget(self.actionsdockwidgetcontents)
103 # "Repository Status" widget
104 self.statusdockwidget = create_dock('Status', self)
105 self.statusdockwidget.setWidget(StatusWidget(self))
107 # "Commit Message Editor" widget
108 self.position_label = QtGui.QLabel()
109 font = qtutils.default_monospace_font()
110 font.setPointSize(int(font.pointSize() * 0.8))
111 self.position_label.setFont(font)
112 self.commitdockwidget = create_dock('Commit', self)
113 titlebar = self.commitdockwidget.titleBarWidget()
114 titlebar.add_corner_widget(self.position_label)
116 self.commitmsgeditor = CommitMessageEditor(model, self)
117 relay_signal(self, self.commitmsgeditor, SIGNAL(signals.amend_mode))
118 relay_signal(self, self.commitmsgeditor, SIGNAL(signals.signoff))
119 relay_signal(self, self.commitmsgeditor,
120 SIGNAL(signals.load_previous_message))
121 self.commitdockwidget.setWidget(self.commitmsgeditor)
123 # "Command Output" widget
124 logwidget = qtutils.logger()
125 logwidget.setFont(diff_font())
126 self.logdockwidget = create_dock('Console', self)
127 self.logdockwidget.setWidget(logwidget)
129 # "Diff Viewer" widget
130 self.diffdockwidget = create_dock('Diff', self)
131 self.diff_editor = DiffEditor(self.diffdockwidget)
132 self.diffdockwidget.setWidget(self.diff_editor)
134 # All Actions
135 self.menu_unstage_all = add_action(self,
136 'Unstage All', emit(self, signals.unstage_all))
137 self.menu_unstage_all.setIcon(qtutils.icon('remove.svg'))
139 self.menu_unstage_selected = add_action(self,
140 'Unstage From Commit', emit(self, signals.unstage_selected))
141 self.menu_unstage_selected.setIcon(qtutils.icon('remove.svg'))
143 self.menu_show_diffstat = add_action(self,
144 'Diffstat', emit(self, signals.diffstat), 'Alt+D')
146 self.menu_stage_modified = add_action(self,
147 'Stage Changed Files To Commit',
148 emit(self, signals.stage_modified), 'Alt+A')
149 self.menu_stage_modified.setIcon(qtutils.icon('add.svg'))
151 self.menu_stage_untracked = add_action(self,
152 'Stage All Untracked', emit(self, signals.stage_untracked), 'Alt+U')
153 self.menu_stage_untracked.setIcon(qtutils.icon('add.svg'))
155 self.menu_export_patches = add_action(self,
156 'Export Patches...', guicmds.export_patches, 'Alt+E')
157 self.menu_preferences = add_action(self,
158 'Preferences', lambda: preferences(model=prefs_model),
159 QtGui.QKeySequence.Preferences, 'Ctrl+O')
161 self.menu_rescan = add_action(self,
162 'Rescan', emit(self, signals.rescan_and_refresh), 'Ctrl+R')
163 self.menu_rescan.setIcon(qtutils.reload_icon())
165 self.menu_browse_recent = add_action(self,
166 'Recently Modified Files...', browse_recent, 'Shift+Ctrl+E')
168 self.menu_cherry_pick = add_action(self,
169 'Cherry-Pick...', guicmds.cherry_pick, 'Ctrl+P')
171 self.menu_load_commitmsg = add_action(self,
172 'Load Commit Message...', guicmds.load_commitmsg)
174 self.menu_save_tarball = add_action(self,
175 'Save As Tarball/Zip...', self.save_archive)
177 self.menu_quit = add_action(self,
178 'Quit', self.close, 'Ctrl+Q')
179 self.menu_manage_bookmarks = add_action(self,
180 'Bookmarks...', manage_bookmarks)
181 self.menu_grep = add_action(self,
182 'Grep', guicmds.grep)
183 self.menu_merge_local = add_action(self,
184 'Merge...', merge.local_merge)
186 self.menu_merge_abort = add_action(self,
187 'Abort Merge...', merge.abort_merge)
189 self.menu_fetch = add_action(self,
190 'Fetch...', remote.fetch)
191 self.menu_push = add_action(self,
192 'Push...', remote.push)
193 self.menu_pull = add_action(self,
194 'Pull...', remote.pull)
196 self.menu_open_repo = add_action(self,
197 'Open...', guicmds.open_repo)
198 self.menu_open_repo.setIcon(qtutils.open_icon())
200 self.menu_stash = add_action(self,
201 'Stash...', stash.stash, 'Alt+Shift+S')
203 self.menu_clone_repo = add_action(self,
204 'Clone...', guicmds.clone_repo)
205 self.menu_clone_repo.setIcon(qtutils.git_icon())
207 self.menu_help_docs = add_action(self,
208 'Documentation', resources.show_html_docs,
209 QtGui.QKeySequence.HelpContents)
211 self.menu_help_shortcuts = add_action(self,
212 'Keyboard Shortcuts',
213 show_shortcuts,
214 QtCore.Qt.Key_Question)
216 self.menu_visualize_current = add_action(self,
217 'Visualize Current Branch...',
218 emit(self, signals.visualize_current))
219 self.menu_visualize_all = add_action(self,
220 'Visualize All Branches...',
221 emit(self, signals.visualize_all))
222 self.menu_search_commits = add_action(self,
223 'Search...', search)
224 self.menu_browse_branch = add_action(self,
225 'Browse Current Branch...', guicmds.browse_current)
226 self.menu_browse_other_branch = add_action(self,
227 'Browse Other Branch...', guicmds.browse_other)
228 self.menu_load_commitmsg_template = add_action(self,
229 'Get Commit Message Template',
230 emit(self, signals.load_commit_template))
231 self.menu_help_about = add_action(self,
232 'About', launch_about_dialog)
234 self.menu_branch_diff = add_action(self,
235 'SHA-1...', guicmds.diff_revision)
236 self.menu_diff_expression = add_action(self,
237 'Expression...', guicmds.diff_expression)
238 self.menu_branch_compare = add_action(self,
239 'Branches...', compare_branches)
241 self.menu_create_tag = add_action(self,
242 'Create Tag...', create_tag)
244 self.menu_create_branch = add_action(self,
245 'Create...', create_new_branch, 'Ctrl+B')
247 self.menu_delete_branch = add_action(self,
248 'Delete...', guicmds.branch_delete)
250 self.menu_checkout_branch = add_action(self,
251 'Checkout...', guicmds.checkout_branch, 'Alt+B')
252 self.menu_rebase_branch = add_action(self,
253 'Rebase...', guicmds.rebase)
254 self.menu_branch_review = add_action(self,
255 'Review...', guicmds.review_branch)
257 self.menu_classic = add_action(self,
258 'Browser...', cola_classic)
259 self.menu_classic.setIcon(qtutils.git_icon())
261 self.menu_dag = add_action(self,
262 'DAG...', lambda: git_dag(self.model))
263 self.menu_dag.setIcon(qtutils.git_icon())
265 # Relayed actions
266 status_tree = self.statusdockwidget.widget().tree
267 self.addAction(status_tree.up)
268 self.addAction(status_tree.down)
269 self.addAction(status_tree.process_selection)
270 self.addAction(status_tree.launch_difftool)
272 # Create the application menu
273 self.menubar = QtGui.QMenuBar(self)
275 # File Menu
276 self.file_menu = create_menu('&File', self.menubar)
277 self.file_menu.addAction(self.menu_preferences)
278 self.file_menu.addSeparator()
279 self.file_menu.addAction(self.menu_open_repo)
280 self.file_menu.addAction(self.menu_clone_repo)
281 self.file_menu.addAction(self.menu_manage_bookmarks)
282 self.file_menu.addSeparator()
283 self.file_menu.addAction(self.menu_rescan)
284 self.file_menu.addSeparator()
285 self.file_menu.addAction(self.menu_browse_recent)
286 self.file_menu.addSeparator()
287 self.file_menu.addAction(self.menu_load_commitmsg)
288 self.file_menu.addAction(self.menu_load_commitmsg_template)
289 self.file_menu.addSeparator()
290 self.file_menu.addAction(self.menu_save_tarball)
291 self.file_menu.addAction(self.menu_quit)
292 # Add to menubar
293 self.menubar.addAction(self.file_menu.menuAction())
295 # Commit Menu
296 self.commit_menu = create_menu('Co&mmit', self.menubar)
297 self.commit_menu.setTitle(tr('Commit@@verb'))
298 self.commit_menu.addAction(self.menu_stage_modified)
299 self.commit_menu.addAction(self.menu_stage_untracked)
300 self.commit_menu.addSeparator()
301 self.commit_menu.addAction(self.menu_unstage_all)
302 self.commit_menu.addAction(self.menu_unstage_selected)
303 self.commit_menu.addSeparator()
304 self.commit_menu.addAction(self.menu_search_commits)
305 # Add to menubar
306 self.menubar.addAction(self.commit_menu.menuAction())
308 # Branch Menu
309 self.branch_menu = create_menu('B&ranch', self.menubar)
310 self.branch_menu.addAction(self.menu_branch_review)
311 self.branch_menu.addSeparator()
312 self.branch_menu.addAction(self.menu_create_branch)
313 self.branch_menu.addAction(self.menu_checkout_branch)
314 self.branch_menu.addAction(self.menu_rebase_branch)
315 self.branch_menu.addAction(self.menu_delete_branch)
316 self.branch_menu.addSeparator()
317 self.branch_menu.addAction(self.menu_browse_branch)
318 self.branch_menu.addAction(self.menu_browse_other_branch)
319 self.branch_menu.addSeparator()
320 self.branch_menu.addAction(self.menu_visualize_current)
321 self.branch_menu.addAction(self.menu_visualize_all)
322 # Add to menubar
323 self.menubar.addAction(self.branch_menu.menuAction())
325 # Actions menu
326 self.actions_menu = create_menu('Act&ions', self.menubar)
327 self.actions_menu.addAction(self.menu_merge_local)
328 self.actions_menu.addAction(self.menu_stash)
329 self.actions_menu.addSeparator()
330 self.actions_menu.addAction(self.menu_fetch)
331 self.actions_menu.addAction(self.menu_push)
332 self.actions_menu.addAction(self.menu_pull)
333 self.actions_menu.addSeparator()
334 self.actions_menu.addAction(self.menu_create_tag)
335 self.actions_menu.addSeparator()
336 self.actions_menu.addAction(self.menu_export_patches)
337 self.actions_menu.addAction(self.menu_cherry_pick)
338 self.actions_menu.addSeparator()
339 self.actions_menu.addAction(self.menu_merge_abort)
340 self.actions_menu.addAction(self.menu_grep)
341 # Add to menubar
342 self.menubar.addAction(self.actions_menu.menuAction())
344 # Diff Menu
345 self.diff_menu = create_menu('&Diff', self.menubar)
346 self.diff_menu.addAction(self.menu_branch_diff)
347 self.diff_menu.addAction(self.menu_diff_expression)
348 self.diff_menu.addAction(self.menu_branch_compare)
349 self.diff_menu.addSeparator()
350 self.diff_menu.addAction(self.menu_show_diffstat)
351 # Add to menubar
352 self.menubar.addAction(self.diff_menu.menuAction())
354 # Tools Menu
355 self.tools_menu = create_menu('&Tools', self.menubar)
356 self.tools_menu.addAction(self.menu_classic)
357 self.tools_menu.addAction(self.menu_dag)
358 self.tools_menu.addSeparator()
359 if self.classic_dockable:
360 self.tools_menu.addAction(self.classicdockwidget.toggleViewAction())
362 self.setup_dockwidget_tools_menu()
363 self.menubar.addAction(self.tools_menu.menuAction())
365 # Help Menu
366 self.help_menu = create_menu('&Help', self.menubar)
367 self.help_menu.addAction(self.menu_help_docs)
368 self.help_menu.addAction(self.menu_help_shortcuts)
369 self.help_menu.addAction(self.menu_help_about)
370 # Add to menubar
371 self.menubar.addAction(self.help_menu.menuAction())
373 # Set main menu
374 self.setMenuBar(self.menubar)
376 # Arrange dock widgets
377 top = Qt.TopDockWidgetArea
378 bottom = Qt.BottomDockWidgetArea
380 self.addDockWidget(top, self.commitdockwidget)
381 if self.classic_dockable:
382 self.addDockWidget(top, self.classicdockwidget)
383 self.addDockWidget(top, self.statusdockwidget)
384 self.addDockWidget(top, self.actionsdockwidget)
385 self.addDockWidget(bottom, self.logdockwidget)
386 if self.classic_dockable:
387 self.tabifyDockWidget(self.classicdockwidget, self.commitdockwidget)
388 self.tabifyDockWidget(self.logdockwidget, self.diffdockwidget)
390 # Listen for model notifications
391 model.add_observer(model.message_updated, self._update_view)
393 prefs_model.add_observer(prefs_model.message_config_updated,
394 self._config_updated)
396 # Set a default value
397 self.show_cursor_position(1, 0)
399 # Add button callbacks
400 connect_button(self.rescan_button,
401 emit(self, signals.rescan_and_refresh))
402 connect_button(self.fetch_button, remote.fetch)
403 connect_button(self.push_button, remote.push)
404 connect_button(self.pull_button, remote.pull)
405 connect_button(self.stash_button, stash.stash)
407 connect_button(self.stage_button, self.stage)
408 connect_button(self.unstage_button, self.unstage)
410 self.connect(self.commitmsgeditor, SIGNAL('cursorPosition(int,int)'),
411 self.show_cursor_position)
412 self.connect(self, SIGNAL('update'), self._update_callback)
413 self.connect(self, SIGNAL('apply_state'), self.apply_state)
414 self.connect(self, SIGNAL('install_config_actions'),
415 self._install_config_actions)
417 # Install .git-config-defined actions
418 self._config_task = None
419 self.install_config_actions()
421 # Restore saved settings
422 self._gui_state_task = None
423 self._load_gui_state()
425 log(0, version.git_version_str() + '\ncola version ' + version.version())
427 # Qt overrides
428 def closeEvent(self, event):
429 """Save state in the settings manager."""
430 qtutils.save_state(self)
431 standard.MainWindow.closeEvent(self, event)
433 # Accessors
434 mode = property(lambda self: self.model.mode)
436 def _config_updated(self, source, config, value):
437 if config == 'cola.fontdiff':
438 font = QtGui.QFont()
439 if not font.fromString(value):
440 return
441 qtutils.logger().setFont(font)
442 self.diff_editor.setFont(font)
443 self.commitmsgeditor.setFont(font)
445 elif config == 'cola.tabwidth':
446 # variable-tab-width setting
447 self.diff_editor.set_tab_width(value)
449 def install_config_actions(self):
450 """Install .gitconfig-defined actions"""
451 self._config_task = self._start_config_actions_task()
453 def _start_config_actions_task(self):
454 """Do the expensive "get_config_actions()" call in the background"""
455 class ConfigActionsTask(QtCore.QRunnable):
456 def __init__(self, sender):
457 QtCore.QRunnable.__init__(self)
458 self._sender = sender
459 def run(self):
460 names = cfgactions.get_config_actions()
461 self._sender.emit(SIGNAL('install_config_actions'), names)
463 task = ConfigActionsTask(self)
464 QtCore.QThreadPool.globalInstance().start(task)
465 return task
467 def _install_config_actions(self, names):
468 """Install .gitconfig-defined actions"""
469 if not names:
470 return
471 menu = self.actions_menu
472 menu.addSeparator()
473 for name in names:
474 menu.addAction(name, emit(self, signals.run_config_action, name))
476 def _update_view(self):
477 self.emit(SIGNAL('update'))
479 def _update_callback(self):
480 """Update the title with the current branch and directory name."""
481 branch = self.model.currentbranch
482 curdir = core.decode(os.getcwd())
483 msg = 'Repository: %s\nBranch: %s' % (curdir, branch)
484 self.commitdockwidget.setToolTip(msg)
486 title = '%s: %s' % (self.model.project, branch)
487 if self.mode == self.model.mode_amend:
488 title += ' ** amending **'
489 self.setWindowTitle(title)
491 self.commitmsgeditor.set_mode(self.mode)
493 if not self.model.read_only() and self.mode != self.model.mode_amend:
494 # Check if there's a message file in .git/
495 merge_msg_path = gitcmds.merge_message_path()
496 if merge_msg_path is None:
497 return
498 merge_msg_hash = utils.checksum(core.decode(merge_msg_path))
499 if merge_msg_hash == self.merge_message_hash:
500 return
501 self.merge_message_hash = merge_msg_hash
502 cola.notifier().broadcast(signals.load_commit_message,
503 core.decode(merge_msg_path))
505 def apply_state(self, state):
506 """Imports data for save/restore"""
507 # 1 is the widget version; change when widgets are added/removed
508 standard.MainWindow.apply_state(self, state)
509 qtutils.apply_window_state(self, state, 1)
511 def export_state(self):
512 """Exports data for save/restore"""
513 state = standard.MainWindow.export_state(self)
514 return qtutils.export_window_state(self, state, self.widget_version)
516 def _load_gui_state(self):
517 """Restores the gui from the preferences file."""
518 self._gui_state_task = self._start_gui_state_loading_thread()
520 def _start_gui_state_loading_thread(self):
521 """Do expensive file reading and json decoding in the background"""
522 class LoadGUIStateTask(QtCore.QRunnable):
523 def __init__(self, sender):
524 QtCore.QRunnable.__init__(self)
525 self._sender = sender
526 def run(self):
527 state = settings.Settings().get_gui_state(self._sender)
528 self._sender.emit(SIGNAL('apply_state'), state)
530 task = LoadGUIStateTask(self)
531 QtCore.QThreadPool.globalInstance().start(task)
532 return task
534 def setup_dockwidget_tools_menu(self):
535 # Hotkeys for toggling the dock widgets
536 dockwidgets = (
537 (self.logdockwidget, 'Alt+0'),
538 (self.commitdockwidget, 'Alt+1'),
539 (self.statusdockwidget, 'Alt+2'),
540 (self.diffdockwidget, 'Alt+3'),
541 (self.actionsdockwidget, 'Alt+4'),
543 for dockwidget, shortcut in dockwidgets:
544 # Associate the action with the shortcut
545 action = dockwidget.toggleViewAction()
546 action.setShortcut(shortcut)
547 self.tools_menu.addAction(action)
548 def showdock(show, dockwidget=dockwidget):
549 if show:
550 dockwidget.raise_()
551 dockwidget.widget().setFocus(True)
552 else:
553 self.setFocus(True)
554 self.addAction(action)
555 connect_action_bool(action, showdock)
557 # Create a new shortcut Shift+<shortcut> that gives focus
558 action = QtGui.QAction(self)
559 action.setShortcut('Shift+' + shortcut)
560 def focusdock(dockwidget=dockwidget, showdock=showdock):
561 if dockwidget.toggleViewAction().isChecked():
562 showdock(True)
563 else:
564 dockwidget.toggleViewAction().trigger()
565 self.addAction(action)
566 connect_action(action, focusdock)
568 def save_archive(self):
569 ref = git.rev_parse('HEAD')
570 shortref = ref[:7]
571 GitArchiveDialog.save(ref, shortref, self)
573 def stage(self):
574 """Stage selected files, or all files if no selection exists."""
575 paths = cola.selection_model().unstaged
576 if not paths:
577 cola.notifier().broadcast(signals.stage_modified)
578 else:
579 cola.notifier().broadcast(signals.stage, paths)
581 def unstage(self):
582 """Unstage selected files, or all files if no selection exists."""
583 paths = cola.selection_model().staged
584 if not paths:
585 cola.notifier().broadcast(signals.unstage_all)
586 else:
587 cola.notifier().broadcast(signals.unstage, paths)
589 def dragEnterEvent(self, event):
590 """Accepts drops"""
591 standard.MainWindow.dragEnterEvent(self, event)
592 event.acceptProposedAction()
594 def dropEvent(self, event):
595 """Apply dropped patches with git-am"""
596 event.accept()
597 urls = event.mimeData().urls()
598 if not urls:
599 return
600 paths = map(lambda x: unicode(x.path()), urls)
601 patches = [p for p in paths if p.endswith('.patch')]
602 dirs = [p for p in paths if os.path.isdir(p)]
603 dirs.sort()
604 for d in dirs:
605 patches.extend(self._gather_patches(d))
606 # Broadcast the patches to apply
607 cola.notifier().broadcast(signals.apply_patches, patches)
609 def _gather_patches(self, path):
610 """Find patches in a subdirectory"""
611 patches = []
612 for root, subdirs, files in os.walk(path):
613 for name in [f for f in files if f.endswith('.patch')]:
614 patches.append(os.path.join(root, name))
615 return patches
617 def show_cursor_position(self, rows, cols):
618 display = '&nbsp;%02d:%02d&nbsp;' % (rows, cols)
619 if cols > 78:
620 display = ('<span style="color: white; '
621 ' background-color: red;"'
622 '>%s</span>' % display)
623 elif cols > 72:
624 display = ('<span style="color: black; '
625 ' background-color: orange;"'
626 '>%s</span>' % display)
627 elif cols > 64:
628 display = ('<span style="color: black; '
629 ' background-color: yellow;"'
630 '>%s</span>' % display)
631 else:
632 display = ('<span style="color: grey;">%s</span>' % display)
634 self.position_label.setText(display)