from Page import Page from Widget import Widget from PageMarker import PageMarker from PyQt4 import QtGui, QtCore class PiHud(QtGui.QMainWindow): def __init__(self, global_config, connection): super(PiHud, self).__init__() self.global_config = global_config self.connection = connection # ================= Color Palette ================= palette = self.palette() palette.setColor(self.backgroundRole(), QtCore.Qt.black) self.setPalette(palette) # ================== Init Pages =================== self.pageMarker = PageMarker(self) self.stack = QtGui.QStackedWidget(self) self.setCentralWidget(self.stack) # read the config and make pages for configs in global_config["pages"]: self.__add_existing_page(configs) # ================= Context Menu ================== self.menu = QtGui.QMenu() subMenu = self.menu.addMenu("Add Widget") if len(self.connection.supported_commands) > 0: for command in self.connection.supported_commands: a = subMenu.addAction(command.name) a.setData(command) else: a = subMenu.addAction("No sensors available") a.setDisabled(True) self.menu.addSeparator() self.menu.addAction("New Page", self.__add_page) self.menu.addAction("Delete Page", self.__delete_page) self.menu.addSeparator() self.menu.addAction("Save Layout", self.__save) # ===================== Start ===================== self.timer = QtCore.QBasicTimer() self.setWindowTitle("PiHud") self.showFullScreen() self.start() def __page(self): return self.stack.currentWidget() def __index(self): return self.stack.currentIndex() def __count(self): return self.stack.count() def __save(self): pages = [] for i in range(self.__count()): page = self.stack.widget(i) current_page = [] for widget in page.widgets: current_page.append(widget.config) pages.append(current_page) self.global_config.save(pages) # ========= Main loop ========= def timerEvent(self, event): page = self.__page() for widget in page.widgets: r = self.connection.query(widget.get_command()) widget.render(r) def start(self): # watch the commands on this page for widget in self.__page().widgets: self.connection.watch(widget.get_command()) self.connection.start() self.timer.start(1000/30, self) def stop(self): self.timer.stop(); self.connection.stop() self.connection.unwatch_all() def restart(self): self.stop() self.start() # ========= Widget Actions ========= def __add_existing_widget(self, page, config): # make a widget from the given config widget = Widget(page, config) # add it to the page page.widgets.append(widget) def __add_widget(self, command): # make a default config for this command config = self.global_config.make_config(command) # construct a new widget on this page self.__add_existing_widget(self.__page(), config) # register the new command self.restart() def delete_widget(self, page, widget): # called by the pages themselves page.widgets.remove(widget) p = self.stack.indexOf(page) widget.deleteLater() # reload this page again, to unwatch (if neccessary, # since multiple widgets could be using the same command) self.restart() # ========= Page Actions ========= def __add_existing_page(self, configs=None): """ adds a page and fills with the given widgets """ page = Page(self.stack, self) if configs is not None: for config in configs: self.__add_existing_widget(page, config) self.stack.addWidget(page) def __add_page(self): """ adds a new (empty) page to the end of the page stack """ self.__add_existing_page() self.goto_page(self.__count() - 1) def __delete_page(self): if self.__count() > 1: self.stop() page = self.__page() for widget in page.widgets: self.delete_widget(page, widget) self.stack.removeWidget(page) page.deleteLater() self.goto_page(self.__index()) # calls start() def goto_page(self, p): p = p % len(self.stack) self.stop() # switch page self.stack.setCurrentIndex(p) self.pageMarker.set(self.__count(), self.__index()) self.start() def next_page(self): """ cycle through the screen stack """ self.goto_page(self.__index() + 1) # ========= Window Actions ========= def contextMenuEvent(self, e): action = self.menu.exec_(self.mapToGlobal(e.pos())) if action is not None: command = action.data().toPyObject() # if this is a command creation action, make the new widget # there's got to be a better way to do this... if command is not None: self.__add_widget(command) def keyPressEvent(self, e): key = e.key() if key == QtCore.Qt.Key_Escape: self.stop() self.close() elif key == QtCore.Qt.Key_Tab: self.next_page() def closeEvent(self, e): quit()