class FlowModule: def __init__(self): self.name = "Pretok" self.updateTimer = QTimer() self.updateTimer.timeout.connect(self.update) def makeLayout(self): self.layout = QGraphicsLinearLayout(Qt.Vertical) self.flowComboLayout = QGraphicsLinearLayout(Qt.Horizontal) self.flowLabelLayout = QGraphicsGridLayout() #Flow Layout self.flowData = SvJanez() self.flowView = QGraphicsWebView() self.flowView.setUrl( QUrl(self.flowData.flowImageUrl) ) self.flowView.setEnabled(False) self.flowSelectorCombo = Plasma.ComboBox() self.flowSelectorCombo.addItem(u"Sveti Janez") self.flowSelectorCombo.addItem(u"Soteska") self.flowSelectorCombo.setMinimumWidth(125) self.flowSelectorCombo.textChanged.connect(self.flowSourceChanged) self.flowRefresh = Plasma.IconWidget() self.flowRefresh.setIcon("view-refresh") self.flowRefresh.clicked.connect(self.update) self.flowEnlargeButton = Plasma.IconWidget() self.flowEnlargeButton.setIcon("zoom-in") self.flowEnlargeButton.clicked.connect(self.showFullFlowWidget) self.flowLabel = Plasma.Label() self.flowLabel.setText(u"<b>Pretok:</b> ") self.flowDataLabel = Plasma.Label() self.flowLevelLabel = Plasma.Label() self.flowLevelLabel.setText(u"<b>Višina:</b> ") self.flowLevelDataLabel = Plasma.Label() self.flowTempLabel = Plasma.Label() self.flowTempLabel.setText(u"<b>Temperatura:</b> ") self.flowTempDataLabel = Plasma.Label() self.flowLabelLayout.addItem(self.flowLevelLabel,0,0) self.flowLabelLayout.addItem(self.flowLevelDataLabel,0,1) self.flowLabelLayout.addItem(self.flowLabel,1,0) self.flowLabelLayout.addItem(self.flowDataLabel,1,1) self.flowLabelLayout.addItem(self.flowTempLabel,2,0) self.flowLabelLayout.addItem(self.flowTempDataLabel,2,1) self.flowUpdateTimeSelector = UpdateTimeSelector() self.flowUpdateTimeSelector.setDefaultTime(4) self.flowUpdateTimeSelector.setDefaultInterval('h') self.flowUpdateTimeSelector.updateTimeSpin.valueChanged.connect(self.flowTimeChanged) self.flowUpdateTimeSelector.updateCheckBox.toggled.connect(self.flowTimerToggle) self.flowComboLayout.addItem(self.flowSelectorCombo) self.flowComboLayout.addStretch() self.flowComboLayout.addItem(self.flowEnlargeButton) self.flowComboLayout.addItem(self.flowRefresh) self.layout.addItem(self.flowComboLayout) self.layout.addItem(self.flowView) self.layout.addItem(self.flowLabelLayout) self.layout.addStretch() self.layout.addItem(self.flowUpdateTimeSelector.layout) self.layout.itemAt(0).setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.DefaultType) self.layout.itemAt(2).setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.DefaultType) def flowTimerToggle(self, toggled): if toggled: multiplier = 1 if self.flowUpdateTimeSelector.getInterval() == 'min': multiplier = 60 if self.flowUpdateTimeSelector.getInterval() == 'h': multiplier = 60 * 60 self.updateTimer.start(self.flowUpdateTimeSelector.getTime() * 1000 * multiplier) self.update() else: self.updateTimer.stop() def flowTimeChanged(self, value): if self.flowUpdateTimeSelector.isChecked(): self.updateTimer.stop() self.flowTimerToggle(self.flowUpdateTimeSelector.isChecked()) def flowSourceChanged(self, text): if text == "Sveti Janez": self.flowData = SvJanez() else: self.flowData = Soteska() self.flowView.setUrl(QUrl(self.flowData.flowImageUrl)) self.updateFlowLabels() def updateFlowImage(self): self.flowSourceChanged(self.flowSelectorCombo.text()) def updateFlowLabels(self): self.flowData.fetchData() self.flowDataLabel.setText(u"%s %s" % (self.flowData.currentFlow, u' m3/s')) self.flowTempDataLabel.setText(u"%s %s" % (self.flowData.temperature , u' °C')) self.flowLevelDataLabel.setText(u"%s %s" % (self.flowData.waterLevel , u' cm')) def update(self): try: urllib.urlopen('http://www.google.com', timeout=2) except: self.offlineMode() return self.updateFlowLabels() self.updateFlowImage() def offlineMode(self): self.flowView.setUrl(QUrl("weather-none-available.png")) self.flowDataLabel.setText(u"N/A") self.flowTempDataLabel.setText(u"N/A") self.flowLevelDataLabel.setText(u"N/A") def showFullFlowWidget(self): fullcamwidget = FullCamWidget() fullcamwidget.show(self.flowView.url(), 840, 400)
class CamModule: def __init__(self): self.name = "Kamere" #Cam urls self.camUrls = {u"Ribčev Laz (v živo)": "http://firma.sportnet.si:8080/dvs2000/r1.jpg",\ u"Ribčev Laz": "http://www.bohinj.si/cam/slika3.jpg",\ u"Vogel - 1" : "http://www.snezni-telefon.si/Images/Kamere/6_a.jpg",\ u"Vogel - 2" : "http://www.snezni-telefon.si/Images/Kamere/6_b.jpg",\ u"Vogel - 3" : "http://www.snezni-telefon.si/Images/Kamere/6_c.jpg",\ u"Vogel - 4" : "http://www.snezni-telefon.si/Images/Kamere/6_d.jpg",\ u"Bohinjska Češnjica" : "http://www2.arnes.si/~smisma1/canon.jpg",\ u"Bohinjska Bistrica" : "http://www.drsc.si/kamere/kamslike/bohinjska/slike/boh1_0001.jpg",\ u"Orožnova koča": "http://www.bohinj.si/cam/lisc/slika1.jpg"} self.camSizes ={u"Ribčev Laz (v živo)": "352x228", \ u"Ribčev Laz": "2048x1536",\ u"Vogel - 1" : "1280x1024",\ u"Vogel - 2" : "640x480",\ u"Vogel - 3" : "1280x1024",\ u"Vogel - 4" : "640x480",\ u"Bohinjska Češnjica" : "800x600",\ u"Bohinjska Bistrica" : "352x228",\ u"Orožnova koča": "1280x1024"} self.updateTimer = QTimer() self.updateTimer.timeout.connect(self.update) def makeLayout(self): self.layout = QGraphicsLinearLayout(Qt.Vertical) self.topCamLayout = QGraphicsLinearLayout(Qt.Horizontal) # Cam layout self.camRefreshButton = Plasma.IconWidget() self.camRefreshButton.setIcon("view-refresh") self.camRefreshButton.clicked.connect(self.update) self.camTimeLabel = Plasma.Label() self.camTimeLabel.setText(u"ob") self.camEnlargeButton = Plasma.IconWidget() self.camEnlargeButton.setIcon("zoom-in") self.camEnlargeButton.clicked.connect(self.showFullCamWidget) self.camSelectorCombo = Plasma.ComboBox() for source in sorted(self.camUrls.keys()): self.camSelectorCombo.addItem(source) self.camSelectorCombo.setMinimumWidth(125) self.camSelectorCombo.textChanged.connect(self.camChanged) self.camView = QGraphicsWebView() self.camView.setEnabled(False) self.camTimeDataLabel = Plasma.Label() self.camUpdateTimeSelector = UpdateTimeSelector() self.camUpdateTimeSelector.setDefaultTime(30) self.camUpdateTimeSelector.setDefaultInterval('min') self.camUpdateTimeSelector.updateTimeSpin.valueChanged.connect(self.camTimeChanged) self.camUpdateTimeSelector.updateCheckBox.toggled.connect(self.camTimerToggle) self.topCamLayout.addItem(self.camSelectorCombo) self.topCamLayout.addItem(self.camTimeLabel) self.topCamLayout.addItem(self.camTimeDataLabel) self.topCamLayout.addStretch() self.topCamLayout.addItem(self.camEnlargeButton) self.topCamLayout.addItem(self.camRefreshButton) self.layout.addItem(self.topCamLayout) self.layout.addItem(self.camView) self.layout.addItem(self.camUpdateTimeSelector.layout) self.layout.itemAt(0).setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.DefaultType) self.layout.itemAt(2).setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.DefaultType) def update(self, text=None): try: urllib.urlopen('http://www.google.com', timeout=2) except: self.offlineMode() return if not self.camUpdateTimeSelector.updateCheckBox.isChecked(): self.updateTimer.stop() self.camChanged(self.camSelectorCombo.text()) self.setCamTimeLabel() def offlineMode(self): self.camView.setUrl(QUrl("weather-none-available.png")) self.camTimeDataLabel.setText(" ni na voljo.") def setCamTimeLabel(self): hour = time.localtime().tm_hour if not time.localtime().tm_hour in range(10) else '0' + str(time.localtime().tm_hour) minute = time.localtime().tm_min if not time.localtime().tm_min in range(10) else '0' + str(time.localtime().tm_min) second = time.localtime().tm_sec if not time.localtime().tm_sec in range(10) else '0' + str(time.localtime().tm_sec) self.camTimeDataLabel.setText(u'<b>%s:%s:%s</b>' % (str(hour), str(minute), str(second)) ) def camTimerToggle(self, toggled): if toggled: multiplier = 1 if self.camUpdateTimeSelector.getInterval() == 'min': multiplier = 60 if self.camUpdateTimeSelector.getInterval() == 'h': multiplier = 60 * 60 self.updateTimer.start(self.camUpdateTimeSelector.getTime() * 1000 * multiplier) self.update() else: self.updateTimer.stop() def camChanged(self, text): self.camView.setUrl( QUrl( self.camUrls[unicode(text)] ) ) self.setCamTimeLabel() def camTimeChanged(self, value): if self.camUpdateTimeSelector.isChecked(): self.updateTimer.stop() self.camTimerToggle(self.camUpdateTimeSelector.isChecked()) def showFullCamWidget(self): fullcamwidget = FullCamWidget() size = self.camSizes[unicode(self.camSelectorCombo.text())] size = [ int(i) for i in size.split('x')] if size[0] < 640 and size[1] < 480: fullcamwidget.show(self.camView.url(), size[0] + 25, size[1] + 125) else: fullcamwidget.show(self.camView.url(), 645, 505)
class Lectern(QMainWindow): def __init__(self, parent=None): super(Lectern, self).__init__(parent) self.anchor = None self.initMainMenu() self.initToolbar() splitter = QSplitter() self.tocView = QTreeView() self.tocView.clicked.connect(self.navTo) self.tocModel = TableOfContents() self.tocModel.isEmpty.connect(self.handleTOCLoad) self.tocView.setModel(self.tocModel) self.tocView.expandAll() self.tocView.hide() splitter.addWidget(self.tocView) self.webView = QGraphicsWebView() frame = self.webView.page().mainFrame() scene = QGraphicsScene() scene.addItem(self.webView) self.graphicsView = GraphicsView(scene) self.graphicsView.setFrameShape(QFrame.NoFrame) glWidget = QGLWidget(self) self.graphicsView.setViewport(glWidget) self.webView.loadFinished.connect(self.handleLoad) splitter.addWidget(self.graphicsView) self.setCentralWidget(splitter) self.ebook_info = {} self.setWindowTitle('Lectern') try: self.ebook_info = self.openBook(QApplication.arguments()[1]) except IndexError: pass def initMainMenu(self): menuBar = self.menuBar() menuBar.setNativeMenuBar(True) # TODO: add CROSS-PLATFORM shortcut keys. (e.g. For Quit, use ⌘Q on Mac OS X, ALT-F4 elsewhere) fileMenu = QMenu('File', menuBar) navMenu = QMenu('Navigate', menuBar) # File Menu openAction = QAction('Open', fileMenu) openAction.triggered.connect(self.chooseEbook) fileMenu.addAction(openAction) quitAction = QAction('Quit', fileMenu) quitAction.triggered.connect(self.closeEvent) fileMenu.addAction(quitAction) # Nav Menu prevChatperAction = QAction('Previous Chapter', navMenu) prevChatperAction.triggered.connect(self.prevChapter) navMenu.addAction(prevChatperAction) nextChatperAction = QAction('Next Chapter', navMenu) nextChatperAction.triggered.connect(self.nextChapter) navMenu.addAction(nextChatperAction) menuBar.addMenu(fileMenu) menuBar.addMenu(navMenu) def initToolbar(self): toolBar = QToolBar(self) chooseAction = QAction(self.style().standardIcon( QStyle.SP_DialogOpenButton), 'Open', toolBar) chooseAction.triggered.connect(self.chooseEbook) toolBar.addAction(chooseAction) self.prevAction = QAction(self.style().standardIcon( QStyle.SP_ArrowBack), 'Go back', toolBar) self.prevAction.setEnabled(False) self.prevAction.triggered.connect(self.prevChapter) toolBar.addAction(self.prevAction) self.nextAction = QAction(self.style().standardIcon( QStyle.SP_ArrowForward), 'Go forward', toolBar) self.nextAction.setEnabled(False) self.nextAction.triggered.connect(self.nextChapter) toolBar.addAction(self.nextAction) self.addToolBar(toolBar) def chooseEbook(self): path = QFileDialog.getOpenFileName(self, 'Open eBook', QDesktopServices.storageLocation( QDesktopServices.DocumentsLocation),'EPUBs (*.epub)') if not isfile(path): return if self.ebook_info is not None and 'temp_path' in self.ebook_info: if exists(self.ebook_info['temp_path']): rmtree(self.ebook_info['temp_path']) path = QDir.toNativeSeparators(path) self.ebook_info = self.openBook(path) def openBook(self, path): ebook_info = {} path = realpath(path) if not isfile(path): QMessageBox.critical(self, 'File not found', 'File not found') mimetype, _ = guess_type(path) if mimetype != 'application/epub+zip': QMessageBox.critical(self, 'Not an EPUB', 'Not an EPUB') return None ebook = ZipFile(path) names = ebook.namelist() if not 'META-INF/container.xml' in names: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'container.xml not '\ 'found') return None container_tree = etree.parse(ebook.open('META-INF/container.xml')) rootfile = container_tree.xpath("//*[local-name() = 'rootfile']") if len(rootfile) == 0: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'root not found in '\ 'manifest') return None content_opf = rootfile[0].get('full-path') if content_opf is None: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'content.opf not found') return None ebook_info['opf_root'] = posixpath.dirname(content_opf) tree = etree.parse(ebook.open(content_opf)) manifest = tree.xpath("*[local-name() = 'manifest']") if len(manifest) == 0: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'Manifest not found') return None manifest = manifest[0] items = {} for item in manifest: item_id = item.get('id') if item_id is None: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'Item has no id') return None href = item.get('href') if href is None: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'Item has no href') return None items[item_id] = href spine = tree.xpath("*[local-name() = 'spine']") if len(spine) == 0: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'Spine not found') return None spine = spine[0] ebook_info['chapters'] = [] for itemref in spine: idref = itemref.get('idref') if not idref in items: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'Item in spine '\ 'not found in manifest') return None ebook_info['chapters'].append(items[idref]) if len(ebook_info['chapters']) == 0: ebook.close() QMessageBox.critical(self, 'Invalid EPUB', 'Content not found') return None # Table of contents toc = tree.find("//*[@href='toc.ncx']") if toc is not None: toc_path = posixpath.join(ebook_info['opf_root'], 'toc.ncx') if toc_path in names: toc_tree = etree.parse(ebook.open(toc_path)) navMap = toc_tree.xpath("//*[local-name() = 'navMap']") if len(navMap) > 0: self.tocModel.importNavMap(navMap[0]) temp = QDir.toNativeSeparators(QDesktopServices.storageLocation( QDesktopServices.TempLocation)) # In case we have two copies of Lectern opening the same book. filename = '{0}-{1}'.format(splitext(basename(path))[0], uuid4()) ebook_info['temp_path'] = join(temp, filename) if exists(ebook_info['temp_path']): rmtree(ebook_info['temp_path']) ebook.extractall(ebook_info['temp_path']) ebook.close() ebook_info['index'] = 0 url = join(ebook_info['temp_path'], ebook_info['opf_root'], ebook_info['chapters'][0]) self.webView.setUrl(QUrl(url)) if len(ebook_info['chapters']) > 1: self.nextAction.setEnabled(True) return ebook_info def prevChapter(self): index = self.ebook_info['index'] chapters = self.ebook_info['chapters'] if index > 0: index -= 1 if index == 0: self.prevAction.setEnabled(False) url = join(self.ebook_info['temp_path'], self.ebook_info['opf_root'], chapters[index]) self.webView.setUrl(QUrl(url)) self.ebook_info['index'] = index self.nextAction.setEnabled(True) def nextChapter(self): index = self.ebook_info['index'] chapters = self.ebook_info['chapters'] if index < len(chapters) - 1: index += 1 if index == len(chapters) - 1: self.nextAction.setEnabled(False) url = join(self.ebook_info['temp_path'], self.ebook_info['opf_root'], chapters[index]) self.webView.setUrl(QUrl(url)) self.ebook_info['index'] = index self.prevAction.setEnabled(True) def closeBook(self): if self.ebook_info is not None and 'temp_path' in self.ebook_info: if exists(self.ebook_info['temp_path']): rmtree(self.ebook_info['temp_path']) self.ebook_info = None self.tocView.hide() self.prevAction.setEnabled(False) self.nextAction.setEnabled(False) def closeEvent(self, event = 0): if(event == 0): event = PyQt4.QtGui.QCloseEvent() self.closeBook() super(Lectern, self).closeEvent(event) # Suppress "cannot make invalid context current" warnings sys.exit(0) def navTo(self, index): navPoint = index.internalPointer() href = posixpath.join(self.ebook_info['temp_path'], self.ebook_info['opf_root'], navPoint.src) try: path, anchor = href.split('#') if path == self.webView.url().path(): self.webView.page().mainFrame().scrollToAnchor(anchor) return else: self.anchor = anchor except ValueError: pass url = QUrl.fromEncoded(href) self.webView.setUrl(url) def handleLoad(self, ok): if self.anchor is not None: self.webView.page().mainFrame().addToJavaScriptWindowObject("app", self); self.webView.page().mainFrame().scrollToAnchor(self.anchor) def handleTOCLoad(self, isEmpty): if isEmpty: self.tocView.hide() else: self.tocView.show()