Bump for harmattan
[gonvert] / gonvert / util / qwrappers.py
1 #!/usr/bin/env python
2
3 from __future__ import with_statement
4 from __future__ import division
5
6 import logging
7
8 import qt_compat
9 QtCore = qt_compat.QtCore
10 QtGui = qt_compat.import_module("QtGui")
11
12 import qui_utils
13 import misc as misc_utils
14 import linux as linux_utils
15
16
17 _moduleLogger = logging.getLogger(__name__)
18
19
20 class ApplicationWrapper(object):
21
22         DEFAULT_ORIENTATION = "Default"
23         AUTO_ORIENTATION = "Auto"
24         LANDSCAPE_ORIENTATION = "Landscape"
25         PORTRAIT_ORIENTATION = "Portrait"
26
27         def __init__(self, qapp, constants):
28                 self._constants = constants
29                 self._qapp = qapp
30                 self._clipboard = QtGui.QApplication.clipboard()
31
32                 self._errorLog = qui_utils.QErrorLog()
33                 self._mainWindow = None
34
35                 self._fullscreenAction = QtGui.QAction(None)
36                 self._fullscreenAction.setText("Fullscreen")
37                 self._fullscreenAction.setCheckable(True)
38                 self._fullscreenAction.setShortcut(QtGui.QKeySequence("CTRL+Enter"))
39                 self._fullscreenAction.toggled.connect(self._on_toggle_fullscreen)
40
41                 self._orientation = self.DEFAULT_ORIENTATION
42                 self._orientationAction = QtGui.QAction(None)
43                 self._orientationAction.setText("Next Orientation")
44                 self._orientationAction.setCheckable(True)
45                 self._orientationAction.setShortcut(QtGui.QKeySequence("CTRL+o"))
46                 self._orientationAction.triggered.connect(self._on_next_orientation)
47
48                 self._logAction = QtGui.QAction(None)
49                 self._logAction.setText("Log")
50                 self._logAction.setShortcut(QtGui.QKeySequence("CTRL+l"))
51                 self._logAction.triggered.connect(self._on_log)
52
53                 self._quitAction = QtGui.QAction(None)
54                 self._quitAction.setText("Quit")
55                 self._quitAction.setShortcut(QtGui.QKeySequence("CTRL+q"))
56                 self._quitAction.triggered.connect(self._on_quit)
57
58                 self._aboutAction = QtGui.QAction(None)
59                 self._aboutAction.setText("About")
60                 self._aboutAction.triggered.connect(self._on_about)
61
62                 self._qapp.lastWindowClosed.connect(self._on_app_quit)
63                 self._mainWindow = self._new_main_window()
64                 self._mainWindow.window.destroyed.connect(self._on_child_close)
65
66                 self.load_settings()
67
68                 self._mainWindow.show()
69                 self._idleDelay = QtCore.QTimer()
70                 self._idleDelay.setSingleShot(True)
71                 self._idleDelay.setInterval(0)
72                 self._idleDelay.timeout.connect(self._on_delayed_start)
73                 self._idleDelay.start()
74
75         def load_settings(self):
76                 raise NotImplementedError("Booh")
77
78         def save_settings(self):
79                 raise NotImplementedError("Booh")
80
81         def _new_main_window(self):
82                 raise NotImplementedError("Booh")
83
84         @property
85         def qapp(self):
86                 return self._qapp
87
88         @property
89         def constants(self):
90                 return self._constants
91
92         @property
93         def errorLog(self):
94                 return self._errorLog
95
96         @property
97         def fullscreenAction(self):
98                 return self._fullscreenAction
99
100         @property
101         def orientationAction(self):
102                 return self._orientationAction
103
104         @property
105         def orientation(self):
106                 return self._orientation
107
108         @property
109         def logAction(self):
110                 return self._logAction
111
112         @property
113         def aboutAction(self):
114                 return self._aboutAction
115
116         @property
117         def quitAction(self):
118                 return self._quitAction
119
120         def set_orientation(self, orientation):
121                 self._orientation = orientation
122                 self._mainWindow.update_orientation(self._orientation)
123
124         @classmethod
125         def _next_orientation(cls, current):
126                 return {
127                         cls.DEFAULT_ORIENTATION: cls.AUTO_ORIENTATION,
128                         cls.AUTO_ORIENTATION: cls.LANDSCAPE_ORIENTATION,
129                         cls.LANDSCAPE_ORIENTATION: cls.PORTRAIT_ORIENTATION,
130                         cls.PORTRAIT_ORIENTATION: cls.DEFAULT_ORIENTATION,
131                 }[current]
132
133         def _close_windows(self):
134                 if self._mainWindow is not None:
135                         self.save_settings()
136                         self._mainWindow.window.destroyed.disconnect(self._on_child_close)
137                         self._mainWindow.close()
138                         self._mainWindow = None
139
140         @misc_utils.log_exception(_moduleLogger)
141         def _on_delayed_start(self):
142                 self._mainWindow.start()
143
144         @misc_utils.log_exception(_moduleLogger)
145         def _on_app_quit(self, checked = False):
146                 if self._mainWindow is not None:
147                         self.save_settings()
148                         self._mainWindow.destroy()
149
150         @misc_utils.log_exception(_moduleLogger)
151         def _on_child_close(self, obj = None):
152                 if self._mainWindow is not None:
153                         self.save_settings()
154                         self._mainWindow = None
155
156         @misc_utils.log_exception(_moduleLogger)
157         def _on_toggle_fullscreen(self, checked = False):
158                 with qui_utils.notify_error(self._errorLog):
159                         self._mainWindow.set_fullscreen(checked)
160
161         @misc_utils.log_exception(_moduleLogger)
162         def _on_next_orientation(self, checked = False):
163                 with qui_utils.notify_error(self._errorLog):
164                         self.set_orientation(self._next_orientation(self._orientation))
165
166         @misc_utils.log_exception(_moduleLogger)
167         def _on_about(self, checked = True):
168                 raise NotImplementedError("Booh")
169
170         @misc_utils.log_exception(_moduleLogger)
171         def _on_log(self, checked = False):
172                 with qui_utils.notify_error(self._errorLog):
173                         logPath = linux_utils.get_resource_path(
174                                 "cache", self._constants.__app_name__, "%s.log" % self._constants.__app_name__
175                         )
176                         with open(logPath, "r") as f:
177                                 logLines = f.xreadlines()
178                                 log = "".join(logLines)
179                                 self._clipboard.setText(log)
180
181         @misc_utils.log_exception(_moduleLogger)
182         def _on_quit(self, checked = False):
183                 with qui_utils.notify_error(self._errorLog):
184                         self._close_windows()
185
186
187 class WindowWrapper(object):
188
189         def __init__(self, parent, app):
190                 self._app = app
191
192                 self._errorDisplay = qui_utils.ErrorDisplay(self._app.errorLog)
193
194                 self._layout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight)
195                 self._layout.setContentsMargins(0, 0, 0, 0)
196
197                 self._superLayout = QtGui.QVBoxLayout()
198                 self._superLayout.addWidget(self._errorDisplay.toplevel)
199                 self._superLayout.setContentsMargins(0, 0, 0, 0)
200                 self._superLayout.addLayout(self._layout)
201
202                 centralWidget = QtGui.QWidget()
203                 centralWidget.setLayout(self._superLayout)
204                 centralWidget.setContentsMargins(0, 0, 0, 0)
205
206                 self._window = qui_utils.QSignalingMainWindow(parent)
207                 self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
208                 qui_utils.set_stackable(self._window, True)
209                 self._window.setCentralWidget(centralWidget)
210
211                 self._closeWindowAction = QtGui.QAction(None)
212                 self._closeWindowAction.setText("Close")
213                 self._closeWindowAction.setShortcut(QtGui.QKeySequence("CTRL+w"))
214                 self._closeWindowAction.triggered.connect(self._on_close_window)
215
216                 self._window.addAction(self._closeWindowAction)
217                 self._window.addAction(self._app.quitAction)
218                 self._window.addAction(self._app.fullscreenAction)
219                 self._window.addAction(self._app.orientationAction)
220                 self._window.addAction(self._app.logAction)
221
222         @property
223         def window(self):
224                 return self._window
225
226         @property
227         def windowOrientation(self):
228                 geom = self._window.size()
229                 if geom.width() <= geom.height():
230                         return QtCore.Qt.Vertical
231                 else:
232                         return QtCore.Qt.Horizontal
233
234         @property
235         def idealWindowOrientation(self):
236                 if self._app.orientation ==  self._app.AUTO_ORIENTATION:
237                         windowOrientation = self.windowOrientation
238                 elif self._app.orientation ==  self._app.DEFAULT_ORIENTATION:
239                         windowOrientation = qui_utils.screen_orientation()
240                 elif self._app.orientation ==  self._app.LANDSCAPE_ORIENTATION:
241                         windowOrientation = QtCore.Qt.Horizontal
242                 elif self._app.orientation ==  self._app.PORTRAIT_ORIENTATION:
243                         windowOrientation = QtCore.Qt.Vertical
244                 else:
245                         raise RuntimeError("Bad! No %r for you" % self._app.orientation)
246                 return windowOrientation
247
248         def walk_children(self):
249                 return ()
250
251         def start(self):
252                 pass
253
254         def close(self):
255                 for child in self.walk_children():
256                         child.window.destroyed.disconnect(self._on_child_close)
257                         child.close()
258                 self._window.close()
259
260         def destroy(self):
261                 pass
262
263         def show(self):
264                 self._window.show()
265                 for child in self.walk_children():
266                         child.show()
267                 self.set_fullscreen(self._app.fullscreenAction.isChecked())
268
269         def hide(self):
270                 for child in self.walk_children():
271                         child.hide()
272                 self._window.hide()
273
274         def set_fullscreen(self, isFullscreen):
275                 if self._window.isVisible():
276                         if isFullscreen:
277                                 self._window.showFullScreen()
278                         else:
279                                 self._window.showNormal()
280                 for child in self.walk_children():
281                         child.set_fullscreen(isFullscreen)
282
283         def update_orientation(self, orientation):
284                 if orientation == self._app.DEFAULT_ORIENTATION:
285                         qui_utils.set_autorient(self.window, False)
286                         qui_utils.set_window_orientation(self.window, None)
287                 elif orientation == self._app.AUTO_ORIENTATION:
288                         qui_utils.set_autorient(self.window, True)
289                         qui_utils.set_window_orientation(self.window, None)
290                 elif orientation == self._app.LANDSCAPE_ORIENTATION:
291                         qui_utils.set_autorient(self.window, False)
292                         qui_utils.set_window_orientation(self.window, QtCore.Qt.Horizontal)
293                 elif orientation == self._app.PORTRAIT_ORIENTATION:
294                         qui_utils.set_autorient(self.window, False)
295                         qui_utils.set_window_orientation(self.window, QtCore.Qt.Vertical)
296                 else:
297                         raise RuntimeError("Unknown orientation: %r" % orientation)
298                 for child in self.walk_children():
299                         child.update_orientation(orientation)
300
301         @misc_utils.log_exception(_moduleLogger)
302         def _on_child_close(self, obj = None):
303                 raise NotImplementedError("Booh")
304
305         @misc_utils.log_exception(_moduleLogger)
306         def _on_close_window(self, checked = True):
307                 with qui_utils.notify_error(self._errorLog):
308                         self.close()
309
310
311 class AutoFreezeWindowFeature(object):
312
313         def __init__(self, app, window):
314                 self._app = app
315                 self._window = window
316                 self._app.qapp.focusChanged.connect(self._on_focus_changed)
317                 if self._app.qapp.focusWidget() is not None:
318                         self._window.setUpdatesEnabled(True)
319                 else:
320                         self._window.setUpdatesEnabled(False)
321
322         def close(self):
323                 self._app.qapp.focusChanged.disconnect(self._on_focus_changed)
324                 self._window.setUpdatesEnabled(True)
325
326         @misc_utils.log_exception(_moduleLogger)
327         def _on_focus_changed(self, oldWindow, newWindow):
328                 with qui_utils.notify_error(self._app.errorLog):
329                         if oldWindow is None and newWindow is not None:
330                                 self._window.setUpdatesEnabled(True)
331                         elif oldWindow is not None and newWindow is None:
332                                 self._window.setUpdatesEnabled(False)