Removing contact caching from backend, moving it to session
[gc-dialer] / src / util / qui_utils.py
1 import sys
2 import logging
3
4 from PyQt4 import QtCore
5 from PyQt4 import QtGui
6
7 import misc
8
9
10 _moduleLogger = logging.getLogger(__name__)
11
12
13 class QErrorLog(QtCore.QObject):
14
15         messagePushed = QtCore.pyqtSignal()
16         messagePopped = QtCore.pyqtSignal()
17
18         def __init__(self):
19                 QtCore.QObject.__init__(self)
20                 self._messages = []
21
22         def push_message(self, message):
23                 self._messages.append(message)
24                 self.messagePushed.emit()
25
26         def push_exception(self):
27                 userMessage = str(sys.exc_info()[1])
28                 _moduleLogger.exception(userMessage)
29                 self.push_message(userMessage)
30
31         def pop_message(self):
32                 del self._messages[0]
33                 self.messagePopped.emit()
34
35         def peek_message(self):
36                 return self._messages[0]
37
38         def __len__(self):
39                 return len(self._messages)
40
41
42 class ErrorDisplay(object):
43
44         def __init__(self, errorLog):
45                 self._errorLog = errorLog
46                 self._errorLog.messagePushed.connect(self._on_message_pushed)
47                 self._errorLog.messagePopped.connect(self._on_message_popped)
48
49                 errorIcon = get_theme_icon(("dialog-error", "app_install_error", "gtk-dialog-error"))
50                 self._severityIcon = errorIcon.pixmap(32, 32)
51                 self._severityLabel = QtGui.QLabel()
52                 self._severityLabel.setPixmap(self._severityIcon)
53
54                 self._message = QtGui.QLabel()
55                 self._message.setText("Boo")
56
57                 closeIcon = get_theme_icon(("window-close", "general_close", "gtk-close"))
58                 self._closeLabel = QtGui.QPushButton(closeIcon, "")
59                 self._closeLabel.clicked.connect(self._on_close)
60
61                 self._controlLayout = QtGui.QHBoxLayout()
62                 self._controlLayout.addWidget(self._severityLabel)
63                 self._controlLayout.addWidget(self._message)
64                 self._controlLayout.addWidget(self._closeLabel)
65
66                 self._topLevelLayout = QtGui.QHBoxLayout()
67                 self._topLevelLayout.addLayout(self._controlLayout)
68                 self._widget = QtGui.QWidget()
69                 self._widget.setLayout(self._topLevelLayout)
70                 self._widget.hide()
71
72         @property
73         def toplevel(self):
74                 return self._widget
75
76         @QtCore.pyqtSlot()
77         @QtCore.pyqtSlot(bool)
78         @misc.log_exception(_moduleLogger)
79         def _on_close(self, checked = False):
80                 self._errorLog.pop_message()
81
82         @QtCore.pyqtSlot()
83         @misc.log_exception(_moduleLogger)
84         def _on_message_pushed(self):
85                 if 1 <= len(self._errorLog) and self._widget.isHidden():
86                         self._message.setText(self._errorLog.peek_message())
87                         self._widget.show()
88
89         @QtCore.pyqtSlot()
90         @misc.log_exception(_moduleLogger)
91         def _on_message_popped(self):
92                 if len(self._errorLog) == 0:
93                         self._message.setText("")
94                         self._widget.hide()
95                 else:
96                         self._message.setText(self._errorLog.peek_message())
97
98
99 class QHtmlDelegate(QtGui.QStyledItemDelegate):
100
101         def paint(self, painter, option, index):
102                 newOption = QtGui.QStyleOptionViewItemV4(option)
103                 self.initStyleOption(newOption, index)
104
105                 doc = QtGui.QTextDocument()
106                 doc.setHtml(newOption.text)
107                 doc.setTextWidth(newOption.rect.width())
108
109                 if newOption.widget is not None:
110                         style = newOption.widget.style()
111                 else:
112                         style = QtGui.QApplication.style()
113
114                 newOption.text = ""
115                 style.drawControl(QtGui.QStyle.CE_ItemViewItem, newOption, painter)
116
117                 ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()
118                 if newOption.state & QtGui.QStyle.State_Selected:
119                         ctx.palette.setColor(
120                                 QtGui.QPalette.Text,
121                                 newOption.palette.color(
122                                         QtGui.QPalette.Active,
123                                         QtGui.QPalette.HighlightedText
124                                 )
125                         )
126
127                 textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, newOption)
128                 painter.save()
129                 painter.translate(textRect.topLeft())
130                 painter.setClipRect(textRect.translated(-textRect.topLeft()))
131                 doc.documentLayout().draw(painter, ctx)
132                 painter.restore()
133
134         def sizeHint(self, option, index):
135                 newOption = QtGui.QStyleOptionViewItemV4(option)
136                 self.initStyleOption(newOption, index)
137
138                 doc = QtGui.QTextDocument()
139                 doc.setHtml(newOption.text)
140                 doc.setTextWidth(newOption.rect.width())
141                 size = QtCore.QSize(doc.idealWidth(), doc.size().height())
142                 return size
143
144
145 def _null_set_stackable(window, isStackable):
146         pass
147
148
149 def _maemo_set_stackable(window, isStackable):
150         window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
151
152
153 try:
154         QtCore.Qt.WA_Maemo5StackedWindow
155         set_stackable = _maemo_set_stackable
156 except AttributeError:
157         set_stackable = _null_set_stackable
158
159
160 def _null_set_autorient(window, isStackable):
161         pass
162
163
164 def _maemo_set_autorient(window, isStackable):
165         window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
166
167
168 try:
169         QtCore.Qt.WA_Maemo5AutoOrientation
170         set_autorient = _maemo_set_autorient
171 except AttributeError:
172         set_autorient = _null_set_autorient
173
174
175 def _null_set_landscape(window, isStackable):
176         pass
177
178
179 def _maemo_set_landscape(window, isStackable):
180         window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
181
182
183 try:
184         QtCore.Qt.WA_Maemo5LandscapeOrientation
185         set_landscape = _maemo_set_landscape
186 except AttributeError:
187         set_landscape = _null_set_landscape
188
189
190 def _null_set_portrait(window, isStackable):
191         pass
192
193
194 def _maemo_set_portrait(window, isStackable):
195         window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
196
197
198 try:
199         QtCore.Qt.WA_Maemo5PortraitOrientation
200         set_portrait = _maemo_set_portrait
201 except AttributeError:
202         set_portrait = _null_set_portrait
203
204
205 def _null_show_progress_indicator(window, isStackable):
206         pass
207
208
209 def _maemo_show_progress_indicator(window, isStackable):
210         window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
211
212
213 try:
214         QtCore.Qt.WA_Maemo5ShowProgressIndicator
215         show_progress_indicator = _maemo_show_progress_indicator
216 except AttributeError:
217         show_progress_indicator = _null_show_progress_indicator
218
219
220 def _null_mark_numbers_preferred(widget):
221         pass
222
223
224 def _newqt_mark_numbers_preferred(widget):
225         widget.setInputMethodHints(QtCore.Qt.ImhPreferNumbers)
226
227
228 try:
229         QtCore.Qt.ImhPreferNumbers
230         mark_numbers_preferred = _newqt_mark_numbers_preferred
231 except AttributeError:
232         mark_numbers_preferred = _null_mark_numbers_preferred
233
234
235 def screen_orientation():
236         geom = QtGui.QApplication.desktop().screenGeometry()
237         if geom.width() <= geom.height():
238                 return QtCore.Qt.Vertical
239         else:
240                 return QtCore.Qt.Horizontal
241
242
243 def _null_get_theme_icon(iconNames, fallback = None):
244         icon = fallback if fallback is not None else QtGui.QIcon()
245         return icon
246
247
248 def _newqt_get_theme_icon(iconNames, fallback = None):
249         for iconName in iconNames:
250                 if QtGui.QIcon.hasThemeIcon(iconName):
251                         icon = QtGui.QIcon.fromTheme(iconName)
252                         break
253         else:
254                 icon = fallback if fallback is not None else QtGui.QIcon()
255         return icon
256
257
258 try:
259         QtGui.QIcon.fromTheme
260         get_theme_icon = _newqt_get_theme_icon
261 except AttributeError:
262         get_theme_icon = _null_get_theme_icon
263