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