1 # Copyright (c) 2008 David Aguilar
2 """This module provides miscellaneous Qt utility functions.
6 from PyQt4
import QtCore
7 from PyQt4
import QtGui
11 from cola
import utils
12 from cola
import signals
13 from cola
import resources
20 _logger
= cola
.views
.log
.LogView()
21 cola
.notifier().listen(signals
.log_cmd
, _logger
.log
)
25 def log(status
, output
):
26 """Sends messages to the log window.
30 cola
.notifier().broadcast(signals
.log_cmd
, status
, output
)
32 def SLOT(signal
, *args
, **opts
):
34 Returns a callback that broadcasts a message over the notifier.
36 If the caller of SLOT() provides args or opts then those are
37 used instead of the ones provided by the invoker of the callback.
40 def broadcast(*local_args
, **local_opts
):
42 cola
.notifier().broadcast(signal
, *args
, **opts
)
44 cola
.notifier().broadcast(signal
, *local_args
, **local_opts
)
48 def prompt(msg
, title
=None):
49 """Presents the user with an input widget and returns the input."""
54 parent
= QtGui
.QApplication
.instance().activeWindow()
55 result
= QtGui
.QInputDialog
.getText(parent
, msg
, title
)
56 return (unicode(result
[0]), result
[1])
58 def create_listwidget_item(text
, filename
):
59 """Creates a QListWidgetItem with text and the icon at filename."""
60 item
= QtGui
.QListWidgetItem()
61 item
.setIcon(QtGui
.QIcon(filename
))
66 def create_treewidget_item(text
, filename
):
67 """Creates a QTreeWidgetItem with text and the icon at filename."""
68 if filename
not in _tree_icon_cache
:
69 _tree_icon_cache
[filename
] = QtGui
.QIcon(filename
)
70 icon
= _tree_icon_cache
[filename
]
71 item
= QtGui
.QTreeWidgetItem()
76 def information(title
, message
=None):
77 """Launches a QMessageBox information with the
78 provided title and message."""
83 parent
= QtGui
.QApplication
.instance().activeWindow()
84 QtGui
.QMessageBox
.information(parent
, title
, message
)
85 # Register globally with the notifier
86 cola
.notifier().listen(signals
.information
, information
)
88 def selected_treeitem(tree_widget
):
89 """Returns a(id_number, is_selected) for a QTreeWidget."""
92 item
= tree_widget
.currentItem()
94 id_number
= item
.data(0, QtCore
.Qt
.UserRole
).toInt()[0]
96 return(id_number
, selected
)
98 def selected_row(list_widget
):
99 """Returns a(row_number, is_selected) tuple for a QListWidget."""
100 row
= list_widget
.currentRow()
101 item
= list_widget
.item(row
)
102 selected
= item
is not None and item
.isSelected()
103 return(row
, selected
)
105 def selection_list(listwidget
, items
):
106 """Returns an array of model items that correspond to
107 the selected QListWidget indices."""
109 itemcount
= listwidget
.count()
110 widgetitems
= [ listwidget
.item(idx
) for idx
in range(itemcount
) ]
112 for item
, widgetitem
in zip(items
, widgetitems
):
113 if widgetitem
.isSelected():
114 selected
.append(item
)
117 def tree_selection(treeitem
, items
):
118 """Returns model items that correspond to selected widget indices"""
119 itemcount
= treeitem
.childCount()
120 widgetitems
= [ treeitem
.child(idx
) for idx
in range(itemcount
) ]
122 for item
, widgetitem
in zip(items
[:len(widgetitems
)], widgetitems
):
123 if widgetitem
.isSelected():
124 selected
.append(item
)
128 def selected_item(list_widget
, items
):
129 """Returns the selected item in a QListWidget."""
130 row
, selected
= selected_row(list_widget
)
131 if selected
and row
< len(items
):
136 def open_dialog(parent
, title
, filename
=None):
137 """Creates an Open File dialog and returns a filename."""
139 return unicode(QtGui
.QFileDialog
140 .getOpenFileName(parent
, title_tr
, filename
))
142 def opendir_dialog(parent
, title
, path
):
143 """Prompts for a directory path"""
145 flags
= (QtGui
.QFileDialog
.ShowDirsOnly |
146 QtGui
.QFileDialog
.DontResolveSymlinks
)
148 qstr
= (QtGui
.QFileDialog
149 .getExistingDirectory(parent
, title_tr
, path
, flags
))
153 def save_dialog(parent
, title
, filename
=''):
154 """Creates a Save File dialog and returns a filename."""
155 title_tr
= parent
.tr(title
)
156 return unicode(QtGui
.QFileDialog
157 .getSaveFileName(parent
, title_tr
, filename
))
160 """Given a basename returns a QIcon from the corresponding cola icon."""
161 return QtGui
.QIcon(resources
.icon(basename
))
163 def question(parent
, title
, message
, default
=True):
164 """Launches a QMessageBox question with the provided title and message.
165 Passing "default=False" will make "No" the default choice."""
166 yes
= QtGui
.QMessageBox
.Yes
167 no
= QtGui
.QMessageBox
.No
174 message
= tr(message
)
175 result
= QtGui
.QMessageBox
.question(parent
, title
, message
,
177 return result
== QtGui
.QMessageBox
.Yes
179 def set_clipboard(text
):
180 """Sets the copy/paste buffer to text."""
183 clipboard
= QtGui
.QApplication
.instance().clipboard()
184 clipboard
.setText(text
, QtGui
.QClipboard
.Clipboard
)
185 clipboard
.setText(text
, QtGui
.QClipboard
.Selection
)
187 def set_selected_item(widget
, idx
):
188 """Sets a the currently selected item to the item at index idx."""
189 if type(widget
) is QtGui
.QTreeWidget
:
190 item
= widget
.topLevelItem(idx
)
192 widget
.setItemSelected(item
, True)
193 widget
.setCurrentItem(item
)
195 def add_items(widget
, items
):
196 """Adds items to a widget."""
200 def set_items(widget
, items
):
201 """Clear the existing widget contents and set the new items."""
203 add_items(widget
, items
)
206 """Translate a string into a local language."""
207 return unicode(QtGui
.QApplication
.instance().translate('', txt
))
209 def icon_file(filename
, staged
=False, untracked
=False):
210 """Returns a file path representing a corresponding file path."""
212 if os
.path
.exists(core
.encode(filename
)):
213 ifile
= resources
.icon('staged.png')
215 ifile
= resources
.icon('removed.png')
217 ifile
= resources
.icon('untracked.png')
219 ifile
= utils
.file_icon(filename
)
222 def icon_for_file(filename
, staged
=False, untracked
=False):
223 """Returns a QIcon for a particular file path."""
224 ifile
= icon_file(filename
, staged
=staged
, untracked
=untracked
)
227 def create_treeitem(filename
, staged
=False, untracked
=False, check
=True):
228 """Given a filename, return a QListWidgetItem suitable
229 for adding to a QListWidget. "staged" and "untracked"
230 controls whether to use the appropriate icons."""
232 ifile
= icon_file(filename
, staged
=staged
, untracked
=untracked
)
234 ifile
= resources
.icon('staged.png')
235 return create_treewidget_item(filename
, ifile
)
238 def update_file_icons(widget
, items
, staged
=True,
239 untracked
=False, offset
=0):
240 """Populate a QListWidget with custom icon items."""
241 for idx
, model_item
in enumerate(items
):
242 item
= widget
.item(idx
+offset
)
244 item
.setIcon(icon_for_file(model_item
, staged
, untracked
))
246 def set_listwidget_strings(widget
, items
):
247 """Sets a list widget to the strings passed in items."""
249 add_items(widget
, [ QtGui
.QListWidgetItem(i
) for i
in items
])
252 def cached_icon(key
):
253 """Maintain a cache of standard icons and return cache entries."""
254 if key
not in _icon_cache
:
255 style
= QtGui
.QApplication
.instance().style()
256 _icon_cache
[key
] = style
.standardIcon(key
)
257 return _icon_cache
[key
]
260 """Return a standard icon for a directory."""
261 return cached_icon(QtGui
.QStyle
.SP_DirIcon
)
264 """Return a standard icon for a file."""
265 return cached_icon(QtGui
.QStyle
.SP_FileIcon
)
268 """Return the diff font string."""
269 qfont
= QtGui
.QFont()
270 font
= cola
.model().cola_config('fontdiff')
271 if font
and qfont
.fromString(font
):
274 if cola
.utils
.is_darwin():
276 qfont
.setFamily(family
)
277 font
= unicode(qfont
.toString())
278 # TODO this might not be the best place for the default
279 cola
.model().set_diff_font(font
)
282 def set_diff_font(widget
):
283 """Updates the diff font based on the configured value."""
285 block
= widget
.signalsBlocked()
286 widget
.blockSignals(True)
287 if isinstance(widget
, QtGui
.QFontComboBox
):
288 widget
.setCurrentFont(qfont
)
290 widget
.setFont(qfont
)
291 widget
.blockSignals(block
)