def on_downloaded(self): widget = self.iface.messageBar().createMessage( u"Géofoncier", u"Téléchargement du RFU.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(2) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) progress_bar.setValue(1) # https://pro.geofoncier.fr/index.php?¢re=-196406,5983255&context=metropole url = self.permalinkLineEdit.text() if not url: return self.abort_action(msg=u"Veuillez renseigner le permalien.") self.url = url try: self.download(self.url) except Exception as e: return self.abort_action(msg=e.message) progress_bar.setValue(2) self.iface.messageBar().clearWidgets() return
def on_downloaded(self): widget = self.iface.messageBar().createMessage(u"Géofoncier", u"Téléchargement du RFU.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(2) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) progress_bar.setValue(1) # https://pro.geofoncier.fr/index.php?¢re=-196406,5983255&context=metropole url = self.permalinkLineEdit.text() if not url: return self.abort_action(msg=u"Veuillez renseigner le permalien.") self.url = url try: self.download(self.url) except Exception as e: return self.abort_action(msg=e.message) progress_bar.setValue(2) self.iface.messageBar().clearWidgets() return
def start_worker(worker, iface, message, with_progress=True): # configure the QgsMessageBar message_bar_item = iface.messageBar().createMessage(message) progress_bar = QProgressBar() progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) if not with_progress: progress_bar.setMinimum(0) progress_bar.setMaximum(0) cancel_button = QPushButton() cancel_button.setText('Cancel') cancel_button.clicked.connect(worker.kill) message_bar_item.layout().addWidget(progress_bar) message_bar_item.layout().addWidget(cancel_button) iface.messageBar().pushWidget(message_bar_item, iface.messageBar().INFO) # start the worker in a new thread # let Qt take ownership of the QThread thread = QThread(iface.mainWindow()) worker.moveToThread(thread) worker.set_message.connect( lambda message: set_worker_message(message, message_bar_item)) worker.toggle_show_progress.connect( lambda show: toggle_worker_progress(show, progress_bar)) worker.toggle_show_cancel.connect( lambda show: toggle_worker_cancel(show, cancel_button)) worker.finished.connect(lambda result: worker_finished( result, thread, worker, iface, message_bar_item)) worker.error.connect(lambda e: worker_error(e)) worker.progress.connect(progress_bar.setValue) thread.started.connect(worker.run) thread.start() return thread, message_bar_item
class Popup(QDialog): def __init__(self, widget, parent = None): QDialog.__init__(self, parent) self.setModal(True) self.setWindowTitle("Plot save progress") layout = QVBoxLayout() layout.addWidget(widget) self.progress_bar = QProgressBar() self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(1) self.progress_bar.setValue(0) layout.addWidget(self.progress_bar) buttons = QDialogButtonBox(QDialogButtonBox.Ok, Qt.Horizontal, self) layout.addWidget(buttons) self.setLayout(layout) self.connect(buttons, SIGNAL('accepted()'), self.accept) self.ok_button = buttons.button(QDialogButtonBox.Ok) self.ok_button.setEnabled(False) def closeEvent(self, event): """Ignore clicking of the x in the top right corner""" event.ignore() def keyPressEvent(self, event): """Ignore ESC keystrokes""" if not event.key() == Qt.Key_Escape: QDialog.keyPressEvent(self, event)
class ExerciseUI(QGroupBox): def __init__(self, exercise): super(ExerciseUI, self).__init__() self.exercise = exercise self.initUI() def initUI(self): self.setTitle(self.exercise.label) self.level = QLabel(QString('Lvl. %d' % self.exercise.level)) self.progressbar = QProgressBar() self.progressbar.setMinimum(0) self.progressbar.setMaximum(100) self.progressbar.setValue(self.exercise.progress) grid = QGridLayout() grid.addWidget(self.level, 0, 0) grid.addWidget(self.progressbar, 0, 1, 1, 9) for (index, step) in enumerate(self.exercise.steps): btn = QPushButton(QString('+') + QString.number(step)) grid.addWidget(btn, 1, index) btn.clicked.connect(self.buttonClicked) self.setLayout(grid) def buttonClicked(self): sender = self.sender() step = int(str(sender.text()).lstrip('+')) self.exercise.add(step) self.level.setText(QString('Lvl. %d' % self.exercise.level)) self.progressbar.setValue(self.exercise.progress)
class RenameGui(BaseWindow, QtGui.QMainWindow): renameCompleted = QtCore.pyqtSignal() def __init__(self, session, parent=None): super(RenameGui, self).__init__(parent) self.session = session self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.renameUser.clicked.connect(self.renameUser) self.progressIndicator = QProgressBar(self.ui.statusBar) self.progressIndicator.setMinimumHeight(5) self.progressIndicator.setVisible(False) self.progressIndicator.setMaximum(0) self.progressIndicator.setMinimum(0) self.ui.statusBar.addWidget(self.progressIndicator) self.renameCompleted.connect(self.renameCompletedSlot) self.uiTranslate() def uiTranslate(self): self.setWindowTitle(strings["renameWindowTitle"]) self.ui.newUsername.setPlaceholderText(strings["newUsernameBoxHint"]) self.ui.renameUser.setText(strings["renameUserButtonText"]) def renameCompletedSlot(self): self.progressIndicator.setVisible(False) self.showMessageBox.emit(strings["renameSuccessText"]) def renameUser(self): self.progressIndicator.setVisible(True) def renameThread(): newUsername = self.ui.newUsername.text() if newUsername == "": self.showMessageBox.emit(strings["missingFieldsErrorText"]) return try: oldUsername = self.session.username self.session.renameUser(newUsername) for message in sharedData.messages: if message.sender == oldUsername: message.sender = newUsername elif message.receiver == oldUsername: message.receiver = newUsername storeMessages(self.session.username, sharedData.messages) storeToken(self.session.username, self.session.token) storeKey(self.session.username, self.session.public, self.session.private) storeMessages(oldUsername, None) storeToken(oldUsername, None) storeKey(oldUsername, None, None) self.renameCompleted.emit() except SecureMessagingException as error: self.showMessageBox.emit(strings["errorText"] + responseTranslations[str(error)]) return Thread(target=renameThread).start()
def startWorker(self): # create a new worker instance if self.worker is None: worker = UpdateRegistryWorker() # configure the QgsMessageBar messageBar = self.iface.messageBar().createMessage(u"Update Image Registry", u"Dieser Vorgang kann einige Minute dauern, bitte haben Sie geduld!") progressBar = QProgressBar() progressBar.setMinimum(0) progressBar.setMaximum(0) progressBar.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) cancelButton = QPushButton() cancelButton.setText('Cancel') cancelButton.clicked.connect(self.killWorker) messageBar.layout().addWidget(progressBar) self.progressBar = progressBar messageBar.layout().addWidget(cancelButton) self.iface.messageBar().pushWidget(messageBar, self.iface.messageBar().INFO) #self.iface.messageBar().widgetRemoved # messageBar self.messageBar = messageBar # start the worker in a new thread thread = QThread() worker.moveToThread(thread) worker.finished.connect(self.workerFinished) worker.error.connect(self.workerError) #worker.progress.connect(progressBar.setValue) thread.started.connect(worker.run) thread.start() self.thread = thread self.worker = worker
class ProgressDialog(QDialog): def __init__(self, parent): QDialog.__init__(self, parent) self.resize(300, 75) self.setWindowTitle("Updating") self.vw = QWidget(self) self.vl = QVBoxLayout(self.vw) self.vl.setMargin(10) self.label = QLabel(self.vw) self.label.setText("<b>Downloading:</b> library.zip") self.vl.addWidget(self.label) self.horizontalLayoutWidget = QWidget() self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget) self.horizontalLayout.setMargin(0) self.progressbar = QProgressBar(self.horizontalLayoutWidget) self.progressbar.setFixedWidth(260) self.progressbar.setMinimum(0) self.progressbar.setMaximum(100) self.stopButton = QPushButton(self.horizontalLayoutWidget) self.stopButton.setFlat(True) self.stopButton.setIcon(Icons.stop) self.stopButton.setFixedSize(16,16) self.horizontalLayout.addWidget(self.progressbar) self.horizontalLayout.addWidget(self.stopButton) self.vl.addWidget(self.horizontalLayoutWidget) self.stopButton.clicked.connect(self.forceStop) def setValue(self,val): self.progressbar.setValue(val) def forceStop(self): self.emit(SIGNAL("forceStop"))
class ProgressWidget(QgsMessageBar): def __init__(self, min, max, message, parent=None, timeout = 1.5): """ Constructs a progress widget """ super(self.__class__, self).__init__(parent) self.min = min self.max = max sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) if parent: self.setMinimumSize(parent.width(),40) else: self.setMinimumSize(766,40) self.setSizePolicy(sizePolicy) self.progressBar = QProgressBar() self.progressBar.setMinimum(min) self.progressBar.setMaximum(max) self.msgBarItem = QgsMessageBarItem(self.tr("INFO: "), message, self.progressBar, level=QgsMessageBar.INFO, duration=timeout) self.pushWidget(self.msgBarItem) def initBar(self): """ Initializes the progress bar """ self.progressBar.setValue(0) def step(self): """ Increments the progress bar """ value = self.progressBar.value() + 1 self.progressBar.setValue(value) if value == self.max: time.sleep(1) self.close()
class ForgotPasswordUi(BaseWindow, QtGui.QMainWindow): requestSendingCompleted = QtCore.pyqtSignal() def __init__(self, parent=None): super(ForgotPasswordUi, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.forgot.clicked.connect(self.forgot) self.ui.forgot.setDefault(True) self.shortcut = QtGui.QShortcut(QtGui.QKeySequence("Return"), self) self.shortcut.activated.connect(self.forgot) self.shortcut2 = QtGui.QShortcut(QtGui.QKeySequence("Up"), self) self.shortcut2.activated.connect(self.focusUp) self.shortcut2 = QtGui.QShortcut(QtGui.QKeySequence("Down"), self) self.shortcut2.activated.connect(self.focusDown) self.progressIndicator = QProgressBar(self.ui.statusBar) self.progressIndicator.setMinimumHeight(5) self.progressIndicator.setVisible(False) self.progressIndicator.setMaximum(0) self.progressIndicator.setMinimum(0) self.ui.statusBar.addWidget(self.progressIndicator) self.requestSendingCompleted.connect(self.requestSendingCompleteSlot) self.uiTranslate() def uiTranslate(self): self.setWindowTitle(strings["forgotPasswordWindowTitle"]) self.ui.username.setPlaceholderText(strings["usernameBoxHint"]) self.ui.email.setPlaceholderText(strings["emailBoxHint"]) self.ui.forgot.setText(strings["forgotPasswordButtonText"]) def requestSendingCompleteSlot(self): self.progressIndicator.setVisible(False) self.showMessageBox.emit(strings["forgotSuccessText"]) def focusUp(self): self.ui.username.setFocus() def focusDown(self): self.ui.email.setFocus() def forgot(self): self.progressIndicator.setVisible(True) def requestSenderThread(): if self.ui.username.text() and self.ui.email.text(): try: requestRecovery(self.ui.username.text(), self.ui.email.text()) self.requestSendingCompleted.emit() except SecureMessagingException as error: self.showMessageBox.emit(strings["errorText"] + responseTranslations[str(error)]) else: self.showMessageBox.emit(strings["missingFieldsErrorText"]) Thread(target=requestSenderThread).start()
def launch(self): progressMessageBar = self.iface.messageBar().createMessage("Obteniendo informacion del catastro... ") progress = QProgressBar() progress.setMaximum(0) progress.setMinimum(0) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, self.iface.messageBar().INFO) self.parcelaService.procDone.connect(self.callback) self.parcelaService.start()
class AddUserGui(BaseWindow): addUserCompleted = QtCore.pyqtSignal() def __init__(self, parent=None): super(AddUserGui, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.adduser.clicked.connect(self.adduser) self.progressIndicator = QProgressBar(self.ui.statusBar) self.progressIndicator.setMinimumHeight(5) self.progressIndicator.setVisible(False) self.progressIndicator.setMaximum(0) self.progressIndicator.setMinimum(0) self.ui.statusBar.addWidget(self.progressIndicator) self.addUserCompleted.connect(self.addUserCompletedSlot) self.uiTranslate() def uiTranslate(self): self.setWindowTitle(strings["registerUserWindowTitle"]) self.ui.username.setPlaceholderText(strings["usernameBoxHint"]) self.ui.password.setPlaceholderText(strings["passwordBoxHint"]) self.ui.email.setPlaceholderText(strings["emailBoxHint"]) self.ui.confirm.setPlaceholderText(strings["confirmPasswordBoxHint"]) self.ui.adduser.setText(strings["registerUserButtonText"]) def addUserCompletedSlot(self): self.progressIndicator.setVisible(False) self.showMessageBox.emit(strings["registrationSuccessText"]) def adduser(self): self.progressIndicator.setVisible(True) def addUserThread(): name = self.ui.username.text() password = self.ui.password.text() confirm = self.ui.confirm.text() email = self.ui.email.text() if name == "" or password == "" or email == "": self.showMessageBox.emit(strings["missingFieldsErrorText"]) return if password != confirm: self.showMessageBox.emit(strings["passwordsDontMatchErrorText"]) return try: addUser(name, email, password) self.addUserCompleted.emit() except SecureMessagingException as error: self.showMessageBox.emit(strings["errorText"] + responseTranslations[str(error)]) return Thread(target=addUserThread).start()
class AsyncProgressDialog(QDialog): """ dialog with progress bar to be shown during the asynchronous process """ def __init__(self, parent=None): super(AsyncProgressDialog, self).__init__(parent) self.setFixedSize(300, 40) self.setLayout(QBoxLayout(QBoxLayout.TopToBottom, self)) self.progress_bar = QProgressBar(self) self.progress_bar.setFixedSize(280, 20) self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(10) self.progress_bar.setTextVisible(False) self.layout().addWidget(self.progress_bar)
class QtProgressBar(QtControl, ProxyProgressBar): """ A Qt implementation of an Enaml ProxyProgressBar. """ #: A reference to the widget created by the proxy. widget = Typed(QProgressBar) #-------------------------------------------------------------------------- # Initialization API #-------------------------------------------------------------------------- def create_widget(self): """ Create the underlying progress bar widget. """ self.widget = QProgressBar(self.parent_widget()) def init_widget(self): """ Create and initialize the underlying widget. """ super(QtProgressBar, self).init_widget() d = self.declaration self.set_minimum(d.minimum) self.set_maximum(d.maximum) self.set_value(d.value) self.set_text_visible(d.text_visible) #-------------------------------------------------------------------------- # ProxyProgressBar API #-------------------------------------------------------------------------- def set_minimum(self, value): """ Set the minimum value of the widget. """ self.widget.setMinimum(value) def set_maximum(self, value): """ Set the maximum value of the widget. """ self.widget.setMaximum(value) def set_value(self, value): """ Set the value of the widget. """ self.widget.setValue(value) def set_text_visible(self, visible): """ Set the text visibility on the widget. """ self.widget.setTextVisible(visible)
def createProgressbar(self, loopnumber): """ Create a progress bar when iterating over features """ progressMessageBar = self.messageBar.createMessage( unicode("Chargement des données...", "utf-8")) progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(loopnumber) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.messageBar.pushWidget(progressMessageBar, self.messageBar.INFO) return progress
def __init__(self, iface, provincia,municipio,x,y,callback): #super(Ui_ProgressDialog, self).__init__(parent) self.thread = ParcelaService(provincia,municipio) self.thread.initCoords(x,y) self.iface = iface progressMessageBar = iface.messageBar().createMessage("Obteniendo informacion del catastro... ") progress = QProgressBar() progress.setMaximum(0) progress.setMinimum(0) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, iface.messageBar().INFO) self.thread.procDone.connect(self.fin) self.thread.start()
def _progress_bar_factory_function(self, window_parent, editor, *args, **kwargs): """ Returns a QProgressBar widget for a TraitsUI window. Used by CustomEditor(factory=_progress_bar_factory_function, args=('tuple',) Can't just return self.progress_bar one should be should be created here and then set. window_parent = <PyQt4.QtGui.QBoxLayout object at ...> editor = <traitsui.qt4.custom_editor.CustomEditor object at ...> """ progress_bar = QProgressBar() progress_bar.setMinimum(self.min) progress_bar.setMaximum(self.max) self.progress_bar = progress_bar return progress_bar
def run(self): """Create the output shapefile.""" gpsStatus = self.checkGpsStatus() if gpsStatus: pass #QMessageBox.warning(None, "Test", "Create GPS SHP") elif gpsStatus == None: QMessageBox.warning(None, "Verzeichnis", u"Es wurde kein Bildverzeichnis für diesen Film gefunden.") return else: QMessageBox.warning(None, "Bilder", u"Die vorhandenen Bilder enthalten keine GPS Information.") return check = QFile(self.shpFile) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shpFile): msg = 'Unable to delete existing shapefile "{}"' self.iface.messageBar().pushMessage(u"Error", u"Die Datei existiert bereits und kann nicht überschrieben werden (Eventuell in QGIS geladen!).", level=QgsMessageBar.CRITICAL, duration=10) return False #fields fields = QgsFields() fields.append(QgsField("bildnr", QVariant.Int)) fields.append(QgsField("lat", QVariant.Double)) fields.append(QgsField("lon", QVariant.Double)) fields.append(QgsField("alt", QVariant.Double)) writer = QgsVectorFileWriter(str(self.shpFile), "UTF-8", fields, QGis.WKBPoint, QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId)) mb = self.iface.messageBar().createMessage(u"EXIF", u"Die EXIF Daten (Geo Koordinaten und Höhe) werden aus den Bildern ausgelesen") progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(0) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) mb.layout().addWidget(progress) self.iface.messageBar().pushWidget(mb, QgsMessageBar.INFO) for feature in self.iter_points(): writer.addFeature(feature) del writer self.iface.messageBar().clearWidgets() self.iface.messageBar().pushMessage(u"EXIF", u"Die Shape Datei wurde erfolgreich erstellt und in QGIS geladen!", level=QgsMessageBar.SUCCESS, duration=10) return self.shpFile
def _draw_transfer_item(self, container, filename, id, part_number, peer_ip, percent): items_found = container.findItems(id, Qt.MatchExactly, 1) item = None if len(items_found) > 0: for i in items_found: if i.text(4) == peer_ip and i.text(2) == str(part_number): item = i break if item: container.itemWidget(item, 3).setValue(percent) else: item = QTreeWidgetItem(container, QStringList([str(filename), str(id), str(part_number), "0", str(peer_ip)])) progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(100) progress_bar.setValue(percent) container.setItemWidget(item, 3, progress_bar)
def __init__(self, parent): QProgressBar.__init__(self, parent) self.fLeftClickDown = False self.fMinimum = 0.0 self.fMaximum = 1.0 self.fRealValue = 0.0 self.fLabel = "" self.fPreLabel = " " self.fTextCall = None self.setFormat("(none)") # Fake internal value, 10'000 precision QProgressBar.setMinimum(self, 0) QProgressBar.setMaximum(self, 10000) QProgressBar.setValue(self, 0)
def start_worker(worker, iface, message, with_progress=True): # configure the QgsMessageBar message_bar = iface.messageBar().createMessage(message) progress_bar = QProgressBar() progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) if not with_progress: progress_bar.setMinimum(0) progress_bar.setMaximum(0) cancel_button = QPushButton() cancel_button.setText('Cancel') cancel_button.clicked.connect(worker.kill) message_bar.layout().addWidget(progress_bar) message_bar.layout().addWidget(cancel_button) iface.messageBar().pushWidget(message_bar, iface.messageBar().INFO) # start the worker in a new thread # let Qt take ownership of the QThread thread = QThread(iface.mainWindow()) worker.moveToThread(thread) worker.set_message.connect(lambda message: set_worker_message( message, message_bar_item)) worker.toggle_show_progress.connect(lambda show: toggle_worker_progress( show, progress_bar)) worker.toggle_show_cancel.connect(lambda show: toggle_worker_cancel( show, cancel_button)) worker.finished.connect(lambda result: worker_finished( result, thread, worker, iface, message_bar)) worker.error.connect(lambda e, exception_str: worker_error( e, exception_str, iface)) worker.progress.connect(progress_bar.setValue) thread.started.connect(worker.run) thread.start() return thread, message_bar
class ProgressDialog(QDialog): def __init__(self, parent, title='', info_start='', maximum=100, add=0): QDialog.__init__(self, parent) self.add=add self.setWindowTitle(title) vbox=QVBoxLayout() self.info=QLabel(self) vbox.addWidget(self.info) self.info.setText(info_start) self.progressBar=QProgressBar() self.progressBar.setMaximum(maximum) self.progressBar.setMinimum(0) vbox.addWidget(self.progressBar) self.setLayout(vbox) def progress(self, value): param=value*100+self.add self.progressBar.setValue(param) app=QApplication.instance() app.processEvents()
def syncstarted(self): # Remove the old widget if it's still there. # I don't really like this. Seems hacky. try: self.iface.messageBar().popWidget(self.syncwidget) except RuntimeError: pass except AttributeError: pass self.iface.messageBar().findChildren(QToolButton)[0].setVisible(False) self.syncwidget = self.iface.messageBar().createMessage("Syncing", "Sync in progress", QIcon(":/icons/syncing")) button = QPushButton(self.syncwidget) button.setCheckable(True) button.setText("Status") button.setIcon(QIcon(":/icons/syncinfo")) button.toggled.connect(functools.partial(self.report.setVisible)) pro = QProgressBar() pro.setMaximum(0) pro.setMinimum(0) self.syncwidget.layout().addWidget(pro) self.syncwidget.layout().addWidget(button) self.iface.messageBar().pushWidget(self.syncwidget, QgsMessageBar.INFO)
def updateshows(self): ''' Update local shows with remote content ''' label = QLabel('Updating: ') bar = QProgressBar() bar.setMinimum(0) bar.setMaximum(self.ui.showlist.model().rowCount()) bar.setValue(bar.minimum()) self.ui.statusbar.addWidget(label) self.ui.statusbar.addWidget(bar) for row in range(self.ui.showlist.model().rowCount()): self.backend.updateshow(self.ui.showlist.model().getshow(row).id) bar.setValue(row) self.ui.statusbar.removeWidget(bar) self.ui.statusbar.removeWidget(label) now = datetime.now() self.settings.set(settings.categories.application, settings.keys.lastupdated, now) self.setlastupdatedstatus(now) self.displayshowstatuses()
def displayshowstatuses(self): ''' Set the show statuses for all shows This only really needs to be done at the start or after updating data ''' label = QLabel('Updating status: ') self.ui.statusbar.addWidget(label) shows = self.backend.getlocalshows() showbar = QProgressBar() showbar.setMinimum(0) showbar.setMaximum(len(shows)) showbar.setValue(showbar.minimum()) self.ui.statusbar.addWidget(showbar) for show in shows: self.displayshowstatus(show.id) showbar.setValue(shows.index(show) + 1) self.ui.statusbar.removeWidget(showbar) self.ui.statusbar.removeWidget(label)
class ClientDialog(QDialog): """a simple popup dialog for asking the player what he wants to do""" def __init__(self, client, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(m18n('Choose') + ' - Kajongg') self.setObjectName('ClientDialog') self.client = client self.layout = QGridLayout(self) self.progressBar = QProgressBar() self.timer = QTimer() if not client.game.autoPlay: self.timer.timeout.connect(self.timeout) self.deferred = None self.buttons = [] self.setWindowFlags(Qt.SubWindow | Qt.WindowStaysOnTopHint) self.setModal(False) self.btnHeight = 0 self.answered = False def keyPressEvent(self, event): """ESC selects default answer""" if not self.client.game or self.client.game.autoPlay: return if event.key() in [Qt.Key_Escape, Qt.Key_Space]: self.selectButton() event.accept() else: for btn in self.buttons: if str(event.text()).upper() == btn.message.shortcut: self.selectButton(btn) event.accept() return QDialog.keyPressEvent(self, event) def __declareButton(self, message): """define a button""" maySay = self.client.sayable[message] if Preferences.showOnlyPossibleActions and not maySay: return btn = DlgButton(message, self) btn.setAutoDefault(True) btn.clicked.connect(self.selectedAnswer) self.buttons.append(btn) def focusTileChanged(self): """update icon and tooltip for the discard button""" if not self.client.game: return for button in self.buttons: button.decorate(self.client.game.myself.handBoard.focusTile) for tile in self.client.game.myself.handBoard.lowerHalfTiles(): txt = [] for button in self.buttons: _, _, tileTxt = button.message.toolTip(button, tile) if tileTxt: txt.append(tileTxt) txt = '<br><br>'.join(txt) tile.graphics.setToolTip(txt) if self.client.game.activePlayer == self.client.game.myself: Internal.field.handSelectorChanged(self.client.game.myself.handBoard) def checkTiles(self): """does the logical state match the displayed tiles?""" for player in self.client.game.players: logExposed = list() physExposed = list() physConcealed = list() for tile in player.bonusTiles: logExposed.append(tile.element) for tile in player.handBoard.tiles: if tile.yoffset == 0 or tile.element[0] in 'fy': physExposed.append(tile.element) else: physConcealed.append(tile.element) for meld in player.exposedMelds: logExposed.extend(meld.pairs) logConcealed = sorted(player.concealedTileNames) logExposed.sort() physExposed.sort() physConcealed.sort() assert logExposed == physExposed, '%s != %s' % (logExposed, physExposed) assert logConcealed == physConcealed, '%s != %s' % (logConcealed, physConcealed) def messages(self): """a list of all messages returned by the declared buttons""" return list(x.message for x in self.buttons) def proposeAction(self): """either intelligently or first button by default. May also focus a proposed tile depending on the action.""" result = self.buttons[0] game = self.client.game if game.autoPlay or Preferences.propose: answer, parameter = self.client.intelligence.selectAnswer( self.messages()) result = [x for x in self.buttons if x.message == answer][0] result.setFocus() if answer in [Message.Discard, Message.OriginalCall]: for tile in game.myself.handBoard.tiles: if tile.element == parameter: game.myself.handBoard.focusTile = tile return result def askHuman(self, move, answers, deferred): """make buttons specified by answers visible. The first answer is default. The default button only appears with blue border when this dialog has focus but we always want it to be recognizable. Hence setBackgroundRole.""" self.move = move self.deferred = deferred for answer in answers: self.__declareButton(answer) self.focusTileChanged() self.show() self.checkTiles() game = self.client.game myTurn = game.activePlayer == game.myself prefButton = self.proposeAction() if game.autoPlay: self.selectButton(prefButton) return prefButton.setFocus() self.progressBar.setVisible(not myTurn) if not myTurn: msecs = 50 self.progressBar.setMinimum(0) self.progressBar.setMaximum(game.ruleset.claimTimeout * 1000 // msecs) self.progressBar.reset() self.timer.start(msecs) def placeInField(self): """place the dialog at bottom or to the right depending on space.""" field = Internal.field cwi = field.centralWidget() view = field.centralView geometry = self.geometry() if not self.btnHeight: self.btnHeight = self.buttons[0].height() vertical = view.width() > view.height() * 1.2 if vertical: height = (len(self.buttons) + 1) * self.btnHeight * 1.2 width = (cwi.width() - cwi.height() ) // 2 geometry.setX(cwi.width() - width) geometry.setY(min(cwi.height()//3, cwi.height() - height)) else: handBoard = self.client.game.myself.handBoard if not handBoard: # we are in the progress of logging out return hbLeftTop = view.mapFromScene(handBoard.mapToScene(handBoard.rect().topLeft())) hbRightBottom = view.mapFromScene(handBoard.mapToScene(handBoard.rect().bottomRight())) width = hbRightBottom.x() - hbLeftTop.x() height = self.btnHeight geometry.setY(cwi.height() - height) geometry.setX(hbLeftTop.x()) for idx, btn in enumerate(self.buttons + [self.progressBar]): self.layout.addWidget(btn, idx+1 if vertical else 0, idx+1 if not vertical else 0) idx = len(self.buttons) + 2 spacer = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Expanding) self.layout.addItem(spacer, idx if vertical else 0, idx if not vertical else 0) geometry.setWidth(width) geometry.setHeight(height) self.setGeometry(geometry) def showEvent(self, dummyEvent): """try to place the dialog such that it does not cover interesting information""" self.placeInField() def timeout(self): """the progressboard wants an update""" pBar = self.progressBar if isAlive(pBar): pBar.setValue(pBar.value()+1) pBar.setVisible(True) if pBar.value() == pBar.maximum(): # timeout: we always return the original default answer, not the one with focus self.selectButton() pBar.setVisible(False) def selectButton(self, button=None): """select default answer. button may also be of type Message.""" self.timer.stop() self.answered = True if button is None: button = self.focusWidget() if isinstance(button, Message): assert any(x.message == button for x in self.buttons) answer = button else: answer = button.message if not self.client.sayable[answer]: Sorry(m18n('You cannot say %1', answer.i18nName)) return Internal.field.clientDialog = None self.deferred.callback(answer) def selectedAnswer(self, dummyChecked): """the user clicked one of the buttons""" game = self.client.game if game and not game.autoPlay: self.selectButton(self.sender())
class HomeWidget(BaseWidget): def __init__(self, parent=0, *args, **kwargs): super(HomeWidget, self).__init__(parent=parent, *args, **kwargs) # inputs self._json_fpath = None self._destination_folder = self.guess_destination() self._from_date, self._to_date = self.guess_dates() self.nb_instances = 0 self.setup_ui() @property def json_fpath(self): return self._json_fpath @json_fpath.setter def json_fpath(self, value): self._json_fpath = value self.json_select_button.setText( value if value else "Sélection fichier JSON ODK Aggregate ...") self.update_start_button_state() @property def destination_folder(self): return self._destination_folder @destination_folder.setter def destination_folder(self, value): self._destination_folder = value self.destination_select_button.setText(self.destination_folder) self.update_start_button_state() @property def from_date(self): return self._from_date @from_date.setter def from_date(self, value): self._from_date = value self.from_date_selector.setPythonDate(self.from_date) self.update_start_button_state() @property def to_date(self): return self._to_date @to_date.setter def to_date(self, value): self._to_date = value self.to_date_selector.setPythonDate(self.to_date) self.update_start_button_state() def setup_ui(self): # json file selector self.json_groupbox = QGroupBox("Export ODK Aggregate") layout = QGridLayout() self.json_select_button = PushButton("", self) self.json_select_button.clicked.connect(self.json_selector_clicked) layout.addWidget(self.json_select_button, 1, 0) self.json_groupbox.setLayout(layout) # destination folder selector self.destination_groupbox = QGroupBox("Destination") layout = QGridLayout() self.destination_select_button = PushButton(self.destination_folder, self) self.destination_select_button.clicked.connect( self.destination_selector_clicked) layout.addWidget(self.destination_select_button, 1, 0) self.destination_groupbox.setLayout(layout) # period calendars today = datetime.date.today() self.period_groupbox = QGroupBox("Période") layout = QGridLayout() self.from_date_selector = DateTimeEdit(QDate(self.from_date)) self.from_date_selector.dateChanged.connect(self.from_date_changed) self.from_date_selector.setMaximumDate(self.to_date) self.to_date_selector = DateTimeEdit(QDate(self.to_date)) self.to_date_selector.dateChanged.connect(self.to_date_changed) self.to_date_selector.setMinimumDate(self.from_date) self.to_date_selector.setMaximumDate(today) layout.addWidget(Label("Du"), 2, 0) layout.addWidget(self.from_date_selector, 3, 0) layout.addWidget(Label("Au"), 2, 1) layout.addWidget(self.to_date_selector, 3, 1) self.period_groupbox.setLayout(layout) # start button self.start_button = PushButton("Démarrer") self.start_button.setEnabled(False) self.start_button.setDefault(True) self.start_button.clicked.connect(self.export_requested) # cancel button self.cancel_button = CancelPushButton("Annuler") self.cancel_button.setEnabled(False) self.cancel_button.clicked.connect(self.cancel_export) # grid self.gridBox = QGridLayout() self.gridBox.addWidget(self.json_groupbox, 0, 0, 1, 2) self.gridBox.addWidget(self.destination_groupbox, 1, 0, 1, 2) self.gridBox.addWidget(self.period_groupbox, 2, 0, 1, 2) self.gridBox.addWidget(self.start_button, 3, 0) self.gridBox.addWidget(self.cancel_button, 3, 1) vBox = QVBoxLayout() vBox.addLayout(self.gridBox) self.setLayout(vBox) self.json_fpath = None def guess_destination(self, root_only=False): start_folder = os.path.join(os.path.expanduser("~"), 'Desktop') if root_only: return start_folder return os.path.join(start_folder, Constants.DEFAULT_FOLDER_NAME) def guess_dates(self): to = datetime.date.today() start = to - datetime.timedelta(days=15) return start, to def update_start_button_state(self): self.start_button.setEnabled( all([ self.json_fpath, self.destination_folder, self.from_date, self.to_date ])) def json_selector_clicked(self): # self.file_name_field.setText("Aucun fichier") self.start_button.setEnabled(False) fpath = QFileDialog.getOpenFileName( self, "Choisir le fichier d'export JSON", self.json_fpath or self.guess_destination(root_only=True), "Fichiers JSON (*.json)") self.json_fpath = os.path.abspath(fpath) if fpath else self.json_fpath def destination_selector_clicked(self): path = QFileDialog.getExistingDirectory(self, "Sélectionner le dossier", self.destination_folder) if path: self.destination_folder = os.path.abspath(path) def from_date_changed(self, new_date): self.from_date = new_date.toPyDate() def to_date_changed(self, new_date): self.to_date = new_date.toPyDate() def export_requested(self): logger.debug("export_requested") self.parentWidget().exporter.check_aggregate_presence() def display_missing_aggregate_confirmation(self): if MissingODKConfirmationWidget().exec_() == QDialog.Accepted: self.start_export() def start_export(self): logger.debug("Lancement ...") self.add_progressbar() self.start_button.setEnabled(False) self.cancel_button.setEnabled(True) self.parentWidget().exporter.parse( destination_folder=self.destination_folder, fname=self.json_fpath, from_date=self.from_date, to_date=self.to_date) def cancel_export(self): logger.debug("cancel") self.parentWidget().exporter.cancel() def update_progress_label(self, index): progression_label = "Export en cours... {index}/{total}" \ .format(index=index, total=self.nb_instances) self.progression_groupbox.setTitle(progression_label) def add_progressbar(self): self.progressbar = QProgressBar() self.progressbar.setMinimum(0) self.progressbar.setMaximum(100) self.progressbar.reset() self.progressbar.setTextVisible(False) self.progression_groupbox = QGroupBox("...") progress_layout = QHBoxLayout() progress_layout.addWidget(self.progressbar) self.progression_groupbox.setLayout(progress_layout) self.gridBox.addWidget(self.progression_groupbox, 4, 0, 1, 2) def remove_progressbar(self): self.progression_groupbox.deleteLater() self.progression_groupbox = None @pyqtSlot(bool, int, str) def parsing_ended(self, succeeded, nb_instances, error_message): if succeeded: self.nb_instances = nb_instances @pyqtSlot(str, int) def exporting_instance(self, ident, index): logger.debug("exporting_instance") self.update_progress_label(index) @pyqtSlot(bool, int) def instance_completed(self, succeeded, index): logger.debug("instance_completed") pc = index * 100 // self.nb_instances self.progressbar.setValue(pc) @pyqtSlot(int, int, int, int) def export_ended(self, nb_instances_successful, nb_instances_failed, nb_medias_successful, nb_medias_failed): self.cancel_button.setEnabled(False) self.start_button.setEnabled(True) @pyqtSlot() def export_canceled(self): self.remove_progressbar() self.cancel_button.setEnabled(False) self.start_button.setEnabled(True) QMessageBox.warning( self, "Export annulé !", "L'export en cours a été annulé.\n" "Tous les fichiers créés ont été supprimés", QMessageBox.Ok, QMessageBox.NoButton) if self.parentWidget().is_exiting: self.parentWidget().do_close()
class Form(QMainWindow, Ui_MainWindow): """IT Query Main Window.""" def __init__(self, initIds, initErrIds, parent=None): """Setup main window and populate with data(if given).""" super(Form, self).__init__(parent) self.setupUi(self) self.setWindowTitle("IT Query {0}".format(__version__)) self.selectedIds = initIds self.errorIds = initErrIds LOG_LEVEL = logging.INFO currTime = time.localtime() runDate = time.strftime("%Y-%m-%d", currTime) self.dbPath = DB.Db.Info.Path LOG_FNAME = "{0}\{1}-{2}.{3}".format(self.dbPath, "itquery", runDate, "txt") if LOG_LEVEL == logging.INFO: LOG_FORMAT = "%(asctime)s\t%(message)s" else: LOG_FORMAT = ("%(asctime)s - %(levelname)s - %(funcName)s " " - %(message)s") self.logger = logging.getLogger("itquery") self.logger.setLevel(LOG_LEVEL) self.handler = logging.FileHandler(LOG_FNAME) formatter = logging.Formatter(LOG_FORMAT) self.handler.setFormatter(formatter) self.logger.addHandler(self.handler) for action, slot in ((self.updateButton, self.updateSelection), (self.bionumericsButton, self.bnSelectFields), (self.itemTrackerButton, self.itSelectFields)): action.clicked.connect(slot) for action, slot in ((self.actionCollapseAll, self.collapseAll), (self.actionExpandAll, self.expandAll), (self.actionCollapseItem, self.collapseItem), (self.actionCherryPicking, self.cherryPicking), (self.actionExpandItem, self.expandItem), (self.actionSelectAll, self.selectAll), (self.actionSelectDNA, self.selectDNA), (self.actionSelectFrozenStock, self.selectFrozenStock), (self.actionSelectInvert, self.selectInvert), (self.actionSelectNone, self.selectNone), (self.actionGetAllSelected, self.getAllSelected), (self.actionRefresh, self.refresh), (self.actionAbout, self.about), (self.actionViewTree, self.viewTree), (self.actionClearLog, self.clearLog), (self.actionLegend, self.legend), (self.actionExportTraceList, self.exportTraceList), (self.actionExportDNAList, self.exportDNAList), (self.actionClose, self.close)): action.triggered.connect(slot) self.treeWidget.itemSelectionChanged.connect(self.updateInfo) self.viewMenu.addAction(self.logDockWidget.toggleViewAction()) icon = QIcon(":/text-x-log.png") self.logDockWidget.toggleViewAction().setIcon(icon) self.actionSelectInBionumerics.toggled.connect(self.selectInBionumerics) self.userComboBox.currentIndexChanged.connect(self.userChanged) self.statusComboBox.currentIndexChanged.connect(self.statusChanged) self.treeActions = QActionGroup(self) self.treeActions.addAction(self.actionExpandItem) self.treeActions.addAction(self.actionCollapseItem) self.treeActions.addAction(self.actionExpandAll) self.treeActions.addAction(self.actionCollapseAll) self.selectActions = QActionGroup(self) self.selectActions.addAction(self.actionSelectAll) self.selectActions.addAction(self.actionSelectNone) self.selectActions.addAction(self.actionSelectInvert) self.selectActions.addAction(self.actionSelectDNA) self.selectActions.addAction(self.actionSelectFrozenStock) self.exportActions = QActionGroup(self) self.exportActions.addAction(self.actionExportDNAList) self.exportActions.addAction(self.actionExportTraceList) self.statusbar.setSizeGripEnabled(True) # user label at the right end of status bar # db = lims.DATABASE db = "No information" dbLabel = QLabel("Database: <b>{0}</b>".format(db)) self.statusbar.addPermanentWidget(dbLabel) user = os.environ.get("USERNAME") or "Demo user" label = QLabel("Logged in as: <b>{0}</b>".format(user)) self.statusbar.addPermanentWidget(label) # restore main window state settings = QSettings() size = settings.value("MainWindow/Size", QVariant(QSize(600, 500))).toSize() self.resize(size) position = settings.value("MainWindow/Position", QVariant(QPoint(0, 0))).toPoint() self.move(position) self.restoreState(settings.value("MainWindow/State").toByteArray()) splitterState = settings.value("MainWindow/SplitState").toByteArray() self.splitter.restoreState(splitterState) # selected fields self.dbName = bns.ConnectedDb.ConnectDb.GetList() regKey = "Bionumerics/{0}/SelFields".format(self.dbName) regBnFields = settings.value(regKey).toStringList() self.bnSelectedFields = [unicode(item) for item in regBnFields] regItFields = settings.value("ItemTracker/SelFields").toStringList() self.itSelectedFields = [unicode(item) for item in regItFields] # progress bar self.progressBar = QProgressBar(self) self.progressBar.setMaximumWidth(200) self.statusbar.insertPermanentWidget(0, self.progressBar) self.progressBar.hide() # initialize variables self.itemIds = {} self.itemNames = {} # bnFields - bionumerics information in the info panel self.bnFields = {} self.strainInfo = {} # maintains list of keys that are updated self.updatedStrains = [] self.selectRadioButton.setChecked(True) self.itemProperties = {} self.tableResults = [] self.getBnFields() self.mkInfo("{0}. Log: {1}".format(time.asctime(), LOG_FNAME)) self.populatedTree = False self.populatedTable = False self.populatedCherry = False idField = "ItemTracker ID" # Field with ItemTracker ID self.itemIdsAll, errors = bn.getItemIds(idField, DB.Db.Entries) if len(errors): for key, message in errors.iteritems(): self.mkError("Key: {0}, {1}".format(key, message)) self.database = None self.updateUi() self.proxyModel = SortFilterProxyModel(self) self.proxyModel.setDynamicSortFilter(True) self.cherryView.setModel(self.proxyModel) self.cherryView.setAlternatingRowColors(True) self.cherryView.setSortingEnabled(True) self.cherryView.verticalHeader().setVisible(False) self.cherryView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.cherryView.horizontalHeader().setStretchLastSection(True) #self.populateTree() # testing QTimer.singleShot(0, self.populateTree) def bnSelectFields(self): """Bionumerics field selection dialog.""" try: fieldNames = bn.getFieldNames() except RuntimeError as e: self.mkError("Failed to get Bionumerics field names: {0}".format(e)) dialog = selectfieldsdlg.selectFieldsDialog(fieldNames, self) if self.bnSelectedFields is not None: dialog.setSelected(self.bnSelectedFields) if dialog.exec_(): self.bnSelectedFields = dialog.getSelected() self.updateInfo() def addCherryData(self, model, row): """Inserts row into model""" model.insertRow(0) for position, value in enumerate(row): model.setData(model.index(0, position), value) def createCherryModel(self, data, parent): """Creates a model for the tableview using data retrieved from the cherry picking database. """ total = len(data) self.progressBar.setMaximum(total) self.progressBar.show() model = QStandardItemModel(0, len(CHERRY_COLUMNS), parent) for position, column in enumerate(CHERRY_COLUMNS): model.setHeaderData(position, Qt.Horizontal, column) # get additional data for each item keys = [item[CHERRY_COLUMNS.index("Key")] for item in data] itemIds = [] missing = [] itemIdsAll = dict((v, k) for k, v in self.itemIdsAll.iteritems()) for key in keys: if key in itemIdsAll: itemIds.append(itemIdsAll[key]) else: missing.append(key) if len(missing): msg = ("Keys exist in cherry picking database but absent " "in Bionumerics {0}".format(", ".join(missing))) self.mkWarn(msg) if not len(itemIds): msg = "No entries in cherry picking database" self.statusBar().showMessage(msg, 5000) self.mkInfo(msg) return None itemIds = list(set(itemIds)) (dnaData, noData, errors) = lims.GetNewestDNAForCherryPicking(itemIds) if len(noData): msg = ", ".join(str(item) for item in noData) self.mkWarn("{0}: {1}".format("No DNA's for these strains", msg)) if len(errors): msg = ", ".join(errors) self.mkError(msg) for count, result in enumerate(data): result = list(result) key = result[0] if key in itemIdsAll: self.progressBar.setValue(count) #QApplication.processEvents() parentID = itemIdsAll[key] if parentID in dnaData: properties = dnaData[parentID] for value in ("ItemName", "DNA concentration", "Volume", "Freezer", "Rack", "Shelf", "PlateRack", "Position"): if value in properties: result.append(properties[value]) else: result.append("") self.addCherryData(model, result) return model def cherryPicking(self): """Populate the cherry picking table""" if self.populatedCherry: if not self.stackedWidget.currentIndex() == 2: self.stackedWidget.setCurrentIndex(2) self.updateUi() return self.statusbar.showMessage("Getting data from cherry picking database") db = DB.Db.Info.Name cherryData = pgdb.get_data(db) if not len(cherryData): msg = "No cherry picking entries for this database" self.statusbar.showMessage(msg, 5000) self.mkInfo(msg) self.stackedWidget.setCurrentIndex(2) self.updateUi() return self.userComboBox.clear() self.statusComboBox.clear() # filter combo boxes for label, combo in (("Username", self.userComboBox), ("Status", self.statusComboBox)): position = CHERRY_COLUMNS.index(label) comboItems = set([item[position] for item in cherryData]) combo.addItem("All") combo.addItems(list(comboItems)) self.proxyModel.traceStatus = self.statusComboBox.currentText() self.cherryView.reset() self.cherryView.setDisabled(True) self.statusbar.showMessage("Getting data from ItemTracker") model = self.createCherryModel(cherryData, self) if not model: self.cherryView.setEnabled(False) self.filterGroupBox.setDisabled(True) else: self.proxyModel.setSourceModel(model) self.cherryView.setEnabled(True) self.filterGroupBox.setEnabled(True) self.cherryView.resizeColumnsToContents() self.updateCounts() self.stackedWidget.setCurrentIndex(2) # switch view to table self.statusbar.clearMessage() self.progressBar.setValue(len(cherryData)) self.progressBar.hide() self.populatedCherry = True self.updateUi() def statusChanged(self): """Filter cherry picking based on current trace status from combo box.""" self.proxyModel.setTraceStatus(self.statusComboBox.currentText()) self.updateCounts() def userChanged(self): """Filter cherry picking based on current user from combo box.""" user = self.userComboBox.currentText() if user == "All": user = "******" regExp = QRegExp(user, Qt.CaseInsensitive, QRegExp.RegExp2) self.proxyModel.setFilterRegExp(regExp) self.updateCounts() def updateCounts(self): """Update counts of strains, traces and DNA in cherry picking""" strains = [] traces = self.proxyModel.rowCount() dna = [] for i in range(traces): for field, totals in (("Key", strains), ("DNA", dna)): index = self.proxyModel.index(i, CHERRY_COLUMNS.index(field)) data = self.proxyModel.data(index).toString().trimmed() if len(data) and data not in totals: totals.append(data) self.strainsLcdNumber.display(len(strains)) self.tracesLcdNumber.display(traces) self.dnaLcdNumber.display(len(dna)) def getSaveFile(self, caption=""): """Opens the save file dialog and returns the file name.""" if not len(caption): caption = "Save File As" fn = QFileDialog.getSaveFileName(self, caption, self.dbPath, "Text files (*.txt);;All Files (*.*)") if fn: if QFileInfo(fn).suffix().isEmpty(): fn += ".txt" return fn def exportTextFile(self, fh=None, header=None, data=None): """Writes data to the given file. Accepts column names and the data as arguments """ if not fh: self.mkError("Could not open file for writing") return if not data: data = [] if not len(data): self.mkWarn("No data to write") return fname = QFile(fh) if fname.open(QFile.WriteOnly | QFile.Text): txt = QTextStream(fname) if header: txt << ", ".join(col for col in header) txt << "\n" txt << "\n".join(", ".join(item) for item in data) msg = "File export complete: {0}".format(str(fname.fileName())) self.mkSuccess(msg) def exportDNAList(self): """Export list of DNA's displayed in cherry picking.""" data = [] keys = [] columns = CHERRY_COLUMNS[:] excludeColumns = ["Gene", "Orientation"] exclude = [] for item in excludeColumns: exclude.append(CHERRY_COLUMNS.index(item)) columns.remove(item) keyIndex = CHERRY_COLUMNS.index("Key") dnaIndex = CHERRY_COLUMNS.index("DNA") for i in range(0, self.proxyModel.rowCount()): # continue if key exists in keys index = self.proxyModel.index(i, keyIndex) key = self.proxyModel.data(index).toString() if key in keys: continue # continue if DNA column is empty index = self.proxyModel.index(i, dnaIndex) dna = self.proxyModel.data(index).toString() if dna.isEmpty(): continue row = [] for j in range(self.proxyModel.columnCount()): if j in exclude: continue index = self.proxyModel.index(i, j) value = self.proxyModel.data(index).toString() if not value.isEmpty(): row.append(str(value)) else: row.append("") data.append(row) keys.append(key) fh = self.getSaveFile("Export DNA List") self.exportTextFile(fh, columns, data) def exportTraceList(self): """Export list of traces displayed in cherry picking.""" data = [] for i in range(0, self.proxyModel.rowCount()): row = [] for j in range(self.proxyModel.columnCount()): index = self.proxyModel.index(i, j) value = self.proxyModel.data(index).toString() if not value.isEmpty(): row.append(str(value)) else: row.append("") data.append(row) fh = self.getSaveFile("Export Trace List") columns = CHERRY_COLUMNS[:] self.exportTextFile(fh, columns, data) def clearLog(self): """Clears the log window""" self.logBrowser.clear() def closeEvent(self, event): """Called on closing the window. Save settings and exit.""" self.handler.close() self.logger.removeHandler(self.handler) if self.okToContinue(): settings = QSettings() settings.setValue("MainWindow/Size", QVariant(self.size())) settings.setValue("MainWindow/Position", QVariant(self.pos())) settings.setValue("MainWindow/State", QVariant(self.saveState())) settings.setValue("MainWindow/SplitState", self.splitter.saveState()) bnSelectedFields = QVariant(self.bnSelectedFields) \ if self.bnSelectedFields else QVariant() regkey = "Bionumerics/{0}/SelFields".format(self.dbName) settings.setValue(regkey, bnSelectedFields) itSelectedFields = QVariant(self.itSelectedFields) \ if self.itSelectedFields else QVariant() settings.setValue("ItemTracker/SelFields", itSelectedFields) else: event.ignore() def collapseItem(self): """Collapse selected item.""" try: selected = self.treeWidget.selectedItems()[0] except IndexError: selected = None self.statusbar.showMessage("No item selected", 2000) if selected: self.treeWidget.collapseItem(selected) def collapseAll(self): """Collapse all items.""" self.treeWidget.collapseAll() def disableWidgets(self, widgets): """Disable group of widgets. Does not change visibility.""" for widget in widgets: if widget.isEnabled(): widget.setDisabled(True) def enableWidgets(self, widgets): """Enable group of widgets. Set visible if not visible.""" for widget in widgets: if not widget.isEnabled(): widget.setEnabled(True) if not widget.isVisible(): widget.setVisible(True) def expandItem(self): """Expand selected item.""" try: selected = self.treeWidget.selectedItems()[0] except IndexError: selected = None self.statusbar.showMessage("No item selected", 2000) if selected: self.treeWidget.expandItem(selected) def expandAll(self): """Expands all items.""" self.treeWidget.expandAll() def getBnFields(self): """Get bionumerics field information required for the info panel.""" bnFields = bn.getFieldNames() strainFields = ["Strain", "STRAIN"] for field in strainFields: if (field in bnFields) and (field not in self.bnSelectedFields): self.bnSelectedFields.append(field) for key in self.selectedIds.values(): if not self.bnFields.get(key): self.bnFields[key] = bn.getSelectedFields(key, bnFields) def getParent(self, item): """Returns the top level parent of an item.""" parentItem = None while item.parent(): parentItem = item.parent() item = parentItem return parentItem def getData(self, items, itemid): """Returns parent and children for data received from GetDictionary.""" if len(items): children = items[itemid].keys() yield itemid, children items = items[itemid] for child in children: for res in self.getData(items, child): yield res return def getAllItemIds(self): """Gets all ItemTracker IDs in the current Bionumerics database.""" itemIds = {} field = "ItemTracker ID" value = None for i in range(len(DB.Db.Entries)): value = DB.Db.Entries[i].Field(field).Content # bugfix: don't display if ItemTracker ID contains spaces value = value.strip() if not len(value): continue key = DB.Db.Entries[i].Key key = key.strip() if key in itemIds: itemIds.pop(key) msg = "Duplicate keys in database: {0}. Not processed".format(key) self.mkWarn(msg) continue try: value = int(value) except (ValueError, TypeError): self.mkWarn("Invalid ItemTracker ID {0} for entry " "{1} in Bionumerics".format(value, key)) if isinstance(value, int): if value in itemIds.values(): msg = ("Duplicate ItemTracker ID: {0}. " "Keys: {1}, ".format(value, key)) for k, v in itemIds.items(): if v == value: itemIds.pop(k) msg += k self.mkWarn(msg) else: itemIds[key] = value return itemIds def getAllSelected(self): """Get all selected items by user.""" if self.populatedTable: self.stackedWidget.setCurrentIndex(1) self.updateUi() return msg = "Getting all selected entries from ItemTracker. Please wait..." self.statusbar.showMessage(msg) if len(self.itemIdsAll): try: self.tableResults = \ lims.SelectAllselectedEntries(self.itemIdsAll.keys()) except: raise RuntimeError else: self.mkInfo("No ItemTracker IDs to process") if not len(self.tableResults): user = os.environ.get("USERNAME") msg = "No selected entries for user {0}".format(user) self.statusbar.showMessage(msg, 5000) self.mkInfo(msg) self.stackedWidget.setCurrentIndex(1) self.populatedTable = False self.updateUi() else: QTimer.singleShot(0, self.populateTable) def getItemtrackerFields(self): """Returns all ItemTracker fields returned from GetDictionary.""" fields = [] alwaysFields = ["ItemID", "ItemName", "Position"] for item in self.itemProperties: for field in self.itemProperties[item].keys(): if (field not in fields) and (field not in alwaysFields): fields.append(field) return fields def getWidget(self): """Returns the current active widget.""" index = self.stackedWidget.currentIndex() if index == 0: widget = self.treeWidget elif index == 1: widget = self.selectedWidget elif index == 2: widget = self.cherryView return widget def about(self): """About box.""" import platform msg = """\ <b>IT Query</b> version {0} <p>An interface to query ItemTracker from Bionumerics</p>Python {1} - Qt {2} - PyQt {3} on {4}\ """.format(__version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system()) msg += """<br>Icons from the <a href="http://www.oxygen-icons.org/">Oxygen project</a> </p>""" QMessageBox.about(self, "About IT Query", msg) def legend(self): """A simple dialog displaying the color legend used in treeview.""" dialog = legenddlg.legendDialog(self) dialog.exec_() def itSelectFields(self): """ItemTracker field selection dialog.""" fieldNames = self.getItemtrackerFields() dialog = selectfieldsdlg.selectFieldsDialog(fieldNames, self) if self.itSelectedFields is not None: dialog.setSelected(self.itSelectedFields) if dialog.exec_(): self.itSelectedFields = dialog.getSelected() self.updateInfo() def mkWarn(self, msg): """Orange color""" bgColor = "235,115,49" self.mkTable(bgColor, "WARNING", msg) def mkError(self, msg): """Red color""" bgColor = "226,8,0" self.mkTable(bgColor, "ERROR", msg) def mkSuccess(self, msg): """Green color""" bgColor = "55,164,44" self.mkTable(bgColor, "SUCCESS", msg) def mkInfo(self, msg): """Blue color""" bgColor = "0,87,174" self.mkTable(bgColor, "INFO", msg) def mkTable(self, bgColor, status, msg): """Formats message displayed in the log window.""" formatStatus = ('<font style="color:rgb({0})"><strong>{1}</strong>' '</font>'.format(bgColor, status)) self.logBrowser.append("{0}: {1}".format(formatStatus, msg)) def okToContinue(self): """Check before closing.""" if len(self.updatedStrains): reply = QMessageBox(QMessageBox.Question, "Selection", "Entry selection in Bionumerics", QMessageBox.NoButton, self) originalButton = QPushButton("Keep Original Selection") updatedButton = QPushButton("Updated Items Only") cancelButton = QPushButton("Cancel") reply.addButton(originalButton, QMessageBox.ActionRole) reply.addButton(updatedButton, QMessageBox.ActionRole) reply.addButton(cancelButton, QMessageBox.RejectRole) reply.exec_() if reply.clickedButton() == cancelButton: return False elif reply.clickedButton() == originalButton: bn.selectEntries(self.selectedIds.values() +\ self.errorIds.keys()) elif reply.clickedButton() == updatedButton: bn.selectEntries(self.updatedStrains) return True def populateTable(self): """Populates table with data from ItemTracker.""" self.selectedWidget.clear() self.selectedWidget.setSortingEnabled(False) numRows = len(self.tableResults) self.mkInfo("Selected items in ItemTracker: {0}".format(numRows)) self.selectedWidget.setAlternatingRowColors(True) header = ["ItemID", "StrainID", "ItemType", "ItemName", "BacteriaItemID"] self.selectedWidget.setColumnCount(len(header)) self.selectedWidget.setHeaderLabels(header) # use result and populate table for result in self.tableResults: properties = [unicode(i) for i in result] item = QTreeWidgetItem(self.selectedWidget, properties) item.setCheckState(0, Qt.Unchecked) self.selectedWidget.setSortingEnabled(True) for i in range(len(header)): self.selectedWidget.resizeColumnToContents(i) self.stackedWidget.setCurrentIndex(1) # switch view to table self.statusbar.clearMessage() self.populatedTable = True self.updateUi() def populateTree(self): """Populates tree view with information from ItemTracker.""" if len(self.errorIds): self.mkError("{0} entries do not have valid " "ItemTracker IDs in Bionumerics.".format(len(self.errorIds))) for key, msg in self.errorIds.iteritems(): self.mkError("KEY: {0} {1}".format(key, msg)) if not len(self.selectedIds): self.statusbar.showMessage("No items to process", 5000) return parents = {} headers = ["Items", "Selected", "SelectedBy", "Viability", "Volume", "DNA concentration", "UserName", "TubePresent", "InputDate", "AlternID", "Status"] self.treeWidget.setItemsExpandable(True) self.treeWidget.setAlternatingRowColors(True) self.treeWidget.setColumnCount(len(headers)) self.treeWidget.setHeaderLabels(headers) msg = "Getting information from ItemTracker. Please wait..." self.statusbar.showMessage(msg) self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.show() (treeData, self.itemProperties, message) = lims.GetDictionary((self.selectedIds.keys())) if len(message): for msg in message: self.mkError("ItemTracker error: {0}".format(msg)) if not len(treeData): self.mkError("Could not get data from ItemTracker for" "selected entries") self.statusBar().clearMessage() self.progressBar.hide() self.updateUi() return # bugfix: If ItemType property does not exist for the first item # self.database is not set and tree view is not updated. db = None if not self.database: for item in self.itemProperties.values(): try: db = item["ItemType"] except KeyError: pass if db == "Salmonella": self.database = db break elif db == "Listeria": self.database = db break self.progressBar.setMaximum(len(treeData)) count = 0 for key, value in treeData.iteritems(): count += 1 self.progressBar.setValue(count) if not(value and isinstance(value, dict)): self.mkWarn("No data returned for key {0}".format(key)) continue items = {} items[key] = value for results in self.getData(items, key): parent = parents.get(results[0]) if not parent: parent_id = self.selectedIds[results[0]] self.strainInfo[parent_id] = {self.database:[], "Frozen Stock":[], "DNA":[]} parent = QTreeWidgetItem(self.treeWidget, [unicode(parent_id)]) brush = QBrush() brush.setColor(Qt.blue) parent.setForeground(0, brush) parent.setIcon(0, QIcon(":/branch-closed.png")) parent.setData(0, Qt.CheckStateRole, QVariant()) parents[results[0]] = parent for children in results[1]: itemName = self.itemProperties[children]["ItemName"] if not self.itemIds.get(itemName): self.itemIds[itemName] = children childprops = [] childprops.append(unicode(itemName)) for header in headers[1:]: try: childprop = self.itemProperties[children][header] if childprop is None or childprop == "": childprops.append(unicode("")) else: childprops.append(unicode(childprop)) except KeyError: childprops.append(unicode("")) continue childs = parents.get(children) if not childs: childs = QTreeWidgetItem(parent, childprops) if self.itemProperties[children]["TubePresent"] == "-": childs.setBackgroundColor(0, QColor(232, 87, 82)) childs.setForeground(0, QColor(255, 255, 255)) if self.itemProperties[children]["Selected"] == "yes": childs.setBackgroundColor(0, QColor(119, 183, 83)) childs.setForeground(0, QColor(255, 255, 255)) itype = self.itemProperties[children]["ItemType"] if itype: self.strainInfo[parent_id][itype].append(itemName) parents[children] = childs childs.setCheckState(0, Qt.Unchecked) self.treeWidget.expandAll() for i in range(len(headers)): self.treeWidget.resizeColumnToContents(i) if not self.treeWidget.isEnabled(): self.treeWidget.setEnabled(True) self.mkInfo("Processed <b>{0}</b> entries".format(len(treeData))) self.progressBar.setValue(len(treeData)) self.progressBar.hide() self.populatedTree = True self.updateUi() self.statusbar.showMessage("Ready", 5000) def selectAll(self): """All items are selected (checked).""" index = self.stackedWidget.currentIndex() widget = self.getWidget() it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.NotChecked) count = 0 if index == 0: while it.value(): if it.value().parent(): it.value().setCheckState(0, Qt.Checked) count += 1 it += 1 elif index == 1: while it.value(): it.value().setCheckState(0, Qt.Checked) count += 1 it += 1 if count: self.statusbar.showMessage("Selected {0} items".format(count), 3000) def selectDNA(self): """Select all DNA items.""" self.selectItems("DNA") def selectFrozenStock(self): """Select all Frozen Stock items.""" self.selectItems("Frozen Stock") def selectNone(self): """Clears the selection.""" widget = self.getWidget() it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.Checked) while it.value(): it.value().setCheckState(0, Qt.Unchecked) it += 1 def selectInvert(self): """Inverts the selection.""" index = self.stackedWidget.currentIndex() widget = self.getWidget() it = QTreeWidgetItemIterator(widget) if index == 0: while it.value(): if it.value().parent(): if it.value().checkState(0) == Qt.Checked: it.value().setCheckState(0, Qt.Unchecked) else: it.value().setCheckState(0, Qt.Checked) it += 1 else: while it.value(): if it.value().checkState(0) == Qt.Checked: it.value().setCheckState(0, Qt.Unchecked) else: it.value().setCheckState(0, Qt.Checked) it += 1 def selectItems(self, itemType): """Select all items of a given ItemType.""" self.statusbar.showMessage("Selecting all {0}'s. " "Please wait...".format(itemType)) items = [] itemsAll = [] index = self.stackedWidget.currentIndex() if index == 0: position = 0 items = [item[itemType] for item in self.strainInfo.values()] for item in items: if len(item): itemsAll += item else: position = 3 for item in self.tableResults: if item[2] == itemType: itemsAll.append(item[3]) if not len(itemsAll): self.statusbar.showMessage("No {0}'s in list".format(itemType), 5000) return self.selectNone() widget = self.getWidget() it = QTreeWidgetItemIterator(widget) while it.value(): if it.value().text(position) in itemsAll: it.value().setCheckState(0, Qt.Checked) it += 1 self.statusbar.showMessage("Selected {0} {1}'s".format(len(itemsAll), itemType), 3000) def selectInBionumerics(self, on): """Selects Bionumerics entries with checked items from table view (get all selected) """ actionGroup = QActionGroup(self) actionGroup.addAction(self.actionViewTree) actionGroup.addAction(self.refresh_action) actionGroup.addAction(self.actionSelectAll) actionGroup.addAction(self.actionSelectInvert) actionGroup.addAction(self.actionSelectNone) actionGroup.addAction(self.actionSelectDNA) actionGroup.addAction(self.actionSelectFrozenStock) if on: actionGroup.setEnabled(False) if not len(self.itemNames): self.itemNames = bn.createIdMap() it = QTreeWidgetItemIterator(self.selectedWidget, QTreeWidgetItemIterator.Checked) checkedItems = [] while it.value(): parentCode = unicode(it.value().text(4)) bnStrain = self.itemNames[int(parentCode)] if bnStrain not in checkedItems: checkedItems.append(bnStrain) it += 1 if len(checkedItems): bn.selectEntries(checkedItems) else: self.statusbar.showMessage("No items checked", 3000) else: actionGroup.setEnabled(True) bn.selectEntries(self.selectedIds.values() + self.errorIds.keys()) def updateSelection(self): """Updates selection status in ItemTracker.""" if self.actionSelectInBionumerics.isChecked(): self.selectInBionumerics(False) self.actionSelectInBionumerics.setChecked(False) self.updateButton.setEnabled(False) self.statusbar.showMessage("Updating selection. Please wait...") if self.selectRadioButton.isChecked(): selectedAction = "SELECT" elif self.deselectRadioButton.isChecked(): selectedAction = "DESELECT" checkedItems = {} updatedItems = [] failedItems = [] index = self.stackedWidget.currentIndex() widget = self.getWidget() it = QTreeWidgetItemIterator(widget, QTreeWidgetItemIterator.Checked) if index == 0: while it.value(): itemName = unicode(it.value().text(0)) itemId = self.itemIds[itemName] checkedItems[itemName] = itemId parentItem = self.getParent(it.value()) strain = unicode(parentItem.text(0)) if strain not in self.updatedStrains: self.updatedStrains.append(strain) it += 1 elif index == 1: if not len(self.itemNames): self.itemNames = bn.createIdMap() while it.value(): itemId = unicode(it.value().text(0)) itemName = unicode(it.value().text(3)) checkedItems[itemName] = int(itemId) parentCode = unicode(it.value().text(4)) strain = self.itemNames[int(parentCode)] if strain not in self.updatedStrains: self.updatedStrains.append(strain) it += 1 if not len(checkedItems): self.statusbar.showMessage("No items checked", 5000) self.updateButton.setEnabled(True) return for itemName, itemId in checkedItems.iteritems(): if selectedAction == "SELECT": result = lims.SelectItem(itemId) elif selectedAction == "DESELECT": result = lims.UnselectItem(itemId) if not len(result): updatedItems.append(itemName) else: failedItems.append(itemName) if len(updatedItems): self.mkSuccess("{0}ED {1} items".format(selectedAction, len(updatedItems))) self.logBrowser.append("{0}".format(", ".join(updatedItems))) self.logger.info("{0}\t{1}".format(selectedAction, ", ".join(updatedItems))) if len(failedItems): self.mkError("{0} failed for {1} items".format(selectedAction, len(failedItems))) self.logBrowser.append("{0}".format(", ".join(failedItems))) self.logger.info("{0}\t{1}".format(selectedAction, ", ".join(failedItems))) self.updateButton.setEnabled(True) if len(updatedItems) or len(failedItems): self.populatedTree = False self.populatedTable = False self.refresh() def updateUi(self): """Updates interface based on the view.""" index = self.stackedWidget.currentIndex() # only show export actions in cherry picking if index != 2: widgets = [self.exportToolBar, self.exportActions] self.disableWidgets(widgets) for widget in widgets: widget.setVisible(False) # disable select menu in cherry picking (not implemented) if index == 2: self.selectMenu.setEnabled(False) else: self.selectMenu.setEnabled(True) if index == 0: # Tree View self.disableWidgets([self.actionViewTree, self.actionSelectInBionumerics]) self.enableWidgets([self.actionGetAllSelected, self.actionCherryPicking]) for widget in [self.actionSelectInBionumerics, self.getSelectedToolBar]: widget.setVisible(False) #self.fieldsGroupBox.setVisible(True) widgets = [self.widget, self.treeWidget, self.selectGroupBox, self.fieldsGroupBox, self.actionLegend, self.treeToolBar, self.treeActions, self.selectActions] for widget in widgets: if not widget.isVisible(): widget.setVisible(True) if self.populatedTree: self.enableWidgets(widgets) else: self.disableWidgets(widgets) try: self.treeWidget.selectedItems()[0] except IndexError: self.infoBrowser.setDisabled(True) self.fieldsGroupBox.setEnabled(self.infoBrowser.isEnabled()) elif index == 1: self.widget.setVisible(True) self.enableWidgets([self.actionViewTree, self.actionCherryPicking]) self.actionSelectInBionumerics.setVisible(True) self.getSelectedToolBar.setVisible(True) for widget in [self.actionLegend, self.fieldsGroupBox, self.treeToolBar, self.treeActions]: widget.setVisible(False) self.disableWidgets([self.actionGetAllSelected, self.actionLegend, self.treeToolBar, self.treeActions]) widgets = [self.widget, self.selectedWidget, self.selectGroupBox, self.actionSelectInBionumerics, self.getSelectedToolBar, self.selectActions] if self.populatedTable: self.enableWidgets(widgets) else: self.disableWidgets(widgets) elif index == 2: self.widget.setVisible(False) # ItemTracker and field selection self.actionCherryPicking.setEnabled(False) self.exportToolBar.setVisible(True) self.exportActions.setVisible(True) for action in [self.actionViewTree, self.actionGetAllSelected]: action.setEnabled(True) widgets = [self.selectActions, self.actionSelectInBionumerics, self.actionLegend, self.treeActions, self.treeToolBar, self.getSelectedToolBar] self.disableWidgets(widgets) for widget in widgets: widget.setVisible(False) widgets = [self.cherryView, self.filterGroupBox, self.lcdGroupBox, self.exportActions, self.exportToolBar] if self.populatedCherry: self.enableWidgets(widgets) else: self.disableWidgets(widgets) def updateInfo(self): """Infobar displaying ItemTracker and Bionumerics fields.""" content = ('<table border="0" cellspacing="0" ' 'cellpadding="5" width="100%">') self.infoBrowser.clear() try: selected = self.treeWidget.selectedItems()[0] except IndexError: return else: self.infoBrowser.setEnabled(True) self.fieldsGroupBox.setEnabled(True) try: parentName = self.getParent(selected).text(0) except AttributeError: parentName = None if parentName: itemName = unicode(selected.text(0)) itemId = self.itemIds[itemName] if itemId: content += """\ <tr bgcolor="#85026C"> <th colspan="2" align="left"> <font color="white">ITEMTRACKER</font> </th> </tr>\ """ count = 0 for field, value in (("Strain", parentName), ("Item Name", itemName), ("Item ID", itemId)): if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) count += 1 try: properties = self.itemProperties[int(itemId)] except KeyError: self.mkWarn("Could not get properties for " "ItemTracker ID {0}".format(itemId)) if len(properties): try: location = properties["Position"] except KeyError: location = [] if len(location): for field, value in (("Freezer", location[0]), ("Rack", location[1]), ("Shelf", location[2]), ("Plate Rack", location[3]), ("Position", location[4])): if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, value) count += 1 if len(self.itSelectedFields): for itField in self.itSelectedFields: try: itemProperty = properties[itField] except KeyError: itemProperty = "" if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(itField, itemProperty) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(itField, itemProperty) count += 1 else: content += """\ <tr> <td colspan="2">No information</td> </tr>""" self.infoBrowser.setHtml(QString(content)) content += """\ <tr bgcolor="#CF4913"> <th colspan="2" align="left"> <font color="white">BIONUMERICS</font> </th> </tr>\ """ strainInfo = {} try: strainInfo = self.bnFields.get(unicode(parentName)) except KeyError: self.mkWarn("Could not get information for {0}".format(parentName)) if len(strainInfo): count = 0 for field in self.bnSelectedFields: if count % 2 == 0: content += """\ <tr> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, strainInfo[field]) else: content += """\ <tr bgcolor="#eee"> <td>{0}</td> <td>{1}</td> </tr>\ """.format(field, strainInfo[field]) count += 1 else: self.mkWarn("No information for {0}".format(parentName)) content += "</table>" else: strainName = unicode(selected.text(0)) itemId = None for ids, keys in self.selectedIds.iteritems(): if keys == strainName: itemId = ids break if not itemId: self.infoBrowser.setHtml(QString(content)) return content = """\ <table border="0" cellpadding="5" cellspacing="0" width="100%"> <tr bgcolor="#85026C"> <th colspan="2" align="left"> <font color="white">ITEMTRACKER</font> </th> </tr> <tr bgcolor="#eee"> <td>AlternID</td> <td>{0}</td> </tr> <tr> <td>OriginalID</td> <td>{1}</td> </tr>\ """.format(self.itemProperties[itemId]["AlternID"], self.itemProperties[itemId]["OriginalID"]) content += "</table>" content += """\ <table border="0" cellpadding="5" cellspacing="0" width="100%"> <tr bgcolor="#BF0361"> <th align="left"> <font color="white">{0}</font> </th> <th align="right"> <font color="white">{1}</font> </th> </tr> <tr> <td colspan="2">{2}</td> </tr>\ """.format(self.database.upper(), len(self.strainInfo[strainName][self.database]), ", ".join(self.strainInfo[strainName][self.database])) content += """\ <tr bgcolor="#00438A"> <th align="left"> <font color="white">FROZEN STOCK</font> </th> <th align="right"> <font color="white">{0}</font> </th> </tr> <tr> <td colspan="2">{1}</td> </tr>\ """.format(len(self.strainInfo[strainName]["Frozen Stock"]), ", ".join(self.strainInfo[strainName]["Frozen Stock"])) content += """\ <tr bgcolor="#00734D"> <th align="left"> <font color="white">DNA</font> </th> <th align="right"> <font color="white">{0}</font> </th> </tr> <tr> <td colspan="2">{1}</td> </tr>\ """.format(len(self.strainInfo[strainName]["DNA"]), ", ".join(self.strainInfo[strainName]["DNA"])) content += "</table>" self.infoBrowser.setHtml(QString(content)) def viewTree(self): """Toolbar button/action to switch to tree view.""" self.selectRadioButton.setChecked(True) if not self.populatedTree: self.stackedWidget.setCurrentIndex(0) self.refresh() self.stackedWidget.setCurrentIndex(0) self.updateUi() def refresh(self): """Updates view(s).""" index = self.stackedWidget.currentIndex() if index == 1: self.populatedTable = False self.selectedWidget.clear() self.getAllSelected() elif index == 0: self.populatedTree = False self.treeWidget.clear() self.treeWidget.setDisabled(True) bnField = "ItemTracker ID" self.selectedIds = {} self.errorIds = {} selection = DB.Db.Selection self.selectedIds, self.errorIds = bn.getItemIds(bnField, selection) if len(self.selectedIds): self.strainInfo = {} self.itemIds = {} self.getBnFields() # self.populateTree() QTimer.singleShot(0, self.populateTree) elif index == 2: self.populatedCherry = False QTimer.singleShot(0, self.cherryPicking) self.updateUi()
class QuadStatusBar(QHBoxLayout): positionChanged = pyqtSignal(int, int, int) # x,y,z def __init__(self, parent=None): QHBoxLayout.__init__(self, parent) self.setContentsMargins(0, 4, 0, 0) self.setSpacing(0) self.timeControlFontSize = 12 def showXYCoordinates(self): self.zLabel.setHidden(True) self.zSpinBox.setHidden(True) def showXYZCoordinates(self): self.zLabel.setHidden(False) self.zSpinBox.setHidden(False) def hideTimeSlider(self, flag): visibleBefore = not self.timeSlider.isHidden() self.timeSlider.setHidden(flag) self.timeEndButton.setHidden(flag) self.timeStartButton.setHidden(flag) self.timePreviousButton.setHidden(flag) self.timeNextButton.setHidden(flag) self._registerTimeframeShortcuts(enabled=not flag, remove=visibleBefore) def setToolTipTimeButtonsCrop(self, croppingFlag=False): if croppingFlag == True: self.timeStartButton.setToolTip( "Jump to lirst frame of current crop") self.timeEndButton.setToolTip("Jump to last frame of current crop") self.timePreviousButton.setToolTip("Previous Frame") self.timeNextButton.setToolTip("Next Frame") else: self.timeStartButton.setToolTip("First Frame") self.timeEndButton.setToolTip("Last Frame") self.timePreviousButton.setToolTip("Previous Frame") self.timeNextButton.setToolTip("Next Frame") def setToolTipTimeSliderCrop(self, croppingFlag=False): if croppingFlag == True: self.timeSlider.setToolTip( "Choose the time coordinate of the current crop.") else: self.timeSlider.setToolTip( "Choose the time coordinate of the current dataset.") def createQuadViewStatusBar(self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor): self.xLabel, self.xSpinBox = _get_pos_widget('X', xbackgroundColor, xforegroundColor) self.yLabel, self.ySpinBox = _get_pos_widget('Y', ybackgroundColor, yforegroundColor) self.zLabel, self.zSpinBox = _get_pos_widget('Z', zbackgroundColor, zforegroundColor) self.xSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'x')) self.ySpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'y')) self.zSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'z')) self.addWidget(self.xLabel) self.addWidget(self.xSpinBox) self.addWidget(self.yLabel) self.addWidget(self.ySpinBox) self.addWidget(self.zLabel) self.addWidget(self.zSpinBox) self.addSpacing(10) self.crosshairsCheckbox = QCheckBox() self.crosshairsCheckbox.setChecked(False) self.crosshairsCheckbox.setCheckable(True) self.crosshairsCheckbox.setText("Crosshairs") self.addWidget(self.crosshairsCheckbox) self.addSpacing(10) self.busyIndicator = QProgressBar() self.busyIndicator.setMaximumWidth(200) self.busyIndicator.setMaximum(0) self.busyIndicator.setMinimum(0) self.busyIndicator.setVisible(False) self.busyIndicator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.addWidget(self.busyIndicator) self.setStretchFactor(self.busyIndicator, 1) self.addStretch() self.addSpacing(20) self.timeSpinBox = DelayedSpinBox(750) icons_dir = os.path.dirname(volumina.__file__) + "/icons" self.timeStartButton = QToolButton() self.timeStartButton.setIcon(QIcon(icons_dir + "/skip-start.png")) self.addWidget(self.timeStartButton) self.timeStartButton.clicked.connect(self._onTimeStartButtonClicked) #self.timeStartButton.setFixedWidth(4*self.timeControlFontSize) self.timePreviousButton = QToolButton() self.timePreviousButton.setIcon(QIcon(icons_dir + "/play-reverse.png")) self.addWidget(self.timePreviousButton) self.timePreviousButton.clicked.connect( self._onTimePreviousButtonClicked) #self.timePreviousButton.setFixedWidth(4*self.timeControlFontSize) self.timeSlider = QSlider(Qt.Horizontal) self.timeSlider.setMinimumWidth(10) self.timeSlider.setMaximumWidth(200) self.setToolTipTimeSliderCrop() self.addWidget(self.timeSlider) self.timeSlider.valueChanged.connect(self._onTimeSliderChanged) self.timeNextButton = QToolButton() self.timeNextButton.setIcon(QIcon(icons_dir + "/play.png")) self.addWidget(self.timeNextButton) self.timeNextButton.clicked.connect(self._onTimeNextButtonClicked) #self.timeNextButton.setFixedWidth(4*self.timeControlFontSize) self.timeEndButton = QToolButton() self.timeEndButton.setIcon(QIcon(icons_dir + "/skip-end.png")) #self.timeEndButton.setFixedWidth(4*self.timeControlFontSize) self.setToolTipTimeButtonsCrop() self.addWidget(self.timeEndButton) self.timeEndButton.clicked.connect(self._onTimeEndButtonClicked) self.timeLabel = QLabel(" Time:") self.addWidget(self.timeLabel) timeControlFont = self.timeSpinBox.font() if self.timeControlFontSize > timeControlFont.pointSize(): timeControlFont.setPixelSize(2 * self.timeControlFontSize) self.timeStartButton.setFont(timeControlFont) self.timeEndButton.setFont(timeControlFont) self.timeLabel.setFont(timeControlFont) self.timeSpinBox.setFont(timeControlFont) self.addWidget(self.timeSpinBox) self.timeSpinBox.delayedValueChanged.connect( self._onTimeSpinBoxChanged) self._registerTimeframeShortcuts() def _registerTimeframeShortcuts(self, enabled=True, remove=True): """ Register or deregister "," and "." as keyboard shortcuts for scrolling in time """ mgr = ShortcutManager() ActionInfo = ShortcutManager.ActionInfo def action(key, actionInfo): if enabled: mgr.register(key, actionInfo) else: if remove: mgr.unregister(actionInfo) action( "<", ActionInfo("Navigation", "Go to next time frame", "Go to next time frame", self._onTimeNextButtonClicked, self.timeNextButton, self.timeNextButton)) action( ">", ActionInfo("Navigation", "Go to previous time frame", "Go to previous time frame", self._onTimePreviousButtonClicked, self.timePreviousButton, self.timePreviousButton)) def _onTimeStartButtonClicked(self): self.timeSpinBox.setValue( self.parent().parent().parent().editor.cropModel.get_roi_t()[0]) def _onTimeEndButtonClicked(self): self.timeSpinBox.setValue( self.parent().parent().parent().editor.cropModel.get_roi_t()[1]) def _onTimePreviousButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value() - 1) def _onTimeNextButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value() + 1) def _onTimeSpinBoxChanged(self): editor = self.parent().parent().parent().editor cropModel = editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): if minValueT > self.timeSpinBox.value( ) or maxValueT < self.timeSpinBox.value(): for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame( True) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame( False) self.timeSlider.setValue(self.timeSpinBox.value()) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame( False) if minValueT > self.timeSpinBox.value(): self.timeSlider.setValue(minValueT) elif maxValueT < self.timeSpinBox.value(): self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSpinBox.value( ) and self.timeSpinBox.value() <= maxValueT: self.timeSlider.setValue(self.timeSpinBox.value()) def _onTimeSliderChanged(self): cropModel = self.parent().parent().parent().editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): self.timeSpinBox.setValue(self.timeSlider.value()) else: if minValueT > self.timeSlider.value(): self.timeSpinBox.setValue(minValueT) self.timeSlider.setValue(minValueT) elif self.timeSlider.value() > maxValueT: self.timeSpinBox.setValue(maxValueT) self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSlider.value( ) and self.timeSlider.value() <= maxValueT: self.timeSpinBox.setValue(self.timeSlider.value()) def _handlePositionBoxValueChanged(self, axis, value): new_position = [ self.xSpinBox.value(), self.ySpinBox.value(), self.zSpinBox.value() ] changed_axis = ord(axis) - ord('x') new_position[changed_axis] = value self.positionChanged.emit(*new_position) def updateShape5D(self, shape5D): self.timeSpinBox.setMaximum(shape5D[0] - 1) self.xSpinBox.setMaximum(shape5D[1] - 1) self.ySpinBox.setMaximum(shape5D[2] - 1) self.zSpinBox.setMaximum(shape5D[3] - 1) def updateShape5Dcropped(self, shape5DcropMin, shape5Dmax): self.timeSpinBox.setMaximum(shape5Dmax[0] - 1) self.xSpinBox.setMaximum(shape5Dmax[1] - 1) self.ySpinBox.setMaximum(shape5Dmax[2] - 1) self.zSpinBox.setMaximum(shape5Dmax[3] - 1) self.timeSlider.setMaximum(shape5Dmax[0] - 1) self.timeSpinBox.setValue(shape5DcropMin[0]) self.xSpinBox.setValue(shape5DcropMin[1]) self.ySpinBox.setValue(shape5DcropMin[2]) self.zSpinBox.setValue(shape5DcropMin[3]) self.timeSlider.setValue(shape5DcropMin[0]) def setMouseCoords(self, x, y, z): self.xSpinBox.setValueWithoutSignal(x) self.ySpinBox.setValueWithoutSignal(y) self.zSpinBox.setValueWithoutSignal(z)
class LabelAssistDialog(QDialog): """ A simple UI for showing bookmarks and navigating to them. FIXME: For now, this window is tied to a particular lane. If your project has more than one lane, then each one will have it's own bookmark window, which is kinda dumb. """ def __init__(self, parent, topLevelOperatorView): super(LabelAssistDialog, self).__init__(parent) # Create thread router to populate table on main thread self.threadRouter = ThreadRouter(self) # Set object classification operator view self.topLevelOperatorView = topLevelOperatorView self.setWindowTitle("Label Assist") self.setMinimumWidth(500) self.setMinimumHeight(700) layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) # Show variable importance table rows = 0 columns = 4 self.table = QTableWidget(rows, columns) self.table.setHorizontalHeaderLabels(['Frame', 'Max Area', 'Min Area', 'Labels']) self.table.verticalHeader().setVisible(False) # Select full row on-click and call capture double click self.table.setSelectionBehavior(QTableView.SelectRows); self.table.doubleClicked.connect(self._captureDoubleClick) layout.addWidget(self.table, 1, 0, 3, 2) # Create progress bar self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.hide() layout.addWidget(self.progressBar, 4, 0, 1, 2) # Create button to populate table self.computeButton = QPushButton('Compute object info') self.computeButton.clicked.connect(self._triggerTableUpdate) layout.addWidget(self.computeButton, 5, 0) # Create close button closeButton = QPushButton('Close') closeButton.clicked.connect(self.close) layout.addWidget(closeButton, 5, 1) # Set dialog layout self.setLayout(layout) def _triggerTableUpdate(self): # Check that object area is included in selected features featureNames = self.topLevelOperatorView.SelectedFeatures.value if 'Standard Object Features' not in featureNames or 'Count' not in featureNames['Standard Object Features']: box = QMessageBox(QMessageBox.Warning, 'Warning', 'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"', QMessageBox.NoButton, self) box.show() return # Clear table self.table.clearContents() self.table.setRowCount(0) self.table.setSortingEnabled(False) self.progressBar.show() self.computeButton.setEnabled(False) def compute_features_for_frame(tIndex, t, features): # Compute features and labels (called in parallel from request pool) roi = [slice(None) for i in range(len(self.topLevelOperatorView.LabelImages.meta.shape))] roi[tIndex] = slice(t, t+1) roi = tuple(roi) frame = self.topLevelOperatorView.SegmentationImages(roi).wait() frame = frame.squeeze().astype(numpy.uint32, copy=False) # Dirty trick: We don't care what we're passing here for the 'image' parameter, # but vigra insists that we pass *something*, so we'll cast the label image as float32. features[t] = vigra.analysis.extractRegionFeatures(frame.view(numpy.float32), frame, ['Count'], ignoreLabel=0) tIndex = self.topLevelOperatorView.SegmentationImages.meta.axistags.index('t') tMax = self.topLevelOperatorView.SegmentationImages.meta.shape[tIndex] features = {} labels = {} def compute_all_features(): # Compute features in parallel pool = RequestPool() for t in range(tMax): pool.add( Request( partial(compute_features_for_frame, tIndex, t, features) ) ) pool.wait() # Compute labels labels = self.topLevelOperatorView.LabelInputs([]).wait() req = Request(compute_all_features) req.notify_finished( partial(self._populateTable, features, labels) ) req.submit() @threadRouted def _populateTable(self, features, labels, *args): self.progressBar.hide() self.computeButton.setEnabled(True) for time, feature in features.iteritems(): # Insert row rowNum = self.table.rowCount() self.table.insertRow(self.table.rowCount()) # Get max and min object areas areas = feature['Count']#objectFeatures['Standard Object Features']['Count'] maxObjArea = numpy.max(areas[numpy.nonzero(areas)]) minObjArea = numpy.min(areas[numpy.nonzero(areas)]) # Get number of labeled objects labelNum = numpy.count_nonzero(labels[time]) # Load fram number item = QTableWidgetItem(str(time)) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 0, item) # Load max object areas item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(maxObjArea))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 1, item) # Load min object areas item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(minObjArea))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 2, item) # Load label numbers item = QTableWidgetItemWithFloatSorting(str("{: .01f}".format(labelNum))) item.setFlags( Qt.ItemIsSelectable | Qt.ItemIsEnabled ) self.table.setItem(rowNum, 3, item) # Resize column size to fit dialog size self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch) # Sort by max object area self.table.setSortingEnabled(True) self.table.sortByColumn(1) def _captureDoubleClick(self): # Navigate to selected frame index = self.table.selectedIndexes()[0] frameStr = self.table.model().data(index).toString() if frameStr: frameNum = int(frameStr) self.parent().editor.posModel.time = frameNum
class MainWinGui(QtGui.QMainWindow): progressIndeterminate = QtCore.pyqtSignal() progressSet = QtCore.pyqtSignal(int) progressStop = QtCore.pyqtSignal() def __init__(self, parent=None): super(MainWinGui, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.myName.setText(getStoredName() or "") self.ui.myName.textEdited.connect(self.nameChanged) self.communicator = Communicator(self) self.communicator.peersUpdated.connect(self.refreshPeers) self.communicator.fileReceived.connect(self.fileReceived) self.ui.refreshPeersButton.clicked.connect(self.discoverPeers) self.ui.peerList.itemClicked.connect(self.peerSelected) self.progressIndeterminate.connect(self.progressIndeterminateSlot) self.progressSet.connect(self.progressSetSlot) self.progressStop.connect(self.progressStopSlot) self.progressIndicator = QProgressBar(self.ui.statusbar) self.progressIndicator.setMinimumHeight(5) self.progressIndicator.setVisible(False) self.progressIndicator.setMaximum(0) self.progressIndicator.setMinimum(0) self.ui.statusbar.addWidget(self.progressIndicator) def nameChanged(self, newName): storeName(newName) self.communicator.updateName(newName) def progressStart(self): self.progressIndicator.setVisible(True) def progressSetSlot(self, value): self.progressStart() self.progressIndicator.setMaximum(100) self.progressIndicator.setValue(value) def progressIndeterminateSlot(self): self.progressStart() self.progressIndicator.setMaximum(0) def progressStopSlot(self): self.progressIndicator.setVisible(False) def show(self): super(MainWinGui, self).show() self.refreshPeers() self.discoverPeers() def discoverPeers(self): self.communicator.discoverPeers() def refreshPeers(self): self.ui.peerList.clear() for peer in self.communicator.peers: peer = self.communicator.peers[peer] peerName = QListWidgetItem(self.ui.peerList) peerName.peer = peer nameFont = QtGui.QFont() nameFont.setPointSize(14) peerDetails = QListWidgetItem(self.ui.peerList) peerDetails.peer = peer detailsFont = QtGui.QFont() detailsFont.setPointSize(10) name = peer.name details = "" if peer.publicKey is None: details += "Unpaired, " else: details += "Paired, " if peer.lastKnownIP is None: details += "unavailable" else: details += "available: " + peer.lastKnownIP peerName.setFont(nameFont) peerName.setText(name) peerDetails.setFont(detailsFont) peerDetails.setText(details) self.ui.peerList.addItem(peerName) self.ui.peerList.addItem(peerDetails) separatorItem = QListWidgetItem(self.ui.peerList) separatorItem.guid = peer.guid separatorItem.peer = None separatorItem.setFlags(QtCore.Qt.NoItemFlags) self.ui.peerList.addItem(separatorItem) def peerSelected(self, selectedItem): selectedItem.setSelected(False) if selectedItem.peer: PeerOptionsUi(self, selectedItem.peer, self.communicator).show() else: pass def sendFile(self, guid): fileName = QtGui.QFileDialog.getOpenFileName() if not fileName: return fileContents = open(fileName, "rb").read() basename = os.path.basename(fileName) self.communicator.sendFile(basename, fileContents, guid) def fileReceived(self, fileName, fileContents): fileName = QtGui.QFileDialog.getSaveFileName(directory=fileName) if not fileName: return with open(fileName, mode="wb") as file: file.write(fileContents)
class LoadVfkPuWidget(PuWidget): """A widget for loading a VFK file.""" set_text_statusbar = pyqtSignal(str, int, bool) set_text_browseVfkLineEdit = pyqtSignal(str) set_value_loadVfkProgressBar = pyqtSignal(int) def _setup_self(self): """Sets up self.""" self.setObjectName(u'loadVfkPuWidget') self.gridLayout = QGridLayout(self) self.gridLayout.setObjectName(u'gridLayout') self._build_widgets() def _build_widgets(self): """Builds own widgets.""" self.set_text_statusbar.connect(self.dW.statusBar.set_text) self.set_text_statusbar.emit(u'Vyberte VFK soubor.', 0, False) self.browseVfkLabel = QLabel(self) self.browseVfkLabel.setObjectName(u'browseVfkLabel') self.browseVfkLabel.setText(u'VFK soubor:') self.gridLayout.addWidget(self.browseVfkLabel, 0, 0, 1, 1) self.browseVfkLineEdit = QLineEdit(self) self.browseVfkLineEdit.setObjectName(u'browseVfkLineEdit') self.set_text_browseVfkLineEdit.connect( self._set_text_browseVfkLineEdit) self.browseVfkLineEdit.textChanged.connect(self._check_vfk_file_path) self.gridLayout.addWidget(self.browseVfkLineEdit, 0, 1, 1, 1) self.browseVfkPushButton = QPushButton(self) self.browseVfkPushButton.setObjectName(u'browseVfkPushButton') self.browseVfkPushButton.clicked.connect(self._browse_vfk_files) self.browseVfkPushButton.setText(u'Procházet') self.gridLayout.addWidget(self.browseVfkPushButton, 0, 2, 1, 1) self.gridLayout.setRowStretch(1, 1) self.loadVfkProgressBar = QProgressBar(self) self.loadVfkProgressBar.setObjectName(u'loadVfkProgressBar') self.loadVfkProgressBar.setMinimum(0) self.set_value_loadVfkProgressBar.connect( self._set_value_loadVfkProgressBar) self.set_value_loadVfkProgressBar.emit(0) self.gridLayout.addWidget(self.loadVfkProgressBar, 2, 0, 1, 2) self.loadVfkPushButton = QPushButton(self) self.loadVfkPushButton.setObjectName(u'loadVfkPushButton') self.loadVfkPushButton.clicked.connect(self._start_loading_vfk_layer) self.loadVfkPushButton.setText(u'Načíst') self.loadVfkPushButton.setDisabled(True) self.gridLayout.addWidget(self.loadVfkPushButton, 2, 2, 1, 1) def _set_text_browseVfkLineEdit(self, text): """Sets the text to the browseVfkLineEdit. Args: text (str): A text to be set. """ self.browseVfkLineEdit.setText(text) def _set_value_loadVfkProgressBar(self, value): """Sets the value to the loadVfkProgressBar. Args: text (str): A value to be set. """ self.loadVfkProgressBar.setValue(value) def _browse_vfk_files(self): """Opens a file dialog and filters VFK files.""" title = u'Vyberte VFK soubor.' filters = u'.vfk (*.vfk)' filePath = self.dW.open_file_dialog(title, filters, True) if filePath: self.set_text_browseVfkLineEdit.emit(filePath) def _check_vfk_file_path(self): """Checks if the text in the browseVfkLineEdit is a path to a VFK file. If so, the loadVfkPushButton is enabled, otherwise the loadVfkPushButton is disabled. """ tempText = self.browseVfkLineEdit.text() tempFileInfo = QFileInfo(tempText) if tempFileInfo.isFile() and tempFileInfo.suffix() in (u'vfk', u'VFK'): self.loadVfkPushButton.setEnabled(True) else: self.loadVfkPushButton.setEnabled(False) def _start_loading_vfk_layer(self): """Starts loading the selected VFK file in a separate thread.""" self.set_text_statusbar.emit( u'Načítám VFK soubor. Tento proces může chvíli trvat...', 0, False) self._enable_load_widgets(False) filePath = self.browseVfkLineEdit.text() QgsApplication.processEvents() self.loadThread = LoadThread(filePath) self.loadThread.started.connect(self._run_loading_vfk_layer) self.loadThread.start() def _run_loading_vfk_layer(self, filePath): """Calls methods for loading a VFK layer. Disables loading widgets until the loading is finished. Args: filePath (str): A full path to the file. """ try: self.set_value_loadVfkProgressBar.emit(0) fileInfo = QFileInfo(filePath) dbPath = QDir(fileInfo.absolutePath())\ .filePath(fileInfo.completeBaseName() + '.db') layerCode = self.dW.parLayerCode vfkDriverName = 'VFK' layerName = fileInfo.completeBaseName() + '|' + layerCode self._create_db_file(filePath, dbPath, layerCode, vfkDriverName) self._open_database(dbPath) # SpatiaLite fix - start if not self.dW.fixedSqliteDriver: dbPath = self._create_spatialite_db_file(dbPath) # SpatiaLite fix - end self._load_vfk_layer(dbPath, layerName, layerCode, vfkDriverName) self.loadVfkProgressBar.setMaximum(1) self.set_value_loadVfkProgressBar.emit(1) self.set_text_statusbar.emit(u'Data byla úspešně načtena.', 0, False) except self.dW.puError: QgsApplication.processEvents() except: QgsApplication.processEvents() self.dW.display_error_messages( self, u'Error loading VFK file "{}".'.format(filePath), u'Chyba při načítání VFK souboru.', u'Chyba při načítání VFK souboru "{}".'.format(filePath)) finally: QgsApplication.processEvents() self._enable_load_widgets(True) def _create_db_file(self, filePath, dbPath, layerCode, vfkDriverName): """Creates a database file. It checks if a database of the same name as the file exists. If not it creates the database with a VFK driver. Args: filePath (str): A full path to the file. dbPath (str): A full path to the database. layerCode (str): A code of the layer. vfkDriverName (str): A name of the VFK driver. Raises: dw.puError: When the VFK driver failed to open VFK file or when the SQlite driver failed to open the database. """ QgsApplication.processEvents() dbInfo = QFileInfo(dbPath) if not dbInfo.isFile(): self.set_text_statusbar.emit( u'Importuji data do SQLite databáze...', 0, False) QgsApplication.processEvents() QgsApplication.registerOgrDrivers() vfkDriver = ogr.GetDriverByName(vfkDriverName) vfkDataSource = vfkDriver.Open(filePath) QgsApplication.processEvents() if not vfkDataSource: raise self.dW.puError( self.dW, self, u'Failed to load data, "{}" is not a valid VFK datasource.' .format(dbPath), u'Data nelze načíst.', u'Data nelze načíst, "{}" není platný datový zdroj VFK.'. format(dbPath)) layerCount, layerNames = self._check_layer_code( vfkDataSource, layerCode) self.loadVfkProgressBar.setMaximum(layerCount) for i in xrange(layerCount): self.set_value_loadVfkProgressBar.emit(i + 1) self.set_text_statusbar.emit( u'Načítám vrstvu {} ({}/{})...'.format( layerNames[i], i + 1, layerCount), 0, False) QgsApplication.processEvents() self._build_geometry(layerCode, vfkDataSource) QgsApplication.processEvents() for vertexLayerCode in self.dW.vertexLayerCodes: if vertexLayerCode in layerNames: self._build_geometry(vertexLayerCode, vfkDataSource) QgsApplication.processEvents() vfkDataSource.Destroy() sqliteDriver = ogr.GetDriverByName('SQLite') sqliteDataSource = sqliteDriver.Open(dbPath) if not sqliteDataSource: raise self.dW.puError( self.dW, self, u'Failed to load data, "{}" is not a valid SQLite datasource.'. format(dbPath), u'Data nelze načíst.', u'Data nelze načíst, "{}" není platný datový zdroj SQLite.'. format(dbPath)) layerCount, layerNames = self._check_layer_code( sqliteDataSource, layerCode) sqliteDataSource.Destroy() def _check_layer_code(self, dataSource, layerCode): """Checks if there is a layer code layer in the data source. Args: dataSource (osgeo.ogr.DataSource): A data source. layerCode (str): A code of the layer. Returns: int: A number of layers in the data source. list: A list of layer names in the data source. Raises: dw.puError: When there is no layer code layer in the data source. """ layerCount = dataSource.GetLayerCount() layerNames = [] for i in xrange(layerCount): layerNames.append(dataSource.GetLayer(i).GetLayerDefn().GetName()) if layerCode not in layerNames: QgsApplication.processEvents() dataSource.Destroy() raise self.dW.puError( self.dW, self, u'VFK file does not contain "{}" layer, therefore it can not be ' u'loaded by PU Plugin. The file can be ' u'loaded by "Add Vector Layer"'.format(layerCode), u'VFK soubor neobsahuje vrstvu {}.'.format(layerCode), u'VFK soubor neobsahuje vrstvu {}, proto nemůže být ' u'pomocí PU Pluginu načten. Data je možné načíst ' u'pomocí "Přidat vektorovou vrstvu."'.format(layerCode)) dataSourceInfo = (layerCount, layerNames) return dataSourceInfo def _build_geometry(self, layerCode, dataSource): """Builds a geometry for the layer in the data source.. Args: layerCode (str): A code of the layer. dataSource (ogr.DataSource) A reference to the OGR data source. """ codeLayer = dataSource.GetLayerByName(layerCode) codeLayer.GetFeatureCount(True) for feature in codeLayer: feature.GetGeometryRef() def _open_database(self, dbPath): """Opens a database. Checks if there are geometry_columns and spatial_ref_sys tables in the database, if not it creates and fills those tables. Checks if there are all PU columns in PAR table, if it it creates and fills those columns. Args: dbPath (str): A full path to the database. Raises: dw.puError: When SQLITE database driver is not available or when database connection fails. """ if not QSqlDatabase.isDriverAvailable('QSQLITE'): raise self.dW.puError( self.dW, self, u'SQLITE database driver is not available.', u'Databázový ovladač QSQLITE není dostupný.', u'Databázový ovladač QSQLITE není dostupný.') connectionName = QUuid.createUuid().toString() db = QSqlDatabase.addDatabase('QSQLITE', connectionName) db.setDatabaseName(dbPath) db.open() if not db.open(): raise self.dW.puError(self.dW, self, u'Database connection failed.', u'Nepodařilo se připojit k databázi.', u'Nepodařilo se připojit k databázi.') self.set_text_statusbar.emit(u'Kontroluji tabulky a sloupce...', 0, False) QgsApplication.processEvents() sqlQuery = QSqlQuery(db) sqlDir = QDir(self.pluginDir.path() + u'/data/sql') query = self._read_text_from_file(sqlDir.filePath(u'check_gc_srs.sql')) sqlQuery.exec_(query) QgsApplication.processEvents() checkGcSrsSize = 0 while sqlQuery.next(): checkGcSrsSize += 1 if checkGcSrsSize < 2: queries = self._read_text_from_file( sqlDir.filePath(u'create_fill_gc_srs.sql')).split(';') for query in queries: sqlQuery.exec_(query) QgsApplication.processEvents() query = self._read_text_from_file( sqlDir.filePath(u'check_pu_columns_PAR.sql')) sqlQuery.exec_(query) QgsApplication.processEvents() columns = [] while sqlQuery.next(): record = sqlQuery.record() name = str(record.value('name')) columns.append(name) if not all(column in columns for column in self.dW.allPuColumns): queries = self._read_text_from_file( sqlDir.filePath(u'add_pu_columns_PAR.sql')).split(';') for query in queries: sqlQuery.exec_(query) QgsApplication.processEvents() queries = self._read_text_from_file( sqlDir.filePath(u'create_sobr_spol.sql')).split(';') for query in queries: sqlQuery.exec_(query) db.close() def _create_spatialite_db_file(self, dbPath): """Creates a SpatiaLite database file. Args: dbPath (str): A full path to the database. Returns: dbPath (str): A full path to the SpatiaLite database. """ dbInfo = QFileInfo(dbPath) sdbPath = QDir(dbInfo.absolutePath())\ .filePath(dbInfo.completeBaseName() + '.sdb') sdbInfo = QFileInfo(sdbPath) if not sdbInfo.isFile(): self.set_text_statusbar.emit( u'Importuji data do SpatiaLite databáze...', 0, False) QgsApplication.processEvents() sqliteDriver = ogr.GetDriverByName('SQLite') spatialiteDataSource = sqliteDriver.CreateDataSource( sdbPath, ['SPATIALITE=YES']) sqliteDataSource = ogr.Open(dbPath) for layerCode in ( self.dW.parLayerCode, ) + self.dW.vertexLayerCodes: originalLayer = sqliteDataSource.GetLayerByName(layerCode) copiedLayer = spatialiteDataSource.CopyLayer( originalLayer, layerCode, ['LAUNDER=NO']) sqliteDataSource.Destroy() spatialiteDataSource.Destroy() QgsApplication.processEvents() return sdbPath def _read_text_from_file(self, filePath, maxSize=2000): """Reads a text from the given file. Args: filePath (str): A full path to the file. maxSize (int): Maximum size of read data from the file in bytes. Returns: str: The text from the file. """ file = QFile(filePath) file.open(QFile.ReadOnly | QFile.Text) text = file.readData(maxSize) file.close() return text def _load_vfk_layer(self, dbPath, layerName, layerCode, vfkDriverName): """Loads a layer of the given code from database into the map canvas. Args: dbPath (str): A full path to the database. layerName (str): A name of the layer. layerCode (str): A code of the layer. vfkDriverName (str): A name of the VFK driver. Raises: dw.puError: When layerCode layer is not valid. """ self.set_text_statusbar.emit( u'Přidávám vrstvu {}...'.format(layerCode), 0, False) QgsApplication.processEvents() # SpatiaLite fix - start if not self.dW.fixedSqliteDriver: composedURI = QgsDataSourceURI() composedURI.setDatabase(dbPath) schema = '' table = layerCode geometryColumn = 'GEOMETRY' composedURI.setDataSource(schema, table, geometryColumn) layer = QgsVectorLayer(composedURI.uri(), layerName, 'spatialite') else: blacklistedDriver = ogr.GetDriverByName(vfkDriverName) blacklistedDriver.Deregister() composedURI = dbPath + '|layername=' + layerCode layer = QgsVectorLayer(composedURI, layerName, 'ogr') blacklistedDriver.Register() # SpatiaLite fix - end if layer.isValid(): self._set_scale_for_features_with_no_or_invalid_geometry(layer) self.dW.set_layer_style(layer, layerCode) self._set_layer_form_config(layer) self._set_layer_table_config(layer) QgsMapLayerRegistry.instance().addMapLayer(layer) self._set_layer_snapping(layer) QgsApplication.processEvents() else: raise self.dW.puError(self.dW, self, u'Layer {} is not valid.'.format(layerCode), u'Vrstva {} není platná.'.format(layerCode), u'Vrstva {} není platná.'.format(layerCode)) def _set_scale_for_features_with_no_or_invalid_geometry(self, layer): """Sets basis scale to zero for features with no or invalid geometry. Args: layer (QgsVectorLayer): A reference to the layer. """ expression = QgsExpression("$geometry is null") features = layer.getFeatures(QgsFeatureRequest(expression)) self.dW.set_field_value_for_features(layer, features, self.dW.puBasisScaleColumnName, 0) def _set_layer_form_config(self, layer): """Sets layer form config. Args: layer (QgsVectorLayer): A reference to the layer. """ fields = layer.pendingFields() formConfig = layer.editFormConfig() for i in layer.pendingAllAttributesList(): if fields[i].name() not in self.dW.editablePuColumns: formConfig.setReadOnly(i) formConfig.setWidgetType(i, 'Hidden') def _set_layer_table_config(self, layer): """Sets layer table config. Args: layer (QgsVectorLayer): A reference to the layer. """ fields = layer.pendingFields() tableConfig = layer.attributeTableConfig() tableConfig.update(fields) columns = tableConfig.columns() for column in columns: if column.name not in self.dW.allVisibleColumns: column.hidden = True tableConfig.setColumns(columns) layer.setAttributeTableConfig(tableConfig) def _set_layer_snapping(self, layer): """Sets layer snapping. Args: layer (QgsVectorLayer): A reference to the layer. """ project = QgsProject.instance() project.setTopologicalEditing(True) project.writeEntry('Digitizing', 'SnappingMode', 'advanced') project.writeEntry('Digitizing', 'IntersectionSnapping', Qt.Checked) project.setSnapSettingsForLayer(layer.id(), True, 2, 1, 10, True) def _enable_load_widgets(self, enableBool): """Sets loading widgets enabled or disabled. Sets enabled or disabled following widgets: browseVfkLineEdit browseVfkPushButton loadVfkPushButton Args: enableBool (bool): True to set enabled, False to set disabled. """ self.browseVfkLineEdit.setEnabled(enableBool) self.browseVfkPushButton.setEnabled(enableBool) self.loadVfkPushButton.setEnabled(enableBool)
class QuadStatusBar(QHBoxLayout): positionChanged = pyqtSignal(int, int, int) # x,y,z def __init__(self, parent=None ): QHBoxLayout.__init__(self, parent) self.setContentsMargins(0,4,0,0) self.setSpacing(0) self.timeControlFontSize = 12 def showXYCoordinates(self): self.zLabel.setHidden(True) self.zSpinBox.setHidden(True) def showXYZCoordinates(self): self.zLabel.setHidden(False) self.zSpinBox.setHidden(False) def hideTimeSlider(self,flag): self.timeSlider.setHidden(flag) self.timeEndButton.setHidden(flag) self.timeStartButton.setHidden(flag) def setToolTipTimeButtonsCrop(self,croppingFlag=False): if croppingFlag==True: self.timeStartButton.setToolTip("Set the time coordinate to the beginning of the current crop.") self.timeEndButton.setToolTip("Set the time coordinate to the end of the current crop.") self.timePreviousButton.setToolTip("Set the time coordinate to the previous time frame.") self.timeNextButton.setToolTip("Set the time coordinate to the next time frame.") else: self.timeStartButton.setToolTip("Set the time coordinate to the beginning of the current dataset.") self.timeEndButton.setToolTip("Set the time coordinate to the end of the current dataset.") self.timePreviousButton.setToolTip("Set the time coordinate to the previous time frame.") self.timeNextButton.setToolTip("Set the time coordinate to the next time frame.") def setToolTipTimeSliderCrop(self,croppingFlag=False): if croppingFlag==True: self.timeSlider.setToolTip("Choose the time coordinate of the current crop.") else: self.timeSlider.setToolTip("Choose the time coordinate of the current dataset.") def createQuadViewStatusBar(self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor): self.xLabel, self.xSpinBox = _get_pos_widget('X', xbackgroundColor, xforegroundColor) self.yLabel, self.ySpinBox = _get_pos_widget('Y', ybackgroundColor, yforegroundColor) self.zLabel, self.zSpinBox = _get_pos_widget('Z', zbackgroundColor, zforegroundColor) self.xSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'x') ) self.ySpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'y') ) self.zSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'z') ) self.addWidget(self.xLabel) self.addWidget(self.xSpinBox) self.addWidget(self.yLabel) self.addWidget(self.ySpinBox) self.addWidget(self.zLabel) self.addWidget(self.zSpinBox) self.addSpacing(10) self.busyIndicator = QProgressBar() self.busyIndicator.setMaximumWidth(200) self.busyIndicator.setMaximum(0) self.busyIndicator.setMinimum(0) self.busyIndicator.setVisible(False) self.busyIndicator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.addWidget( self.busyIndicator ) self.setStretchFactor(self.busyIndicator, 1) self.addStretch() self.addSpacing(10) self.positionCheckBox = QCheckBox() self.positionCheckBox.setChecked(False) self.positionCheckBox.setCheckable(True) self.positionCheckBox.setText("Position") self.addWidget(self.positionCheckBox) self.addSpacing(20) self.timeSpinBox = DelayedSpinBox(750) self.timeStartButton = QPushButton("|<") self.addWidget(self.timeStartButton) self.timeStartButton.clicked.connect(self._onTimeStartButtonClicked) self.timePreviousButton = QPushButton("<") self.addWidget(self.timePreviousButton) self.timePreviousButton.clicked.connect(self._onTimePreviousButtonClicked) self.timePreviousButton.setFixedWidth(4*self.timeControlFontSize) self.timeSlider = QSlider(Qt.Horizontal) self.timeSlider.setMinimumWidth(10) self.timeSlider.setMaximumWidth(200) self.setToolTipTimeSliderCrop() self.addWidget(self.timeSlider) self.timeSlider.valueChanged.connect(self._onTimeSliderChanged) self.timeNextButton = QPushButton(">") self.addWidget(self.timeNextButton) self.timeNextButton.clicked.connect(self._onTimeNextButtonClicked) self.timeNextButton.setFixedWidth(4*self.timeControlFontSize) self.timeEndButton = QPushButton(">|") self.timeEndButton.setFixedWidth(4*self.timeControlFontSize) self.timeStartButton.setFixedWidth(4*self.timeControlFontSize) self.setToolTipTimeButtonsCrop() self.addWidget(self.timeEndButton) self.timeEndButton.clicked.connect(self._onTimeEndButtonClicked) self.timeLabel = QLabel(" Time:") self.addWidget(self.timeLabel) timeControlFont = self.timeSpinBox.font() if self.timeControlFontSize > timeControlFont.pointSize(): timeControlFont.setPixelSize(2*self.timeControlFontSize) self.timeStartButton.setFont(timeControlFont) self.timeEndButton.setFont(timeControlFont) self.timeLabel.setFont(timeControlFont) self.timeSpinBox.setFont(timeControlFont) self.addWidget(self.timeSpinBox) self.timeSpinBox.delayedValueChanged.connect(self._onTimeSpinBoxChanged) def _onTimeStartButtonClicked(self): self.timeSpinBox.setValue(self.parent().parent().parent().editor.cropModel.get_roi_t()[0]) def _onTimeEndButtonClicked(self): self.timeSpinBox.setValue(self.parent().parent().parent().editor.cropModel.get_roi_t()[1]) def _onTimePreviousButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value()-1) def _onTimeNextButtonClicked(self): self.timeSpinBox.setValue(self.timeSpinBox.value()+1) def _onTimeSpinBoxChanged(self): editor = self.parent().parent().parent().editor cropModel = editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): if minValueT > self.timeSpinBox.value() or maxValueT < self.timeSpinBox.value(): for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(True) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(False) self.timeSlider.setValue(self.timeSpinBox.value()) else: for imgView in editor.imageViews: imgView._croppingMarkers._shading_item.set_paint_full_frame(False) if minValueT > self.timeSpinBox.value(): self.timeSlider.setValue(minValueT) elif maxValueT < self.timeSpinBox.value(): self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSpinBox.value() and self.timeSpinBox.value() <= maxValueT: self.timeSlider.setValue(self.timeSpinBox.value()) def _onTimeSliderChanged(self): cropModel = self.parent().parent().parent().editor.cropModel minValueT = cropModel.get_roi_t()[0] maxValueT = cropModel.get_roi_t()[1] if cropModel.get_scroll_time_outside_crop(): self.timeSpinBox.setValue(self.timeSlider.value()) else: if minValueT > self.timeSlider.value(): self.timeSpinBox.setValue(minValueT) self.timeSlider.setValue(minValueT) elif self.timeSlider.value() > maxValueT: self.timeSpinBox.setValue(maxValueT) self.timeSlider.setValue(maxValueT) elif minValueT <= self.timeSlider.value() and self.timeSlider.value() <= maxValueT: self.timeSpinBox.setValue(self.timeSlider.value()) def _handlePositionBoxValueChanged(self, axis, value): new_position = [self.xSpinBox.value(), self.ySpinBox.value(), self.zSpinBox.value()] changed_axis = ord(axis) - ord('x') new_position[changed_axis] = value self.positionChanged.emit(*new_position) def updateShape5D(self, shape5D): self.timeSpinBox.setMaximum(shape5D[0]-1) self.xSpinBox.setMaximum(shape5D[1]-1) self.ySpinBox.setMaximum(shape5D[2]-1) self.zSpinBox.setMaximum(shape5D[3]-1) def updateShape5Dcropped(self, shape5DcropMin, shape5Dmax): self.timeSpinBox.setMaximum(shape5Dmax[0]-1) self.xSpinBox.setMaximum(shape5Dmax[1]-1) self.ySpinBox.setMaximum(shape5Dmax[2]-1) self.zSpinBox.setMaximum(shape5Dmax[3]-1) self.timeSlider.setMaximum(shape5Dmax[0]-1) self.timeSpinBox.setValue(shape5DcropMin[0]) self.xSpinBox.setValue(shape5DcropMin[1]) self.ySpinBox.setValue(shape5DcropMin[2]) self.zSpinBox.setValue(shape5DcropMin[3]) self.timeSlider.setValue(shape5DcropMin[0]) def setMouseCoords(self, x, y, z): self.xSpinBox.setValueWithoutSignal(x) self.ySpinBox.setValueWithoutSignal(y) self.zSpinBox.setValueWithoutSignal(z)
class Qt4SysTrayIcon: def __init__(self): self.snapshots = snapshots.Snapshots() self.config = self.snapshots.config if len(sys.argv) > 1: if not self.config.set_current_profile(sys.argv[1]): logger.warning("Failed to change Profile_ID %s" % sys.argv[1], self) self.qapp = qt4tools.create_qapplication(self.config.APP_NAME) import icon self.icon = icon self.qapp.setWindowIcon(icon.BIT_LOGO) self.status_icon = QSystemTrayIcon(icon.BIT_LOGO) #self.status_icon.actionCollection().clear() self.contextMenu = QMenu() self.menuProfileName = self.contextMenu.addAction( _('Profile: "%s"') % self.config.get_profile_name()) qt4tools.set_font_bold(self.menuProfileName) self.contextMenu.addSeparator() self.menuStatusMessage = self.contextMenu.addAction(_('Done')) self.menuProgress = self.contextMenu.addAction('') self.menuProgress.setVisible(False) self.contextMenu.addSeparator() self.startBIT = self.contextMenu.addAction(icon.BIT_LOGO, _('Start BackInTime')) QObject.connect(self.startBIT, SIGNAL('triggered()'), self.onStartBIT) self.status_icon.setContextMenu(self.contextMenu) self.pixmap = icon.BIT_LOGO.pixmap(24) self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.progressBar.setValue(0) self.progressBar.setTextVisible(False) self.progressBar.resize(24, 6) self.progressBar.render(self.pixmap, sourceRegion=QRegion(0, -14, 24, 6), flags=QWidget.RenderFlags( QWidget.DrawChildren)) self.first_error = self.config.is_notify_enabled() self.popup = None self.last_message = None self.timer = QTimer() QObject.connect(self.timer, SIGNAL('timeout()'), self.update_info) self.ppid = os.getppid() def prepare_exit(self): self.timer.stop() if not self.status_icon is None: self.status_icon.hide() self.status_icon = None if not self.popup is None: self.popup.deleteLater() self.popup = None self.qapp.processEvents() def run(self): self.status_icon.show() self.timer.start(500) logger.info("[qt4systrayicon] begin loop", self) self.qapp.exec_() logger.info("[qt4systrayicon] end loop", self) self.prepare_exit() def update_info(self): if not tools.is_process_alive(self.ppid): self.prepare_exit() self.qapp.exit(0) return message = self.snapshots.get_take_snapshot_message() if message is None and self.last_message is None: message = (0, _('Working...')) if not message is None: if message != self.last_message: self.last_message = message self.menuStatusMessage.setText('\n'.join(tools.wrap_line(self.last_message[1],\ size = 80,\ delimiters = '',\ new_line_indicator = '') \ )) self.status_icon.setToolTip(self.last_message[1]) pg = progress.ProgressFile(self.config) if pg.isFileReadable(): pg.load() percent = pg.get_int_value('percent') if percent != self.progressBar.value(): self.progressBar.setValue(percent) self.progressBar.render(self.pixmap, sourceRegion=QRegion(0, -14, 24, 6), flags=QWidget.RenderFlags( QWidget.DrawChildren)) self.status_icon.setIcon(QIcon(self.pixmap)) self.menuProgress.setText(' | '.join(self.getMenuProgress(pg))) self.menuProgress.setVisible(True) else: self.status_icon.setIcon(self.icon.BIT_LOGO) self.menuProgress.setVisible(False) def getMenuProgress(self, pg): d = (('sent', _('Sent:')), \ ('speed', _('Speed:')),\ ('eta', _('ETA:')) ) for key, txt in d: value = pg.get_str_value(key, '') if not value: continue yield txt + ' ' + value def onStartBIT(self): profileID = self.config.get_current_profile() cmd = [ 'backintime-qt4', ] if not profileID == '1': cmd += ['--profile-id', profileID] proc = subprocess.Popen(cmd)
class TabDownloads(QWidget): instance = None def __init__(self, search, parent=None): QWidget.__init__(self, parent) # Load de l'UI PyQt4.uic.loadUi('ui/downloads.ui', self) # Ajout de la progressBar self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.progressBar.hide() self.HLayout = QBoxLayout(QBoxLayout.LeftToRight) self.HLayout.addWidget(self.progress_label) self.HLayout.addWidget(self.progressBar) self.formLayout_3.addRow(self.HLayout) # Vars TabDownloads.instance = self self.downloads = Downloads() self.pos = None self.download_looked = None # Affichage custom #self.downloads_table.setStyleSheet(\ # "QTableView::item{ \ # border-right-style:solid; \ # border-width:0.5; \ # border-color: #9B9B9B; \ # }") # On autorise la creation de menu contextuel self.setContextMenuPolicy(Qt.CustomContextMenu) # Signaux self.customContextMenuRequested.connect(self.contextMenu) self.downloads_table.itemClicked.connect(self.show_info_download) # Init self.load_downloads() # On remove les finis et en erreur si Config.clean_dl_list = 1 if Configuration.clean_dl_list == 1: self.clean_list_Action() ######################################################### # On désactive les boutons qui sont pas encore implantés self.button_stop_all.setEnabled(False) self.button_resume_all.setEnabled(False) ######################################################### def load_downloads(self): import xml.sax parser = xml.sax.make_parser() parser.setContentHandler(AnalyseDownloads(self.add_downloads)) try: for line in open(os.path.expanduser("~") + '/.pyrex/downloads.xml'): parser.feed(line) self.downloads.save() except: pass def add_download(self, download): # Avant de filtrer on écrit le download #self.downloads.append(download) #TODO : pour quand on pourra resume, décommenter la ligne et ramener le save ici if download.state == 4 or download.progress == 0: rows = self.downloads_table.rowCount() self.downloads_table.insertRow(rows) self.downloads_table.setItem(rows, 0, MyQTableWidgetItem(download.file_share.name, download)) self.downloads_table.setItem(rows, 1, QTableWidgetItem(download.get_progress())) self.downloads_table.setItem(rows, 2, QTableWidgetItem(download.state_str)) self.downloads_table.setItem(rows, 3, QTableWidgetItem("0 ko/s")) self.downloads_table.setItem(rows, 5, QTableWidgetItem(download.date.strftime('%d/%m/%y'))) self.downloads.append(download) # TODO : à modifier probablement quand on aura le resume pour les downloads if download.state != 4 and download.progress == 0: # Signaux download.progressModified.connect(self.update_progress) download.stateChanged.connect(self.update_state) download.downloadFinished.connect(self.download_finished) download.speedModified.connect(self.update_speed) # On save self.downloads.save() def add_downloads(self, downloads): for download in downloads: self.add_download(download) def update_progress(self, download): item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0] row = self.downloads_table.row(item) self.downloads_table.item(row, 1).setText(download.get_progress()) # On update la barre de progression si on est en train de regarder un download if self.download_looked == download: self.progressBar.setValue(int(download.progress)) def update_speed(self, download): item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0] row = self.downloads_table.row(item) self.downloads_table.item(row, 3).setText(convert_speed_str(download.speed)) def update_state(self, download): item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0] row = self.downloads_table.row(item) self.downloads_table.item(row, 2).setText(download.state_str) # On save self.downloads.save() def download_finished(self, download): if download.read_bytes == download.file_share.size: item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0] row = self.downloads_table.row(item) self.downloads_table.item(row, 2).setText("Finished!") self.downloads_table.item(row, 3).setText("") # On save self.downloads.save() else: print "Erreur dans le téléchargement" item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0] row = self.downloads_table.row(item) self.downloads_table.item(row, 2).setText("Error : invalid size :(") self.downloads_table.item(row, 3).setText("") # On save self.downloads.save() def contextMenu(self, pos): self.pos = pos menu = QMenu() # Actions forceAction = menu.addAction("Forcer la reprise") continueAction = menu.addAction("Reprise") pauseAction = menu.addAction("Pause") openAction = menu.addAction("Ouvrir") abortAction = menu.addAction("Annuler") supprListeAction = menu.addAction("Supprimer de la liste") supprDiskAction = menu.addAction("Supprimer de la liste et du disque") copyAction = menu.addAction("Copier l'URL") searchAction = menu.addAction("Rechercher des fichiers similaires") # On désactive les actions s'il n'y a pas de downloads if self.downloads == [] or self.downloads_table.currentRow() < 0: forceAction.setEnabled(False) continueAction.setEnabled(False) pauseAction.setEnabled(False) openAction.setEnabled(False) abortAction.setEnabled(False) supprListeAction.setEnabled(False) supprDiskAction.setEnabled(False) copyAction.setEnabled(False) searchAction.setEnabled(False) ######################################################### # On désactive les boutons qui sont pas encore implantés forceAction.setEnabled(False) #continueAction.setEnabled(False) #pauseAction.setEnabled(False) searchAction.setEnabled(False) ######################################################### # Signaux self.connect(forceAction, SIGNAL('triggered()'), self.force_Action) self.connect(continueAction, SIGNAL('triggered()'), self.continue_Action) self.connect(pauseAction, SIGNAL('triggered()'), self.pause_Action) self.connect(openAction, SIGNAL('triggered()'), self.open_Action) self.connect(abortAction, SIGNAL('triggered()'), self.abort_Action) self.connect(supprListeAction, SIGNAL('triggered()'), self.suppr_liste_Action) self.connect(supprDiskAction, SIGNAL('triggered()'), self.suppr_disk_Action) self.connect(copyAction, SIGNAL('triggered()'), self.copy_Action) self.connect(searchAction, SIGNAL('triggered()'), self.search_Action) # On affiche le menu menu.exec_(self.mapToGlobal(pos)) def getDownloads(self): rows = self.downloads_table.selectionModel().selectedRows() return [self.downloads_table.item(row.row(), 0).download for row in rows] def force_Action(self): print "TODO" def continue_Action(self): for download in self.getDownloads(): print "Resuming download" download.resume() self.display_resume_pause() def pause_Action(self): for download in self.getDownloads(): print "Pausing download" download.pause() self.display_resume_pause() def open_Action(self): for download in self.getDownloads(): open_file(download.local_path) def abort_Action(self): for download in self.getDownloads(): download.stop() row = self.downloads_table.currentRow() self.downloads_table.item(row, 2).setText(u"Annulé!") self.downloads_table.item(row, 3).setText("") def remove_download(self, download, erase): download.stop() row = self.downloads_table.currentRow() # On supprime la ligne self.downloads_table.removeRow(row) # On supprime de la liste self.downloads.remove(download) # On save self.downloads.save() if erase: try: os.remove(download.local_path) except OSError: try: shutil.rmtree(download.local_path) except: print "Erreur dans la suppression du fichier" def suppr_liste_Action(self): for download in self.getDownload(): self.remove_download(download, False) def suppr_disk_Action(self): for download in self.getDownloads(): self.remove_download(download, True) def copy_Action(self): pressPaper = QApplication.clipboard() text = '\n'.join([dl.local_path for dl in self.getDownloads()]) pressPaper.setText(text) def search_Action(self): print "TODO" def show_info_download(self): download = self.getDownloads()[0] self.name_label.setText(u"Nom : {}".format(download.file_share.name)) self.path_label.setText(u"Chemin local : {}".format(download.local_path)) self.url_label.setText(u"URL : {}".format(download.file_share.url)) self.size_label.setText(u"Taille : {}".format(download.file_share.str_size)) self.progressBar.show() self.progressBar.setValue(int(download.progress)) self.download_looked = download def clean_list_Action(self): remove_list = [] for download in self.downloads: if download.state == 4 or download.state == 7: # On trouve la ligne item = self.downloads_table.findItems(download.file_share.name, Qt.MatchExactly)[0] row = self.downloads_table.row(item) # On la supprime self.downloads_table.removeRow(row) # On save pour après la boucle for remove_list.append(download) # On supprime de la liste for download in remove_list: self.downloads.remove(download) # On save self.downloads.save() def double_clicked(self, row, col): download = self.getDownloads()[0] if download: open_file(download.local_path) def display_resume_pause(self): downloads = self.getDownloads() pause = False resume = False if downloads: for download in downloads: if download.state == 5: pause = True else: resume = True self.button_pause.setEnabled(resume) self.button_resume.setEnabled(pause) def clicked(self, row, col): self.display_resume_pause() def resizeEvent(self, event): maxSize = self.downloads_table.size().width() # Nom Ficher : 24% self.downloads_table.horizontalHeader().resizeSection(0, maxSize*.24) # Avancement : 22% self.downloads_table.horizontalHeader().resizeSection(1, maxSize*.22) # Etat : 17% self.downloads_table.horizontalHeader().resizeSection(2, maxSize*.17) # Vitesse : 13% self.downloads_table.horizontalHeader().resizeSection(3, maxSize*.13) # Fin : 12% self.downloads_table.horizontalHeader().resizeSection(4, maxSize*.12) event.accept()
class StatusBox(QGroupBox): STATUS_BOX_TEXT = 'Status' BASE_PATH_REQUIRED_MESSAGE_TEXT = 'Fill in the base path to start scanning for files to be renamed.' SCAN_FILES_PROGRESS_TEXT = 'Scanning files' SCAN_FILES_ERROR_CAPTION_TEXT = 'Error scanning files' RULES_ERROR_CAPTION_TEXT = 'Error in rules' NO_FILES_TO_RENAME_MESSAGE_TEXT = 'No files to rename.' RENAME_FILES_PROGRESS_TEXT = 'Renaming files' RENAME_FILES_ERROR_CAPTION_TEXT = 'Error renaming files' NO_FILES_RENAMED_MESSAGE_TEXT = 'No files changed.' READY_TO_RENAME_MESSAGE_TEXT = 'Ready to rename.' RENAME_PROGRESS_TEXT = 'Executing rename' PLANNING_RENAME_ERROR_CAPTION_TEXT = 'Error while planning rename' RENAME_ERROR_CAPTION_TEXT = 'Error while executing rename' RENAME_COMPLETE_MESSAGE_TEXT = 'Rename completed.' READY_MESSAGE_TEXT = 'Ready.' ERROR_COLOR = '#ff0000' _status_label = None _status_progressbar = None def __init__(self, parent): super().__init__(self.STATUS_BOX_TEXT, parent) self._status_label = QLabel(self) self._status_progressbar = QProgressBar(self) self._status_progressbar.setVisible(False) self._status_progressbar.setMinimum(0) layout = QHBoxLayout(self) layout.addWidget(self._status_label) layout.addWidget(self._status_progressbar) @pyqtSlot(BAONStatus) def show_status(self, status): if status.scan_status == BAONStatus.IN_PROGRESS: self._show_progress(status.scan_status_extra, self.SCAN_FILES_PROGRESS_TEXT) elif status.rename_status == BAONStatus.IN_PROGRESS: self._show_progress(status.rename_status_extra, self.RENAME_FILES_PROGRESS_TEXT) elif status.execute_status == BAONStatus.IN_PROGRESS: self._show_progress(status.execute_status_extra, self.RENAME_PROGRESS_TEXT) elif status.scan_status == BAONStatus.ERROR: self._show_error(status.scan_status_extra, self.SCAN_FILES_ERROR_CAPTION_TEXT) elif status.rules_status == BAONStatus.ERROR: self._show_error(status.rules_status_extra, self.RULES_ERROR_CAPTION_TEXT) elif status.rename_status == BAONStatus.ERROR: self._show_error(status.rename_status_extra, self.RENAME_FILES_ERROR_CAPTION_TEXT) elif status.execute_status == BAONStatus.ERROR: if isinstance(status.execute_status_extra, MakeRenamePlanError): self._show_error(status.execute_status_extra, self.PLANNING_RENAME_ERROR_CAPTION_TEXT) else: self._show_error(status.execute_status_extra, self.RENAME_ERROR_CAPTION_TEXT) elif status.scan_status == BAONStatus.NOT_AVAILABLE: self._show_message(self.BASE_PATH_REQUIRED_MESSAGE_TEXT) elif status.rename_status == BAONStatus.NOT_AVAILABLE: self._show_message(self.NO_FILES_TO_RENAME_MESSAGE_TEXT) elif status.execute_status == BAONStatus.NOT_AVAILABLE: self._show_message(self.NO_FILES_RENAMED_MESSAGE_TEXT) elif status.execute_status == BAONStatus.WAITING_FOR_USER: self._show_message(self.READY_TO_RENAME_MESSAGE_TEXT) elif status.execute_status == BAONStatus.AVAILABLE: self._show_message(self.RENAME_COMPLETE_MESSAGE_TEXT) else: self._show_message(self.READY_MESSAGE_TEXT) def _show_message(self, format_string, *args, **kwargs): self._show_raw_message(format_string.format(*args, **kwargs)) def _show_progress(self, progress, text): self._show_raw_message(text, progress=progress) def _show_error(self, error, caption=None): text = str(error) if caption is not None: text = caption + ': ' + text self._show_raw_message(text, is_error=True) def _show_raw_message(self, text, is_error=False, progress=None): self._status_label.setText(text) self._status_label.setStyleSheet("QLabel {{ color: {0} }}".format(self.ERROR_COLOR) if is_error else "") self._status_progressbar.setVisible(progress is not None) if progress is not None: if progress.is_indeterminate(): self._status_progressbar.setMaximum(0) else: self._status_progressbar.setMaximum(progress.total) self._status_progressbar.setValue(progress.done)
class Window(QMainWindow): def __init__(self,parent = None): QMainWindow.__init__(self,parent) self.resize(1024,768) self.setWindowTitle("Sabel") self.setWindowIcon(Icons.sabel) self.centralwidget = QWidget(self) self.horizontalLayout = QHBoxLayout(self.centralwidget) self.horizontalLayout.setMargin(0) self.cmdList = config.cmds() self.paramList = config.params() '''A.Editor TabWidget''' '''This parent is for findbar and vertical layout''' self.editorLayoutWidget = QWidget(self) self.editorLayoutWidget.setMinimumWidth(800) self.tabWidget = EditorTab(self) self.editorLayout = QVBoxLayout(self.editorLayoutWidget) self.editorLayout.setMargin(0) self.editorLayout.addWidget(self.tabWidget) "0.Style Layout" self.styleLayoutWidget = QFrame() self.styleLayoutWidget.setFrameShape(QFrame.StyledPanel) self.styleLayout = QHBoxLayout(self.styleLayoutWidget) self.styleTest = QPushButton(self.styleLayoutWidget) self.styleTest.setText("Change Styles") self.styleTest.clicked.connect(self.changeStyleSheet) self.popWidget = Popup(self.styleLayoutWidget) self.styleLayout.addWidget(self.styleTest) self.styleLayout.addWidget(self.popWidget) self.styleLayout.setMargin(0) self.editorLayout.addWidget(self.styleLayoutWidget) self.styleLayoutWidget.hide() "1.Find Layout" self.findLayoutWidget = QFrame() self.findLayoutWidget.setFrameShape(QFrame.StyledPanel) self.findLayout = QHBoxLayout(self.findLayoutWidget) self.lineEdit = QLineEdit(self.findLayoutWidget) self.lineEdit_2 = QLineEdit(self.findLayoutWidget) self.findClose = QPushButton(self.findLayoutWidget) self.findClose.setIcon(Icons.close_view) self.findClose.setFlat(True) self.findClose.clicked.connect(self.findBarShow) self.find = QPushButton(self.findLayoutWidget) self.find.setText("Find") self.find.clicked.connect(self.findCurrentText) self.replacefind = QPushButton(self.findLayoutWidget) self.replacefind.setText("Replace/Find") self.replacefind.clicked.connect(self.replaceFindText) self.replace = QPushButton(self.findLayoutWidget) self.replace.setText("Replace") self.replace.clicked.connect(self.replaceCurrentText) self.replaceAll = QPushButton(self.findLayoutWidget) self.replaceAll.setText("Replace All") self.replaceAll.clicked.connect(self.replaceAllText) self.caseSensitive = QToolButton(self.findLayoutWidget) self.caseSensitive.setIcon(Icons.font) self.caseSensitive.setCheckable(True) self.wholeWord = QToolButton(self.findLayoutWidget) self.wholeWord.setText("ww") self.wholeWord.setCheckable(True) self.regex = QToolButton(self.findLayoutWidget) self.regex.setText("re") self.regex.setCheckable(True) self.backward = QToolButton(self.findLayoutWidget) self.backward.setText("bk") self.backward.setCheckable(True) self.backward.setDisabled(True) self.findLayout.addWidget(self.findClose) self.findLayout.addWidget(self.find) self.findLayout.addWidget(self.lineEdit) self.findLayout.addWidget(self.lineEdit_2) self.findLayout.addWidget(self.caseSensitive) self.findLayout.addWidget(self.wholeWord) self.findLayout.addWidget(self.regex) self.findLayout.addWidget(self.backward) self.findLayout.addWidget(self.replacefind) self.findLayout.addWidget(self.replace) self.findLayout.addWidget(self.replaceAll) self.findLayout.setMargin(0) self.findLayoutWidget.setMaximumHeight(25) self.editorLayout.addWidget(self.findLayoutWidget) self.findLayoutWidget.hide() '''B.Designer''' '''This parent is for widgetsbar and design layout''' self.designerLayoutWidget = QWidget(self) self.designerLayoutWidget.setMinimumWidth(800) self.designerWidget = Screen(self) self.designerLayoutWidget.hide() self.designerLayout = QVBoxLayout(self.designerLayoutWidget) self.designerLayout.setMargin(0) self.designerLayout.addWidget(self.designerWidget) '''C.Level Editor''' '''This parent is for spritesheets and level layout''' self.levelLayoutWidget = QWidget(self) self.levelLayoutWidget.setMinimumWidth(800) self.levelWidget = Level(self) self.levelLayoutWidget.hide() self.levelLayout = QVBoxLayout(self.levelLayoutWidget) self.levelLayout.setMargin(0) self.levelLayout.addWidget(self.levelWidget) '''D.Explorer TabWidget''' self.explorerTabWidget = TreeTab(self) #self.explorerTabWidget.setMaximumWidth(200) '''1.Project Tree''' self.tab_5 = QWidget() #self.tab_5.setMaximumWidth(200) self.VerticalLayout_2 = QVBoxLayout(self.tab_5)#QHBoxLayout(self.tab_5) self.VerticalLayout_2.setMargin(0) self.treeWidget = ProjectTree(self.tab_5) #self.treeWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) #self.treeWidget.horizontalScrollBar().show() self.VerticalLayout_2.addWidget(self.treeWidget) '''2.Outline Tree''' self.tab_2 = QWidget() #self.tab_2.setMaximumWidth(200) self.VerticalLayout_3 = QVBoxLayout(self.tab_2) self.VerticalLayout_3.setMargin(0) self.outlineWidget = OutlineTree(self.tab_2) self.outlineWidget.itemDoubleClicked.connect(self.gotoLine) self.VerticalLayout_3.addWidget(self.outlineWidget) '''E.Output TabWidget''' self.outputTabWidget = OutputTab(self) self.tabWidget.currentChanged.connect(self.fileChanged) self.explorerTabWidget.currentChanged.connect(self.closeExplorer) self.outputTabWidget.currentChanged.connect(self.closeConsole) self.tabWidget.setTabsClosable(True) self.tabWidget.setTabShape(0) '''1.Output layout''' #must check self.tab_6 = QWidget() self.horizontalLayout_2 = QVBoxLayout(self.tab_6) self.horizontalLayout_2.setMargin(0) self.textEdit = QTextEdit() self.inputLayout = QHBoxLayout() self.inputLayout.setMargin(0) self.fileButton = QPushButton() self.fileButton.setText("File") self.fileButton.clicked.connect(self.getFile) self.runButton = QPushButton() self.runButton.setFlat(True) self.runButton.setIcon(Icons.go) self.combo = QComboBox() self.combo.setFixedWidth(100) self.comboAdd = QPushButton() self.comboAdd.setIcon(Icons.add) self.comboAdd.setFlat(True) self.comboAdd.clicked.connect(self.addCmd) self.comboDel = QPushButton() self.comboDel.setIcon(Icons.close_view) self.comboDel.setFlat(True) self.comboDel.clicked.connect(self.delCmd) self.combo2 = QComboBox() self.combo2.setFixedWidth(500) self.combo2Add = QPushButton() self.combo2Add.setIcon(Icons.add) self.combo2Add.setFlat(True) self.combo2Add.clicked.connect(self.addParam) self.combo2Del = QPushButton() self.combo2Del.setIcon(Icons.close_view) self.combo2Del.setFlat(True) self.combo2Del.clicked.connect(self.delParam) if(self.checkHasValue(self.cmdList)): for cmd in self.cmdList: self.combo.addItem(cmd) else: self.cmdList = [] if(self.checkHasValue(self.paramList)): for param in self.paramList: self.combo2.addItem(param) else: self.paramList = [] self.horizontalLayout_2.addWidget(self.textEdit) self.inputLayout.addWidget(QLabel("<b>Command:</b>")) self.inputLayout.addWidget(self.combo) self.inputLayout.addWidget(self.comboAdd) self.inputLayout.addWidget(self.comboDel) self.inputLayout.addWidget(QLabel("<b>Parameters:</b>")) self.inputLayout.addWidget(self.combo2) self.inputLayout.addWidget(self.combo2Add) self.inputLayout.addWidget(self.combo2Del) self.inputLayout.addWidget(self.fileButton) self.inputLayout.addWidget(self.runButton) self.horizontalLayout_2.addLayout(self.inputLayout) '''2.Error Layout''' self.tab_7 = QWidget() self.horizontalLayout_4 = QHBoxLayout(self.tab_7) self.horizontalLayout_4.setMargin(0) self.errorTree = ErrorTree(self.tab_7) self.errorTree.itemDoubleClicked.connect(self.errorLine) self.horizontalLayout_4.addWidget(self.errorTree) '''TabWidgets tabs''' #self.designerWidget.addTab(QWidget(self),"") #self.designerWidget.setTabIcon(0,Icons.close_view) #self.levelWidget.addTab(QWidget(self),"") #self.levelWidget.setTabIcon(0,Icons.close_view) self.explorerTabWidget.addTab(self.tab_5,"Projects") self.explorerTabWidget.addTab(self.tab_2,"Outline") self.explorerTabWidget.addTab(QWidget(self),"") self.explorerTabWidget.setTabIcon(0,Icons.cprj) self.explorerTabWidget.setTabIcon(1,Icons.envvar) self.explorerTabWidget.setTabIcon(2,Icons.close_view) self.outputTabWidget.addTab(self.tab_7,"Error") self.outputTabWidget.addTab(self.tab_6,"Output") self.outputTabWidget.addTab(QWidget(self),"") self.outputTabWidget.setTabIcon(0,Icons.error) self.outputTabWidget.setTabIcon(1,Icons.console_view) self.outputTabWidget.setTabIcon(2,Icons.close_view) '''Splitters''' self.split1 = QSplitter(Qt.Horizontal) self.split1.addWidget(self.explorerTabWidget) self.split1.addWidget(self.editorLayoutWidget) self.split1.addWidget(self.designerLayoutWidget) self.split1.addWidget(self.levelLayoutWidget) #self.split1.addWidget(self.tab_5) self.split2 = QSplitter(Qt.Vertical) self.split2.addWidget(self.split1) self.split2.addWidget(self.outputTabWidget) self.horizontalLayout.addWidget(self.split2) '''Status Bar''' self.statusbar = QStatusBar(self) self.aboutButton = QPushButton(self) self.aboutButton.setFlat(True) self.aboutButton.setIcon(Icons.anchor) self.aboutButton.clicked.connect(self.about) self.expButton = QPushButton(self) self.expButton.setFlat(True) self.expButton.setIcon(Icons.prj) self.expButton.clicked.connect(self.exp) self.cmdButton = QPushButton(self) self.cmdButton.setFlat(True) self.cmdButton.setIcon(Icons.console_view) self.cmdButton.clicked.connect(self.cmd) self.cmdButton.setShortcut('Ctrl+D') self.imgButton = QPushButton(self) self.imgButton.setFlat(True) self.imgButton.setIcon(Icons.color_palette) self.imgButton.clicked.connect(self.design) self.imgButton.setShortcut('Ctrl+I') self.findButton = QPushButton(self) self.findButton.setFlat(True) self.findButton.setIcon(Icons.find) self.findButton.setShortcut("Ctrl+F") self.findButton.clicked.connect(self.findBarShow) ''' self.zoominButton = QPushButton(self) self.zoominButton.setFlat(True) self.zoominButton.setIcon(Icons.zoomplus) self.zoominButton.clicked.connect(self.zoomin) self.zoomoutButton = QPushButton(self) self.zoomoutButton.setFlat(True) self.zoomoutButton.setIcon(Icons.zoomminus) self.zoomoutButton.clicked.connect(self.zoomout) ''' '''Status Text,Line Text, Progress Bar and Stop Button''' self.statusText = QLabel("Writable") #self.statusText.setAlignment(Qt.AlignCenter) self.statusText.setFixedWidth(200) self.lineText = QLabel("") self.lineText.setFixedWidth(50) self.progressbar = QProgressBar() self.progressbar.setMinimum(0) self.progressbar.setMaximum(100) self.stopButton = QPushButton(self) self.stopButton.setFlat(True) self.stopButton.setIcon(Icons.stop) self.stopButton.clicked.connect(self.forceStop) self.progressbar.hide() self.stopButton.hide() self.temp = False self.progress = False self.counter = 0 '''Adding all widgets to Status Bar''' self.statusbar.addWidget(self.aboutButton) self.statusbar.addWidget(self.expButton) self.statusbar.addWidget(self.cmdButton) self.statusbar.addWidget(self.imgButton) self.statusbar.addWidget(self.findButton) #self.statusbar.addWidget(QWidget(self)) #self.statusbar.addWidget(self.zoominButton) #self.statusbar.addWidget(self.zoomoutButton) self.statusbar.addWidget(self.statusText) self.statusbar.addWidget(self.lineText) self.statusbar.addWidget(self.progressbar) self.statusbar.addWidget(self.stopButton) #self.statusbar.setFixedHeight(18) ''''Initializing Coloring Style''' self.initEditorStyle() self.initStyleSheet() '''Adding Cental Widget and Status Bar''' self.setCentralWidget(self.centralwidget) self.setStatusBar(self.statusbar) self.textEdit.setReadOnly(True) def initStyleSheet(self): import stylesheet self.setStyleSheet(stylesheet.mainstyl) self.tabWidget.tabBar().setStyleSheet(stylesheet.stletabb) self.explorerTabWidget.tabBar().setStyleSheet(stylesheet.stletabb) self.outputTabWidget.tabBar().setStyleSheet(stylesheet.stletabb) self.popWidget.setStyleSheet(stylesheet.popbg) self.popWidget.hide() ''' This is for changing the palette/window colors to Theme ''' def initEditorStyle(self): pass #editStyle = config.readStyle() #print editStyle #pal = QPalette(self.explorerTabWidget.palette()) #print pal.color(QPalette.Base).name() #print pal.color(QPalette.Window).name() #pal.setColor(QPalette.Base,self.colorStyle.paper) #pal.setColor(QPalette.Text,self.colorStyle.color) #self.explorerTabWidget.setPalette(pal) #self.outputTabWidget.setPalette(pal) ''' This is only for testing dont know if it works for builds ''' def changeStyleSheet(self): ''' Dynamically load the changed stylesheet.py and load the modules and change the style at runtime saves countless deploys ''' import imp foo = imp.load_source('stletabb', workDir+"/stylesheet.py") #print foo.stletabb #self.setStyleSheet(stylesheet.mainstyl) self.tabWidget.tabBar().setStyleSheet(foo.stletabb) self.popWidget.setStyleSheet(foo.popbg) if(self.popWidget.isHidden()): self.popWidget.showPopup() def build_project(self): #current_file = self.files[self.tabWidget.currentIndex()] prj = self.treeWidget.getProject() if(prj != None): self.treeWidget.build(prj) def run_project(self): #current_file = self.files[self.tabWidget.currentIndex()] prj = self.treeWidget.getProject()#current_file) if(prj != None): self.treeWidget.run(prj) def forceStop(self): self.ant.kill() self.progressStop() def kill(self): self.deleteLater() #-----------------------------------------------------------------------------------# # Menu Actions Functions # #-----------------------------------------------------------------------------------# def run(self): if(config.mode() == 0): self.sq.run() elif(config.mode() == 1): self.adb.run() elif(config.mode() == 2): self.ios.run() elif(config.mode() == 3): self.c.run() def setMode(self, action): if(action.text() == "Squ"): config.setMode(0) self.toolBar.action_Build.setEnabled(False) self.toolBar.action_Run.setEnabled(False) elif(action.text() == "Emo"): config.setMode(1) self.toolBar.action_Build.setEnabled(True) self.toolBar.action_Run.setEnabled(True) elif(action.text() == "Android"): config.setMode(2) self.toolBar.action_Build.setEnabled(True) self.toolBar.action_Run.setEnabled(True) elif(action.text() == "ios"): config.setMode(3) self.toolBar.action_Build.setEnabled(False) self.toolBar.action_Run.setEnabled(False) def openCommand(self): text, ok = QInputDialog.getText(self, 'Run Command', 'Command:') cmd = str(text) if ok and cmd != "": import subprocess subprocess.Popen(cmd) def about(self): form = DialogAbout(self) def todo(self): form = DialogTodo(self) form.show() def help(self): QMessageBox.about(self,"Help","This is about all The Help that i can Give you now") def full(self): if not self.isFull: self.setWindowState(Qt.WindowFullScreen) self.isFull = True else: self.setWindowState(Qt.WindowMaximized) self.isFull = False def android(self): form = DialogAndroid(self) form.show() def antt(self): form = DialogAnt(self) form.show() def squirrel(self): form = DialogSquirrel(self) form.show() def findBarShow(self): if(self.findLayoutWidget.isHidden()): self.findLayoutWidget.show() else: self.findLayoutWidget.hide() def exp(self): if(self.explorerTabWidget.isHidden()): self.explorerTabWidget.show() else: self.explorerTabWidget.hide() def cmd(self): if(self.outputTabWidget.isHidden()): self.outputTabWidget.show() else: self.outputTabWidget.hide() def editor(self): if(self.editorLayoutWidget.isHidden()): self.editorLayoutWidget.show() self.levelLayoutWidget.hide() self.designerLayoutWidget.hide() def design(self): if(self.designerLayoutWidget.isHidden()): self.designerLayoutWidget.show() self.editorLayoutWidget.hide() self.levelLayoutWidget.hide() else: self.designerLayoutWidget.hide() self.editorLayoutWidget.show() def level(self): if(self.levelLayoutWidget.isHidden()): self.levelLayoutWidget.show() self.editorLayoutWidget.hide() self.designerLayoutWidget.hide() else: self.levelLayoutWidget.hide() self.editorLayoutWidget.show() def closeDesigner(self,no): pass ''' if(no == self.tiler.closeIndex()): if(self.tiler.isHidden()): self.tiler.show() else: self.tiler.setCurrentIndex(1) self.tiler.hide() ''' '''The current Changed idx of outputTabWidget is passed to this a param''' def closeConsole(self,no = 2): if(no == 2): if(self.outputTabWidget.isHidden()): self.outputTabWidget.show() else: self.outputTabWidget.setCurrentIndex(1) self.outputTabWidget.hide() def popOutput(self): if(self.outputTabWidget.isHidden()): self.outputTabWidget.show() self.outputTabWidget.setCurrentIndex(1) def popError(self): if(self.outputTabWidget.isHidden()): self.outputTabWidget.show() self.outputTabWidget.setCurrentIndex(0) '''The current Changed idx of explorerTabWidget is passed to this a param''' def closeExplorer(self,no = 2): if(no == 2): if(self.explorerTabWidget.isHidden()): self.explorerTabWidget.show() else: self.explorerTabWidget.setCurrentIndex(0) self.explorerTabWidget.hide() elif(no == 1): self.fileChanged(no) ''' This is to refresh the outline widget''' def fileChanged(self,no): if(self.explorerTabWidget.currentIndex() == 1): edt = self.tabWidget.widget(self.tabWidget.currentIndex()) source = edt.text() self.outlineWidget.parseText(source) def statusSaving(self): self.statusText.setText("Saving") def statusParsing(self): self.statusText.setText("Parsing") def statusWriting(self): self.statusText.setText("Writable") def statusRunning(self): self.statusText.setText("Running") def statusStopping(self): self.statusText.setText("Stopping") def statusCommand(self): self.statusText.setText("Command") def statusBuilding(self): self.statusText.setText("Building") def statusInstalling(self): self.statusText.setText("Installing") def statusCleaning(self): self.statusText.setText("Cleaning") def statusCreating(self): self.statusText.setText("Creating") def progressStart(self): self.progress == True self.temp == True if(self.progressbar.isHidden()): self.progressbar.show() if(self.stopButton.isHidden()): self.stopButton.show() self.progressbar.setValue(1) def progressStop(self): self.progress == False self.temp == False self.progressbar.setValue(100) if not(self.progressbar.isHidden()): self.progressbar.hide() if not(self.stopButton.isHidden()): self.stopButton.hide() def progressUpdate(self): if(self.progress): if(self.temp): self.counter += 1 self.progressbar.setValue(self.counter) if(self.counter == 100): self.temp = False else: self.counter -= 1 self.progressbar.setValue(self.counter) if(self.counter == 0): self.temp = True #-----------------------------------------------------------------------------------# # Editor Functions # #-----------------------------------------------------------------------------------# '''Search and Replace Functions''' def findCurrentText(self): edt = self.tabWidget.widget(self.tabWidget.currentIndex()) edt.findText(self.lineEdit.text(),self.regex.isChecked(),self.caseSensitive.isChecked(),self.wholeWord.isChecked(),self.backward.isChecked()) def replaceCurrentText(self): edt = self.tabWidget.widget(self.tabWidget.currentIndex()) edt.replaceText(self.lineEdit_2.text()) def replaceFindText(self): edt = self.tabWidget.widget(self.tabWidget.currentIndex()) edt.replaceText(self.lineEdit_2.text()) self.findCurrentText() def replaceAllText(self): edt = self.tabWidget.widget(self.tabWidget.currentIndex()) while(edt.findText(self.lineEdit.text(),self.regex.isChecked(),self.caseSensitive.isChecked(),self.wholeWord.isChecked(),self.backward.isChecked())): edt.replaceText(self.lineEdit_2.text()) def errorLine(self,error): index = self.tabWidget.currentIndex() edt = self.tabWidget.widget(index) '''To prevent File item double clicking''' if(error.isFile() == False): edt.setLine(error.line) '''Font Functions''' def zoomin(self): pass #for i in range(len(self.files)): # self.tabWidget.widget(i).zoomin() def zoomout(self): pass #for i in range(len(self.files)): # self.tabWidget.widget(i).zoomout() ''' Must implement Lexer ''' def setLexer(self, action): pass #print action.text() def setApi(self, action): #print action.text() for i in range(len(self.files)): #not QString self.tabWidget.widget(i).setApi(str(action.text())) def setFont(self,font): config.setFontName(str(font.family())) for i in range(len(self.files)): self.tabWidget.widget(i).setNewFont(font) def setFontSize(self,idx): fontSize = idx+1 config.setFontSize(fontSize) for i in range(len(self.files)): self.tabWidget.widget(i).setFontSize() def gotoLine(self,item): edt = self.tabWidget.widget(self.tabWidget.currentIndex()) edt.setLine(item.line) def updateLine(self,no,col): self.lineText.setText(str(no)+" : "+str(col)) def setMargin(self): mar = config.margin() if(mar == 0): config.setMargin(1) for i in range(len(self.files)): self.tabWidget.widget(i).setMargin(1) else: config.setMargin(0) for i in range(len(self.files)): self.tabWidget.widget(i).setMargin(0) ''' Toggle ''' def setIndent(self): indent = config.indent() if(indent == 0): config.setIndent(1) for i in range(len(self.files)): self.tabWidget.widget(i).setIndent(1) else: config.setIndent(0) for i in range(len(self.files)): self.tabWidget.widget(i).setIndent(0) ''' Toggle ''' def setWhiteSpace(self): white = config.whiteSpace() if(white == 0): config.setWhiteSpace(1) for i in range(len(self.files)): self.tabWidget.widget(i).setWhitespaceVisibility(True) else: config.setWhiteSpace(0) for i in range(len(self.files)): self.tabWidget.widget(i).setWhitespaceVisibility(False) ''' Toggle ''' def setEndLine(self): for i in range(len(self.files)): edt = self.tabWidget.widget(i) edt.setEolVisibility(not edt.eolVisibility()) def setEncoding(self, action): if(action.text() == "Ascii"): config.setAscii() for i in range(len(self.files)): self.tabWidget.widget(i).setUtf8(False) elif(action.text() == "Unicode"): config.setUnicode() for i in range(len(self.files)): self.tabWidget.widget(i).setUtf8(True) def setThreshold(self,val): config.setThresh(val) for i in range(len(self.files)): #print i self.tabWidget.widget(i).setThreshold(val) def setTabWidth(self,val): config.setTabWidth(val) for i in range(len(self.files)): #print i self.tabWidget.widget(i).setTabWidth(val) '''style Functions''' #-----------------------------------------------------------------------------------# # Command Functions # #-----------------------------------------------------------------------------------# def getFile(self): self.browsedialog = DialogBrowse(self) self.browsedialog.tree.itemDoubleClicked.connect(self.getName) self.browsedialog.show() def getName(self,item): if(item.isFile()): self.browsedialog.accept() fname = item.getPath() if not (fname == ""): index = self.combo2.currentIndex() text = str(self.combo2.itemText(index))+" "+fname self.combo2.setItemText(index,text) self.paramList.pop(index) self.paramList.insert(index,text) config.setParam(self.paramList) def addCmd(self,index): text, ok = QInputDialog.getText(self, 'Add Command', 'Command:') if(ok): if(str(text) != ''): cmd = str(text).upper() self.cmdList.append(cmd) #print self.cmdList self.combo.addItem(cmd) config.setCmd(self.cmdList) config.setParam(self.paramList) def delCmd(self): index = self.combo.currentIndex() self.combo.removeItem(index) self.cmdList.pop(index) #print self.cmdList config.setCmd(self.cmdList) def addParam(self,index): text, ok = QInputDialog.getText(self, 'Add Parameters', 'Params:') if(ok): if(str(text) != ''): param = str(text) self.paramList.append(param) self.combo2.addItem(param) config.setParam(self.paramList) def delParam(self): index = self.combo2.currentIndex() self.combo2.removeItem(index) self.paramList.pop(index) config.setParam(self.paramList) def checkHasValue(self,list): if(list != None and len(list) != 0): return True else: return False
def run(self): """Run method that performs all the real work""" # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: gradle_command = self.get_gradle_dir() dc_directory = self.dlg.lineEdit.text() print dc_directory if dc_directory == '': self.iface.messageBar().pushMessage("Error", "Please provide the directory of the Digital Connector", level=QgsMessageBar.CRITICAL) else: dc_recipe = self.track_recipe_choice() to_save = self.select_output_name() # Update DC and QGIS repo if self.dlg.checkBox_2.isChecked(): git_path = None if platform.system() == 'Windows': # Look in both Program Files and Program Files x86 for i in os.listdir('C:\\Program Files'): if 'Git' in i: git_path = 'C:\\Program Files\\' + i + '\\bin' # No single quotes allowed in the string on Windows... output = sp.call('{0}\\git pull'.format(git_path), cwd=dc_directory) else: pass for j in os.listdir('C:\\Program Files (x86)'): if 'Git' in j: git_path = 'C:\\Program Files (x86)\\' + j + '\\bin' output = sp.call('{0}\\git pull'.format(git_path), cwd=dc_directory) else: pass # If all fails ask user if git_path == None: git_path = QFileDialog.getExistingDirectory( self.dlg, "Select git path", expanduser("~"), QFileDialog.ShowDirsOnly ) output = sp.call('{0}\\git pull'.format(git_path), cwd=dc_directory) # git pull for Mac OSX elif platform.system() == 'Darwin': for i in os.listdir('/usr/local/Cellar/'): if 'git' in i: git_path = '/usr/local/Cellar/' + i + '/' + os.listdir('/usr/local/Cellar/'+ i)[0] + \ '/' + 'bin/git' args = ['{0} pull'.format(git_path)] output = sp.Popen(args, stdout=sp.PIPE, cwd=dc_directory, shell=True) else: pass if git_path == None: git_path = QFileDialog.getExistingDirectory( self.dlg, "Select git path", expanduser("~"), QFileDialog.ShowDirsOnly ) args = ['{0} pull'.format(git_path)] output = sp.Popen(args, stdout=sp.PIPE, cwd=dc_directory, shell=True) else: print 'currently the plugin only supports Mac and Windows' # check if the path corresponds to the examples folder or not. # This is necessary due to the absolute paths of subprocess chars = set("\/") if any((c in chars) for c in dc_recipe): pass else: dc_recipe = '{0}/src/main/resources/executions/examples/{1}'.format(dc_directory,dc_recipe,to_save) # Check for -Pclear=True if self.dlg.checkBox.isChecked(): p_clear = 'true' else: p_clear= 'false' # TODO need to add more error messages if not to_save: self.iface.messageBar().pushMessage("Error", "Please choose a name for the output file", level=QgsMessageBar.CRITICAL) else: if platform.system() == 'Windows': if not gradle_command in os.environ['PATH']: os.environ['PATH'] += ';' + gradle_command else: pass # No single quotes allowed in the string on Windows... output = sp.call('{0} runExport -Precipe="{2}" -Poutput="{3}" -Pclear="{4}"'.format(gradle_command + '\\gradle.bat', dc_directory,dc_recipe,to_save, p_clear), cwd=dc_directory) # Adding the resulting layer in the QGIS Layers Panel vlayer = QgsVectorLayer(to_save,to_save.split("/")[-1],"ogr") QgsMapLayerRegistry.instance().addMapLayer(vlayer) else: args = ["{0} runExport -Precipe='{2}' -Poutput='{3}' -Pclear='{4}'".format(gradle_command,dc_directory, dc_recipe,to_save, p_clear)] output = sp.Popen(args,stdout=sp.PIPE, cwd=dc_directory, shell=True) for log in iter(output.stdout.readline, b''): sys.stdout.write(str(log) + '\n') progressbar = QProgressBar() progressbar.setMinimum(0) progressbar.setMaximum(0) progressbar.setValue(0) progressbar.setWindowTitle("Running gradle task...") progressbar.show() # Adding the resulting layer in the QGIS Layers Panel vlayer = QgsVectorLayer(to_save,to_save.split("/")[-1],"ogr") QgsMapLayerRegistry.instance().addMapLayer(vlayer)
class CatalogDialogTool(QObject): """ Tool for managing the search and export functionality """ def __init__(self, iface, dialog_ui, bbox_tool): """ Constructor for the dialog tool :param iface: The QGIS Interface :param dialog_ui: The dialog GUI :param bbox_tool The bounding box tool :return: dialog tool """ QObject.__init__(self, None) self.iface = iface self.dialog_ui = dialog_ui self.bbox_tool = bbox_tool self.progress_bar = None self.progress_message_bar = None self.progress_message_bar_widget = None self.search_thread_pool = QThreadPool() self.search_lock = Lock() self.export_thread_pool = QThreadPool() self.export_lock = Lock() self.query = None self.previous_credentials = None self.export_file = None self.footprint_layer = None self.filters = CatalogFilters(self.dialog_ui) self.dialog_ui.aoi_button.clicked.connect(self.aoi_button_clicked) self.dialog_ui.reset_button.clicked.connect(self.reset_button_clicked) self.dialog_ui.export_button.clicked.connect(self.export_button_clicked) self.bbox_tool.released.connect(self.search) self.model = None def init_progress_bar(self, progress_max): """ Sets up the progress bar for search functionality :return: None """ if not self.progress_message_bar: self.progress_message_bar = self.iface.messageBar().createMessage("Querying for data") self.progress_bar = QProgressBar() self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(progress_max) self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignCenter) self.progress_message_bar.layout().addWidget(self.progress_bar) self.progress_message_bar_widget = self.iface.messageBar().pushWidget(self.progress_message_bar, self.iface.messageBar().INFO) def init_layers(self): """ Sets up the layers for rendering the items :return: None """ if self.footprint_layer: QgsMapLayerRegistry.instance().removeMapLayer(self.footprint_layer.id()) self.footprint_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "Catalog Footprints", "memory") self.footprint_layer.setCrs(QgsCoordinateReferenceSystem(4326), True) self.footprint_layer.dataProvider().addAttributes(CatalogAcquisitionFeature.get_fields()) QgsMapLayerRegistry.instance().addMapLayer(self.footprint_layer) def clear_widgets(self): """ Clears the progress bar :return: None """ self.progress_bar = None self.progress_message_bar = None if self.progress_message_bar_widget: self.iface.messageBar().popWidget(self.progress_message_bar_widget) self.progress_message_bar_widget = None def is_searching(self): """ Check to see if the system is still searching (checks if there's work in the search thread pool) :return: True if searching; False otherwise """ return self.get_search_active_thread_count() > 0 def is_exporting(self): """ Check to see if the system is still exporting (checks if there's work in the export thread pool) :return: True if searching; False otherwise """ return self.get_export_active_thread_count() > 0 def get_search_active_thread_count(self): """ Gets the number of active threads in the search thread pool :return: """ with self.search_lock: return self.search_thread_pool.activeThreadCount() def get_export_active_thread_count(self): """ Gets the number of active threads in the export thread pool :return: """ with self.export_lock: return self.export_thread_pool.activeThreadCount() def aoi_button_clicked(self): """ Validates and runs the search if validation successful :return: None """ # can't run search during export if self.is_exporting(): self.iface.messageBar().pushMessage("Error", "Cannot run search while export is running.", level=QgsMessageBar.CRITICAL) # can't run multiple search elif self.is_searching(): self.iface.messageBar().pushMessage("Error", "Cannot run a new search while a search is running.", level=QgsMessageBar.CRITICAL) else: self.bbox_tool.reset() self.iface.mapCanvas().setMapTool(self.bbox_tool) def reset_button_clicked(self): """ Resets filters. :return: None """ self.reset() def export_button_clicked(self): """ Validates and runs the export if validation successful :return: None """ # can't run export during search if self.is_searching(): self.iface.messageBar().pushMessage("Error", "Cannot run export while search is running.", level=QgsMessageBar.CRITICAL) # can't run multiple exports elif self.is_exporting(): self.iface.messageBar().pushMessage("Error", "Cannot run a new export while a export is running.", level=QgsMessageBar.CRITICAL) else: self.export() def search(self, top, bottom, left, right): self.search_thread_pool.waitForDone(0) # validate credentials if they changed errors = [] username, password, api_key, max_items_to_return = SettingsOps.get_settings() credentials = [username, password, api_key] if not self.previous_credentials or self.previous_credentials != credentials: SettingsOps.validate_stored_info(username, password, api_key, max_items_to_return, errors) self.previous_credentials = credentials # validate filters if not errors: self.filters.validate(errors) if errors: self.iface.messageBar().pushMessage("Error", "The following errors occurred: " + "<br />".join(errors), level=QgsMessageBar.CRITICAL) else: self.init_layers() self.dialog_ui.tab_widget.setCurrentIndex(RESULTS_TAB_INDEX) next_x_list = self.drange_list(float(left) + INCREMENTAL_INTERVAL, float(right), INCREMENTAL_INTERVAL) next_y_list = self.drange_list(float(bottom) + INCREMENTAL_INTERVAL, float(top), INCREMENTAL_INTERVAL) self.init_progress_bar(len(next_x_list) * len(next_y_list)) self.model = CatalogTableModel(self.dialog_ui.table_view) self.dialog_ui.table_view.setModel(self.model) self.dialog_ui.table_view.selectionModel().selectionChanged.connect(self.selection_changed) if not self.query: self.query = GBDQuery(username=username, password=password, api_key=api_key) filters = self.filters.get_query_filters() time_begin = self.filters.get_datetime_begin() time_end = self.filters.get_datetime_end() current_x = float(left) current_y = float(bottom) for next_x in next_x_list: for next_y in next_y_list: search_runnable = CatalogSearchRunnable(self.query, self.model, self, top=next_y, left=current_x, right=next_x, bottom=current_y, time_begin=time_begin, time_end=time_end, filters=filters) search_runnable.task_object.task_complete.connect(self.on_search_complete) self.search_thread_pool.start(search_runnable) current_y = next_y current_y = bottom current_x = next_x def reset(self): self.filters.remove_all() def export(self): self.export_thread_pool.waitForDone(0) acquisitions = None if self.model is not None: acquisitions = self.model.data if not acquisitions: self.iface.messageBar().pushMessage("Error", "No data to export.", level=QgsMessageBar.CRITICAL) else: # open file ui select_file_ui = QFileDialog() starting_file = self.export_file or os.path.expanduser("~") export_file = select_file_ui.getSaveFileName(None, "Choose output file", starting_file, SELECT_FILTER) if export_file: self.export_file = export_file self.init_progress_bar(0) export_runnable = CatalogExportRunnable(acquisitions, self.export_file) export_runnable.task_object.task_complete.connect(self.on_export_complete) self.export_thread_pool.start(export_runnable) @pyqtSlot() def on_search_complete(self): thread_count = self.get_search_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.dialog_ui.table_view.resizeColumnsToContents() @pyqtSlot() def on_export_complete(self): thread_count = self.get_export_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.iface.messageBar().pushMessage("Info", 'File export has completed to "%s".' % self.export_file) def selection_changed(self, selected, deselected): self.footprint_layer.startEditing() # draw footprints for selected rows selected_rows = set() for index in selected.indexes(): selected_rows.add(index.row()) for row in selected_rows: acquisition = self.model.get(row) feature_id = self.model.generate_feature_id() self.model.set_feature_id(acquisition, feature_id) feature = CatalogAcquisitionFeature(feature_id, acquisition) self.footprint_layer.dataProvider().addFeatures([feature]) # remove footprints for deselected rows deselected_rows = set() for index in deselected.indexes(): deselected_rows.add(index.row()) feature_ids_to_remove = [] for row in deselected_rows: acquisition = self.model.get(row) feature_id = self.model.get_feature_id(acquisition) feature_ids_to_remove.append(feature_id) self.model.remove_feature_id(acquisition) if feature_ids_to_remove: self.footprint_layer.dataProvider().deleteFeatures(feature_ids_to_remove) self.footprint_layer.commitChanges() self.footprint_layer.updateExtents() self.footprint_layer.triggerRepaint() def drange_list(self, start, stop, step): drange_list = [] r = start while r < stop: drange_list.append(r) r += step if not drange_list: drange_list.append(stop) return drange_list
class VmUsageBarWidget(QWidget): class VmUsageBarItem(QTableWidgetItem): def __init__(self, value, vm): super(VmUsageBarWidget.VmUsageBarItem, self).__init__() self.value = value self.vm = vm def set_value(self, value): self.value = value def __lt__(self, other): if self.vm.qid == 0: return True elif other.vm.qid == 0: return False elif self.value == other.value: return self.vm.qid < other.vm.qid else: return int(self.value) < int(other.value) def __init__(self, min, max, format, update_func, vm, load, hue=210, parent=None): super(VmUsageBarWidget, self).__init__(parent) self.min = min self.max = max self.update_func = update_func self.value = min self.widget = QProgressBar() self.widget.setMinimum(min) self.widget.setMaximum(max) self.widget.setFormat(format) self.widget.setStyleSheet( "QProgressBar:horizontal{" +\ "border: 1px solid hsv({0}, 100, 250);".format(hue) +\ "border-radius: 4px;\ background: white;\ text-align: center;\ }\ QProgressBar::chunk:horizontal {\ background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, " +\ "stop: 0 hsv({0}, 170, 207),".format(hue) + " stop: 1 white); \ }" ) layout = QHBoxLayout() layout.addWidget(self.widget) self.setLayout(layout) self.tableItem = self.VmUsageBarItem(min, vm) self.update_load(vm, load) def update_load(self, vm, load): self.value = self.update_func(vm, load) self.widget.setValue(self.value) self.tableItem.set_value(self.value)
def showNodes(self): """ Parse the geometry of a selected layer and show its vertices (nodes) """ mr = self.layerRegistry # Get the selected layer for which to show nodes selectedIndex = self.dlg.comboLayers.currentIndex() selectedLayer = self.dlg.comboLayers.itemData(selectedIndex) registeredLayers = self.layerRegistry.mapLayersByName('Noeuds') featuresCount = int(selectedLayer.featureCount()) # Remove the node layer if already existing if mr.mapLayersByName('Noeuds'): mr.removeMapLayer(mr.mapLayersByName('Noeuds')[0].id()) # Create memory layer to display nodes self.nodeLayer = QgsVectorLayer("Point?crs=EPSG:2056", "Noeuds", "memory") self.nodeLayerProvider = self.nodeLayer.dataProvider() # Create rendering style nodeSymbol = QgsMarkerSymbolV2.defaultSymbol( self.nodeLayer.geometryType()) nodeSymbol.setColor(QColor('#CC3300')) nodeSymbol.setSize(2.0) nodeRenderer = QgsSingleSymbolRendererV2(nodeSymbol) self.nodeLayer.setRendererV2(nodeRenderer) # Select features visible in current map canvas extent if self.dlg.chkSelectByCanvasExtent.checkState(): extent = self.canvas.extent() rect = QgsRectangle(extent.xMinimum(), extent.yMinimum(), extent.xMaximum(), extent.yMaximum()) request = QgsFeatureRequest() request.setFilterRect(rect) featureIterator = selectedLayer.getFeatures(request) # Select all features else: featureIterator = selectedLayer.getFeatures() # Create progress bar progressMessageBar = self.messageBar.createMessage( unicode("Création des noeuds...", "utf-8")) progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(featuresCount) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.messageBar.pushWidget(progressMessageBar, self.iface.messageBar().INFO) # Iterate over feature k = 0 for feature in featureIterator: k += 1 progress.setValue(k) geom = feature.geometry() feat = QgsFeature() # Adapt procedure for each geometry type if (geom): type = geom.wkbType() # LineString if type == QGis.WKBLineString: for point in geom.asPolyline(): feat.setGeometry(QgsGeometry.fromPoint(point)) self.nodeLayerProvider.addFeatures([feat]) # MultiLineString elif type == QGis.WKBMultiLineString: for line in geom.asMultiPolyline(): for vertex in line: feat.setGeometry( QgsGeometry.fromPoint( QgsPoint(vertex[0], vertex[1]))) self.nodeLayerProvider.addFeatures([feat]) # Polygon elif type == QGis.WKBPolygon: polygons = geom.asPolygon() for polygon in polygons: for vertex in polygon: feat.setGeometry( QgsGeometry.fromPoint( QgsPoint(vertex[0], vertex[1]))) self.nodeLayerProvider.addFeatures([feat]) # MultiPolygon elif type == QGis.WKBMultiPolygon: multiPoly = geom.asMultiPolygon() for polygons in multiPoly: for polygon in polygons: for vertex in polygon: feat.setGeometry( QgsGeometry.fromPoint( QgsPoint(vertex[0], vertex[1]))) self.nodeLayerProvider.addFeatures([feat]) else: self.messageBar.pushMessage( "Cartotools : ", unicode("Type de géométrie non" + "supporté: " + str(type), "utf-8"), level=QgsMessageBar.CRITICAL) self.messageBar.clearWidgets() self.layerRegistry.addMapLayer(self.nodeLayer)
class QuadStatusBar(QHBoxLayout): positionChanged = pyqtSignal(int, int, int) # x,y,z def __init__(self, parent=None): QHBoxLayout.__init__(self, parent) self.setContentsMargins(0, 4, 0, 0) self.setSpacing(0) def showXYCoordinates(self): self.zLabel.setHidden(True) self.zSpinBox.setHidden(True) def showXYZCoordinates(self): self.zLabel.setHidden(False) self.zSpinBox.setHidden(False) def createQuadViewStatusBar(self, xbackgroundColor, xforegroundColor, ybackgroundColor, yforegroundColor, zbackgroundColor, zforegroundColor): self.xLabel, self.xSpinBox = _get_pos_widget('X', xbackgroundColor, xforegroundColor) self.yLabel, self.ySpinBox = _get_pos_widget('Y', ybackgroundColor, yforegroundColor) self.zLabel, self.zSpinBox = _get_pos_widget('Z', zbackgroundColor, zforegroundColor) self.xSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'x')) self.ySpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'y')) self.zSpinBox.delayedValueChanged.connect( partial(self._handlePositionBoxValueChanged, 'z')) self.addWidget(self.xLabel) self.addWidget(self.xSpinBox) self.addWidget(self.yLabel) self.addWidget(self.ySpinBox) self.addWidget(self.zLabel) self.addWidget(self.zSpinBox) self.addSpacing(10) self.busyIndicator = QProgressBar() self.busyIndicator.setMaximum(0) self.busyIndicator.setMinimum(0) self.busyIndicator.setVisible(False) self.busyIndicator.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.addWidget(self.busyIndicator) self.setStretchFactor(self.busyIndicator, 1) self.addStretch() self.addSpacing(10) self.positionCheckBox = QCheckBox() self.positionCheckBox.setChecked(True) self.positionCheckBox.setCheckable(True) self.positionCheckBox.setText("Position") self.addWidget(self.positionCheckBox) self.addSpacing(20) self.timeLabel = QLabel("Time:") self.addWidget(self.timeLabel) self.timeSpinBox = DelayedSpinBox(750) self.addWidget(self.timeSpinBox) def _handlePositionBoxValueChanged(self, axis, value): new_position = [ self.xSpinBox.value(), self.ySpinBox.value(), self.zSpinBox.value() ] changed_axis = ord(axis) - ord('x') new_position[changed_axis] = value self.positionChanged.emit(*new_position) def updateShape5D(self, shape5D): self.timeSpinBox.setMaximum(shape5D[0] - 1) self.xSpinBox.setMaximum(shape5D[1] - 1) self.ySpinBox.setMaximum(shape5D[2] - 1) self.zSpinBox.setMaximum(shape5D[3] - 1) def setMouseCoords(self, x, y, z): self.xSpinBox.setValueWithoutSignal(x) self.ySpinBox.setValueWithoutSignal(y) self.zSpinBox.setValueWithoutSignal(z)
class LoginWinGui(BaseWindow, QtGui.QMainWindow): loginComplete = QtCore.pyqtSignal(Session) def __init__(self, parent=None): super(LoginWinGui, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.login.clicked.connect(self.login) self.ui.login.setDefault(True) self.ui.adduser.triggered.connect(self.adduser) self.ui.forgot.triggered.connect(self.forgot) QtGui.QShortcut(QtGui.QKeySequence("Return"), self).activated.connect(self.login) QtGui.QShortcut(QtGui.QKeySequence("Enter"), self).activated.connect(self.login) QtGui.QShortcut(QtGui.QKeySequence("Up"), self).activated.connect(self.focusUp) QtGui.QShortcut(QtGui.QKeySequence("Down"), self).activated.connect(self.focusDown) self.progressIndicator = QProgressBar(self.ui.statusBar) self.progressIndicator.setMinimumHeight(5) self.progressIndicator.setVisible(False) self.progressIndicator.setMaximum(0) self.progressIndicator.setMinimum(0) self.ui.statusBar.addWidget(self.progressIndicator) self.loginComplete.connect(self.loginCompleteSlot) self.uiTranslate() def uiTranslate(self): self.setWindowTitle(strings["loginWindowTitle"]) self.ui.username.setPlaceholderText(strings["usernameBoxHint"]) self.ui.password.setPlaceholderText(strings["passwordBoxHint"]) self.ui.login.setText(strings["loginButtonText"]) self.ui.adduser.setText(strings["registerUserWindowTitle"]) self.ui.forgot.setText(strings["forgotPasswordWindowTitle"]) self.ui.menuTools.setTitle(strings["toolsMenuText"]) def loginCompleteSlot(self, session): self.progressIndicator.setVisible(False) self.mainWin = ConversationsWinGui(session) self.mainWin.windowClosed.connect(self.close) self.mainWin.loggedOut.connect(self.loggedOut) self.mainWin.show() self.hide() def loggedOut(self): self.show() self.mainWin.windowClosed.disconnect(self.close) self.mainWin.close() def onMainClose(self): pass def focusUp(self): self.ui.username.setFocus() def focusDown(self): self.ui.password.setFocus() def login(self): self.progressIndicator.setVisible(True) def loginThread(): username = self.ui.username.text() password = self.ui.password.text() if username == "" or password == "": self.showMessageBox.emit(strings["missingFieldsErrorText"]) return try: if storage.getToken(username) and storage.getKey(username): token = storage.getToken(username) public, private = storage.getKey(username) newSession = Session(username, password, token, public, private) storage.storeKey(newSession.username, newSession.public, newSession.private) else: token, public, private = Session.requestNewToken(username, password) newSession = Session(username, password, token, public, private) storage.storeToken(newSession.username, token) storage.storeKey(newSession.username, newSession.public, newSession.private) self.loginComplete.emit(newSession) except SecureMessagingException as error: if error.message == HTTPStrings.RESPONSE_UNAUTHORIZED: storage.storeKey(username, None, None) storage.storeToken(username, None) loginThread() return self.showMessageBox.emit(strings["errorText"] + responseTranslations[str(error)]) Thread(target=loginThread).start() def adduser(self): addUserGui = AddUserGui(parent=self) addUserGui.show() def forgot(self): forgotUi = ForgotPasswordUi(parent=self) forgotUi.show()
def on_uploaded(self): self.uploaded.emit() # Create message widget = self.iface.messageBar().createMessage( u"Géofoncier", u"Envoi des modifications.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(3) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) progress_bar.setValue(1) enr_ref_dossier, ok = QInputDialog.getText( self, u"Référence de dossier", u"Vous êtes sur le point de soumettre\n" u"les modifications au serveur Géofoncier.\n" u"Veuillez renseigner la référence du dossier.") if not ok: return self.abort_action() if not enr_ref_dossier: return self.abort_action( msg=u"Merci de renseigner une référence de dossier.") commentaire = u"Dossier %s" % enr_ref_dossier dossiers = self.conn.dossiersoge_dossiers(self.zone, enr_ref_dossier) if dossiers.code != 200: return self.abort_action(msg=dossiers.read()) tree = EltTree.fromstring(dossiers.read()) # Check if exception err = tree.find(r"./erreur") if err: return self.abort_action(msg=err.text) nb_dossiers = int(tree.find(r"./dossiers").attrib[r"total"]) if nb_dossiers == 0: return self.abort_action(msg=u"Le dossier \'%s\' n'existe pas." % enr_ref_dossier) if nb_dossiers >= 1: # Prendre par défaut le dernier dossier dans la liste dossier_uri = tree.getiterator( tag=r"dossier")[nb_dossiers - 1].find(r"{http://www.w3.org/2005/Atom}link") enr_api_dossier = dossier_uri.attrib[r"href"].split(r"/")[-1][1:] progress_bar.setValue(2) # Stop editing mode for layer in self.layers: if layer.isEditable(): layer.commitChanges() # Check if dataset changes if (self.edges_added or self.vertices_added or self.edges_removed or self.vertices_removed or self.edges_modified or self.vertices_modified): pass else: return self.abort_action( msg=u"Aucune modification des données n'est détecté.") # Upload, reset and re-download datasets try: log = self.upload(enr_api_dossier=enr_api_dossier, commentaire=commentaire) self.reset() self.download(self.url) except Exception as e: return self.abort_action(msg=e.message) self.canvas.zoomToFullExtent() self.iface.messageBar().clearWidgets() return QMessageBox.information(self, r"Information", u"\r".join(log))
class LabelAssistDialog(QDialog): """ A simple UI for showing bookmarks and navigating to them. FIXME: For now, this window is tied to a particular lane. If your project has more than one lane, then each one will have it's own bookmark window, which is kinda dumb. """ def __init__(self, parent, topLevelOperatorView): super(LabelAssistDialog, self).__init__(parent) # Create thread router to populate table on main thread self.threadRouter = ThreadRouter(self) # Set object classification operator view self.topLevelOperatorView = topLevelOperatorView self.setWindowTitle("Label Assist") self.setMinimumWidth(500) self.setMinimumHeight(700) layout = QGridLayout() layout.setContentsMargins(10, 10, 10, 10) # Show variable importance table rows = 0 columns = 4 self.table = QTableWidget(rows, columns) self.table.setHorizontalHeaderLabels( ['Frame', 'Max Area', 'Min Area', 'Labels']) self.table.verticalHeader().setVisible(False) # Select full row on-click and call capture double click self.table.setSelectionBehavior(QTableView.SelectRows) self.table.doubleClicked.connect(self._captureDoubleClick) layout.addWidget(self.table, 1, 0, 3, 2) # Create progress bar self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(0) self.progressBar.hide() layout.addWidget(self.progressBar, 4, 0, 1, 2) # Create button to populate table self.computeButton = QPushButton('Compute object info') self.computeButton.clicked.connect(self._triggerTableUpdate) layout.addWidget(self.computeButton, 5, 0) # Create close button closeButton = QPushButton('Close') closeButton.clicked.connect(self.close) layout.addWidget(closeButton, 5, 1) # Set dialog layout self.setLayout(layout) def _triggerTableUpdate(self): # Check that object area is included in selected features featureNames = self.topLevelOperatorView.SelectedFeatures.value if 'Standard Object Features' not in featureNames or 'Count' not in featureNames[ 'Standard Object Features']: box = QMessageBox( QMessageBox.Warning, 'Warning', 'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"', QMessageBox.NoButton, self) box.show() return # Clear table self.table.clearContents() self.table.setRowCount(0) self.table.setSortingEnabled(False) self.progressBar.show() self.computeButton.setEnabled(False) # Compute object features and number of labels per frame def compute_features(): features = self.topLevelOperatorView.ObjectFeatures([]).wait() labels = self.topLevelOperatorView.LabelInputs([]).wait() return features, labels req = Request(compute_features) req.notify_finished(self._populateTable) req.submit() @threadRouted def _populateTable(self, features_and_labels): features, labels = features_and_labels self.progressBar.hide() self.computeButton.setEnabled(True) for frame, objectFeatures in features.iteritems(): # Insert row rowNum = self.table.rowCount() self.table.insertRow(self.table.rowCount()) # Get max and min object areas areas = objectFeatures['Standard Object Features']['Count'] maxObjArea = numpy.max(areas[numpy.nonzero(areas)]) minObjArea = numpy.min(areas[numpy.nonzero(areas)]) # Get number of labeled objects labelNum = numpy.count_nonzero(labels[frame]) # Load fram number item = QTableWidgetItem(str(frame)) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 0, item) # Load max object areas item = QTableWidgetItemWithFloatSorting( str("{: .02f}".format(maxObjArea))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 1, item) # Load min object areas item = QTableWidgetItemWithFloatSorting( str("{: .02f}".format(minObjArea))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 2, item) # Load label numbers item = QTableWidgetItemWithFloatSorting( str("{: .01f}".format(labelNum))) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.setItem(rowNum, 3, item) # Resize column size to fit dialog size self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch) # Sort by max object area self.table.setSortingEnabled(True) self.table.sortByColumn(1) def _captureDoubleClick(self): # Navigate to selected frame index = self.table.selectedIndexes()[0] frameStr = self.table.model().data(index).toString() if frameStr: frameNum = int(frameStr) self.parent().editor.posModel.time = frameNum
class CatalogDialogTool(QObject): """ Tool for managing the search and export functionality """ def __init__(self, iface, dialog_ui, bbox_tool): """ Constructor for the dialog tool :param iface: The QGIS Interface :param dialog_ui: The dialog GUI :param bbox_tool The bounding box tool :return: dialog tool """ QObject.__init__(self, None) self.iface = iface self.dialog_ui = dialog_ui self.bbox_tool = bbox_tool self.progress_bar = None self.progress_message_bar = None self.progress_message_bar_widget = None self.search_thread_pool = QThreadPool() self.search_lock = Lock() self.export_thread_pool = QThreadPool() self.export_lock = Lock() self.query = None self.previous_credentials = None self.export_file = None self.footprint_layer = None self.filters = CatalogFilters(self.dialog_ui) self.dialog_ui.aoi_button.clicked.connect(self.aoi_button_clicked) self.dialog_ui.reset_button.clicked.connect(self.reset_button_clicked) self.dialog_ui.export_button.clicked.connect( self.export_button_clicked) self.bbox_tool.released.connect(self.search) self.model = None def init_progress_bar(self, progress_max): """ Sets up the progress bar for search functionality :return: None """ if not self.progress_message_bar: self.progress_message_bar = self.iface.messageBar().createMessage( "Querying for data") self.progress_bar = QProgressBar() self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(progress_max) self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignCenter) self.progress_message_bar.layout().addWidget(self.progress_bar) self.progress_message_bar_widget = self.iface.messageBar( ).pushWidget(self.progress_message_bar, self.iface.messageBar().INFO) def init_layers(self): """ Sets up the layers for rendering the items :return: None """ if self.footprint_layer: QgsMapLayerRegistry.instance().removeMapLayer( self.footprint_layer.id()) self.footprint_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "Catalog Footprints", "memory") self.footprint_layer.setCrs(QgsCoordinateReferenceSystem(4326), True) self.footprint_layer.dataProvider().addAttributes( CatalogAcquisitionFeature.get_fields()) QgsMapLayerRegistry.instance().addMapLayer(self.footprint_layer) def clear_widgets(self): """ Clears the progress bar :return: None """ self.progress_bar = None self.progress_message_bar = None if self.progress_message_bar_widget: self.iface.messageBar().popWidget(self.progress_message_bar_widget) self.progress_message_bar_widget = None def is_searching(self): """ Check to see if the system is still searching (checks if there's work in the search thread pool) :return: True if searching; False otherwise """ return self.get_search_active_thread_count() > 0 def is_exporting(self): """ Check to see if the system is still exporting (checks if there's work in the export thread pool) :return: True if searching; False otherwise """ return self.get_export_active_thread_count() > 0 def get_search_active_thread_count(self): """ Gets the number of active threads in the search thread pool :return: """ with self.search_lock: return self.search_thread_pool.activeThreadCount() def get_export_active_thread_count(self): """ Gets the number of active threads in the export thread pool :return: """ with self.export_lock: return self.export_thread_pool.activeThreadCount() def aoi_button_clicked(self): """ Validates and runs the search if validation successful :return: None """ # can't run search during export if self.is_exporting(): self.iface.messageBar().pushMessage( "Error", "Cannot run search while export is running.", level=QgsMessageBar.CRITICAL) # can't run multiple search elif self.is_searching(): self.iface.messageBar().pushMessage( "Error", "Cannot run a new search while a search is running.", level=QgsMessageBar.CRITICAL) else: self.bbox_tool.reset() self.iface.mapCanvas().setMapTool(self.bbox_tool) def reset_button_clicked(self): """ Resets filters. :return: None """ self.reset() def export_button_clicked(self): """ Validates and runs the export if validation successful :return: None """ # can't run export during search if self.is_searching(): self.iface.messageBar().pushMessage( "Error", "Cannot run export while search is running.", level=QgsMessageBar.CRITICAL) # can't run multiple exports elif self.is_exporting(): self.iface.messageBar().pushMessage( "Error", "Cannot run a new export while a export is running.", level=QgsMessageBar.CRITICAL) else: self.export() def search(self, top, bottom, left, right): self.search_thread_pool.waitForDone(0) # validate credentials if they changed errors = [] username, password, api_key, max_items_to_return = SettingsOps.get_settings( ) credentials = [username, password, api_key] if not self.previous_credentials or self.previous_credentials != credentials: SettingsOps.validate_stored_info(username, password, api_key, max_items_to_return, errors) self.previous_credentials = credentials # validate filters if not errors: self.filters.validate(errors) if errors: self.iface.messageBar().pushMessage( "Error", "The following errors occurred: " + "<br />".join(errors), level=QgsMessageBar.CRITICAL) else: self.init_layers() self.dialog_ui.tab_widget.setCurrentIndex(RESULTS_TAB_INDEX) next_x_list = self.drange_list( float(left) + INCREMENTAL_INTERVAL, float(right), INCREMENTAL_INTERVAL) next_y_list = self.drange_list( float(bottom) + INCREMENTAL_INTERVAL, float(top), INCREMENTAL_INTERVAL) self.init_progress_bar(len(next_x_list) * len(next_y_list)) self.model = CatalogTableModel(self.dialog_ui.table_view) self.dialog_ui.table_view.setModel(self.model) self.dialog_ui.table_view.selectionModel( ).selectionChanged.connect(self.selection_changed) if not self.query: self.query = GBDQuery(username=username, password=password, api_key=api_key) filters = self.filters.get_query_filters() time_begin = self.filters.get_datetime_begin() time_end = self.filters.get_datetime_end() current_x = float(left) current_y = float(bottom) for next_x in next_x_list: for next_y in next_y_list: search_runnable = CatalogSearchRunnable( self.query, self.model, self, top=next_y, left=current_x, right=next_x, bottom=current_y, time_begin=time_begin, time_end=time_end, filters=filters) search_runnable.task_object.task_complete.connect( self.on_search_complete) self.search_thread_pool.start(search_runnable) current_y = next_y current_y = bottom current_x = next_x def reset(self): self.filters.remove_all() def export(self): self.export_thread_pool.waitForDone(0) acquisitions = None if self.model is not None: acquisitions = self.model.data if not acquisitions: self.iface.messageBar().pushMessage("Error", "No data to export.", level=QgsMessageBar.CRITICAL) else: # open file ui select_file_ui = QFileDialog() starting_file = self.export_file or os.path.expanduser("~") export_file = select_file_ui.getSaveFileName( None, "Choose output file", starting_file, SELECT_FILTER) if export_file: self.export_file = export_file self.init_progress_bar(0) export_runnable = CatalogExportRunnable( acquisitions, self.export_file) export_runnable.task_object.task_complete.connect( self.on_export_complete) self.export_thread_pool.start(export_runnable) @pyqtSlot() def on_search_complete(self): thread_count = self.get_search_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.dialog_ui.table_view.resizeColumnsToContents() @pyqtSlot() def on_export_complete(self): thread_count = self.get_export_active_thread_count() if self.progress_message_bar: self.progress_bar.setValue(self.progress_bar.value() + 1) if thread_count == 0: self.clear_widgets() self.iface.messageBar().pushMessage( "Info", 'File export has completed to "%s".' % self.export_file) def selection_changed(self, selected, deselected): self.footprint_layer.startEditing() # draw footprints for selected rows selected_rows = set() for index in selected.indexes(): selected_rows.add(index.row()) for row in selected_rows: acquisition = self.model.get(row) feature_id = self.model.generate_feature_id() self.model.set_feature_id(acquisition, feature_id) feature = CatalogAcquisitionFeature(feature_id, acquisition) self.footprint_layer.dataProvider().addFeatures([feature]) # remove footprints for deselected rows deselected_rows = set() for index in deselected.indexes(): deselected_rows.add(index.row()) feature_ids_to_remove = [] for row in deselected_rows: acquisition = self.model.get(row) feature_id = self.model.get_feature_id(acquisition) feature_ids_to_remove.append(feature_id) self.model.remove_feature_id(acquisition) if feature_ids_to_remove: self.footprint_layer.dataProvider().deleteFeatures( feature_ids_to_remove) self.footprint_layer.commitChanges() self.footprint_layer.updateExtents() self.footprint_layer.triggerRepaint() def drange_list(self, start, stop, step): drange_list = [] r = start while r < stop: drange_list.append(r) r += step if not drange_list: drange_list.append(stop) return drange_list
class CANMonitor(QMainWindow): def __init__(self, app, test, parent): QMainWindow.__init__(self, parent) self.app = app self.lcdDict=dict() self.logBuffer=deque("", 1000) self.logBuffer2=dict() self.logBufferInit=dict() self.logEntryCount=1 self.maxLogEntryCount=65353 self.tableUpdateCouter=0 self.logFile=None self.test=test self.logFileName="/tmp/candash.log" self.connectCANEnable=True self.connectGPSEnable=True self.replayMode=False self.canIdList=[0x621, 0x353, 0x351, 0x635, 0x271, 0x371, 0x623, 0x571, 0x3e5, 0x591, 0x5d1] self.updateGPSThread=None self.config=Config("candash.cfg") self.log=Log(False) font = self.font() font.setPointSize(14) self.setFont(font) self.ampelGruen=QIcon("images/ampel-gruen.png") self.ampelRot=QIcon("images/ampel-rot.png") self.ampelGelb=QIcon("images/ampel-gelb.png") self.lastCANState=canStoppedState self.lastGPSState=gpsStoppedState self.canDecoder=CANDecoder(self) self.initUI(parent) def clearAllLCD(self): for lcdList in self.lcdDict.values(): for lcd in lcdList: if lcd.mode()==QLCDNumber.Bin: lcd.display("00000000") else: lcd.display(0) self.rpmGauge.setValue(0) self.velGauge.setValue(0) def createLCD(self, mode): lcd = QLCDNumber(self) lcd.setMode(mode) lcd.setMinimumHeight(50) lcd.setMinimumWidth(160) lcd.setDigitCount(8) if mode==QLCDNumber.Bin: lcd.display("00000000") else: lcd.display(0) lcd.setSegmentStyle(QLCDNumber.Flat) lcd.setAutoFillBackground(True) palette = lcd.palette() palette.setColor(QPalette.Normal, QPalette.Foreground, Qt.blue) palette.setColor(QPalette.Normal, QPalette.Background, Qt.lightGray) lcd.setPalette(palette); return lcd def addLCD(self, lcd, canId, subItem): if not hex(canId)+":"+subItem in self.lcdDict.keys(): lcdItemList=list() lcdItemList.append(lcd) self.lcdDict[hex(canId)+":"+subItem]=lcdItemList else: self.lcdDict[hex(canId)+":"+subItem].append(lcd) def createCANIdValueEntry(self, vbox, canId, subId, mode): lcd = self.createLCD(mode) self.addLCD(lcd, canId, subId) vbox.addWidget(lcd) def createCANIdEntry(self, form, canId, subId, label, mode): # hbox = QHBoxLayout() lbl = QLabel(self) lbl.setMinimumHeight(50) font = lbl.font() font.setPointSize(14) lbl.setFont(font) if label!=None: lbl.setText(label) # hbox.addWidget(lbl) lcd = self.createLCD(mode) # hbox.addWidget(lcd) form.addRow(lbl, lcd) self.addLCD(lcd, canId, subId) # vbox.addLayout(hbox) def createCANIdEntrySingleLine(self, form, canId, subIdList, label, mode): # hbox = QHBoxLayout() lbl = QLabel(self) lbl.setMinimumHeight(50) font = lbl.font() font.setPointSize(14) lbl.setFont(font) if label!=None: lbl.setText(label) # hbox.addWidget(lbl) hbox2=QHBoxLayout(); for i in range(len(subIdList)): subId=subIdList[i] lcd = self.createLCD(mode) hbox2.addWidget(lcd) self.addLCD(lcd, canId, subId) form.addRow(lbl, hbox2) # hbox.addLayout(hbox2) # vbox.addLayout(hbox) def createLogView(self, vbox): self.logView=QTableView(self) vbox.addWidget(self.logView) self.logViewModel=CANLogViewTableModel(self.logBuffer, self.canIdList, self) self.logView.setModel(self.logViewModel) header=QHeaderView(Qt.Horizontal, self.logView) header.setStretchLastSection(True) header.setResizeMode(NUMBER_COL, QHeaderView.Fixed) header.setResizeMode(TIME_COL, QHeaderView.Fixed) header.setResizeMode(ID_COL, QHeaderView.Fixed) self.logView.setHorizontalHeader(header) self.logView.setColumnWidth(NUMBER_COL, 80) self.logView.setColumnWidth(TIME_COL, 150) self.logView.setColumnWidth(ID_COL, 80) self.logView.setColumnWidth(SIZE_COL, 50) def createLogView2(self, vbox): self.logView2=QTableView(self) vbox.addWidget(self.logView2) self.logViewModel2=CANLogViewTableModel2(self.canIdList, self) self.logView2.setModel(self.logViewModel2) # self.logView2.setSortingEnabled(True) header=QHeaderView(Qt.Horizontal, self.logView2) # header.setStretchLastSection(True) # header.setClickable(True) header.setResizeMode(0, QHeaderView.Fixed) header.setResizeMode(1, QHeaderView.Fixed) self.logView2.setHorizontalHeader(header) self.logView2.setColumnWidth(0, 80) self.logView2.setColumnWidth(1, 50) for i in range(2, 10): self.logView2.setColumnWidth(i, 60) def initUI(self, parent): # exitAction = QAction(QIcon(), 'Exit', self) # exitAction.setShortcut('Ctrl+Q') # exitAction.setStatusTip('Exit application') # exitAction.triggered.connectToCAN(self.close) self.statusbar=self.statusBar() self.progress=QProgressBar() self.statusbar.addPermanentWidget(self.progress) # menubar = self.menuBar() # fileMenu = menubar.addMenu('&File') # fileMenu.addAction(exitAction) # toolbar = self.addToolBar('Exit') ## toolbar.addAction(exitAction) # # self.connectedIcon=QIcon("images/network-connect.png") # self.disconnectIcon=QIcon("images/network-disconnect.png") # self.connectAction = QAction(self.disconnectIcon , 'Connect', self) # self.connectAction.triggered.connect(self._connect1) # self.connectAction.setCheckable(True) # # toolbar.addAction(self.connectAction) # # self.gpsIcon=QIcon("images/icon_gps.gif") # self.reconnectGPSAction = QAction(self.gpsIcon, 'Reconnect GPS', self) # self.reconnectGPSAction.triggered.connect(self._reconnectGPS) # toolbar.addAction(self.reconnectGPSAction) mainWidget=QWidget(self) # mainWidget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) mainWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.setCentralWidget(mainWidget) top=QVBoxLayout(mainWidget) self.tabs = MyTabWidget(self) top.addWidget(self.tabs) mainTab = QWidget(self) miscTab = QWidget(self) misc2Tab=QWidget(self) canLogTab=QWidget(self) dashTab=QWidget(self) gpsTab=QWidget(self) osmTab=QWidget(self) debugLogTab=QWidget(self) mainTabLayout = QFormLayout(mainTab) miscTabLayout = QFormLayout(miscTab) misc2TabLayout = QFormLayout(misc2Tab) canLogTabLayout = QVBoxLayout(canLogTab) dashTabLayout = QHBoxLayout(dashTab) gpsTabLayout=QHBoxLayout(gpsTab) osmTabLayout=QVBoxLayout(osmTab) debugLogTabLayout=QVBoxLayout(debugLogTab) self.tabs.addTab(dashTab, "Dash") self.tabs.addTab(mainTab, "Main") self.tabs.addTab(miscTab, "Misc 1") self.tabs.addTab(misc2Tab, "Misc 2") self.tabs.addTab(canLogTab, "CAN") self.tabs.addTab(gpsTab, "GPS") self.tabs.addTab(osmTab, "OSM") self.tabs.addTab(debugLogTab, "Log") self.tabs.setCurrentIndex(0) self.debugLogWidget=DebugLogWidget(self) debugLogTabLayout.setAlignment(Qt.AlignLeft|Qt.AlignTop) self.debugLogWidget.addToWidget(debugLogTabLayout) # self.debugLogWidget.addLine("test") self.createCANIdEntry(mainTabLayout, 0x353, "0", "Drehzahl", QLCDNumber.Dec) # self.createCANIdEntry(mainTabLayout, 0x353, "1", "Öltemperatur", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x353, "1", "Kuehlwasser Temperatur", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x351, "0", "Geschwindigkeit", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x351, "1", "Außentemperatur", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x635, "0", "Licht, Klemme 58d", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x271, "0", "Zuendung", QLCDNumber.Dec) self.createCANIdEntrySingleLine(miscTabLayout, 0x371, ["0", "1"], "Tuerstatus", QLCDNumber.Bin) self.createCANIdEntry(miscTabLayout, 0x371, "2", "Blinker, Retoursgang", QLCDNumber.Bin) self.createCANIdEntrySingleLine(mainTabLayout, 0x623, ["0", "1", "2"], "Uhrzeit (Stunden)", QLCDNumber.Dec) self.createCANIdEntry(mainTabLayout, 0x571, "0", "Batteriespannung", QLCDNumber.Dec) self.createCANIdEntry(misc2TabLayout, 0x3e5, "0", "Zuheizer 1", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "1", "Zuheizer 2", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "2", "Zuheizer 3", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "3", "Zuheizer 4", QLCDNumber.Bin) self.createCANIdEntry(misc2TabLayout, 0x3e5, "4", "Zuheizer 5", QLCDNumber.Bin) self.createCANIdEntry(miscTabLayout, 0x3e5, "5", "Zuheizer", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x591, "0", "ZV", QLCDNumber.Dec) self.createCANIdEntry(miscTabLayout, 0x5d1, "0", "Scheibenwischer", QLCDNumber.Dec) self.createCANIdEntrySingleLine(mainTabLayout, 0x351, ["2", "3"], "Wegstreckenimpuls", QLCDNumber.Dec) self.createCANIdEntrySingleLine(misc2TabLayout, 0x621, ["0"], "0x621", QLCDNumber.Bin) self.createCANIdEntrySingleLine(misc2TabLayout, 0x621, ["1", "2"], "0x621", QLCDNumber.Dec) logTabs = MyTabWidget(self) canLogTabLayout.addWidget(logTabs) logTabWidget1=QWidget() logTabWidget2=QWidget() logTabs.addTab(logTabWidget1, "Time") logTabs.addTab(logTabWidget2, "Change") logTab1Layout = QVBoxLayout(logTabWidget1) self.createLogView(logTab1Layout) self.logViewFilerBox1=CANFilterBox(False, self) self.logViewFilerBox1.addFilterBox(logTab1Layout) self.logViewTableBox1=CANLogTableBox(self.logViewModel, self.logBuffer, None, self) self.logViewTableBox1.addTableBox(logTab1Layout) logTab2Layout = QVBoxLayout(logTabWidget2) self.createLogView2(logTab2Layout) self.logViewFilterBox2=CANFilterBox(True, self) self.logViewFilterBox2.addFilterBox(logTab2Layout) self.logViewTableBox2=CANLogTableBox(self.logViewModel2, self.logBuffer2, self.logBufferInit, self) self.logViewTableBox2.addTableBox(logTab2Layout) logButtonBox = QHBoxLayout() canLogTabLayout.addLayout(logButtonBox) self.logFileButton=QCheckBox("Log to File", self) self.logFileButton.setToolTip('Enable file logging') self.logFileButton.resize(self.logFileButton.sizeHint()) self.logFileButton.setDisabled(self.replayMode==True) self.logFileButton.clicked.connect(self._enableLogFile) logButtonBox.addWidget(self.logFileButton) self.clearLogButton = QPushButton('Clear Log', self) self.clearLogButton.resize(self.clearLogButton.sizeHint()) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) self.clearLogButton.clicked.connect(self._clearLogFile) logButtonBox.addWidget(self.clearLogButton) self.replayButton = QPushButton('Replay Log', self) self.replayButton.resize(self.replayButton.sizeHint()) self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.replayButton.clicked.connect(self._startReplayMode) logButtonBox.addWidget(self.replayButton) self.stopReplayButton = QPushButton('Stop Replay', self) self.stopReplayButton.resize(self.stopReplayButton.sizeHint()) self.stopReplayButton.setDisabled(self.replayMode==False) self.stopReplayButton.clicked.connect(self._stopReplayMode) logButtonBox.addWidget(self.stopReplayButton) velBox = QVBoxLayout() dashTabLayout.addLayout(velBox) dashTabLayout.setAlignment(Qt.AlignCenter|Qt.AlignBottom) self.velGauge=QtPngDialGauge(self, "tacho3", "tacho31.png") self.velGauge.setMinimum(20) self.velGauge.setMaximum(220) self.velGauge.setStartAngle(135) self.velGauge.setValue(0) # self.velGauge.setMaximumSize(400, 400) velBox.addWidget(self.velGauge) self.createCANIdValueEntry(velBox, 0x351, "0", QLCDNumber.Dec) valuesBox = QVBoxLayout() valuesBox.setAlignment(Qt.AlignCenter|Qt.AlignBottom) dashTabLayout.addLayout(valuesBox) self.createCANIdValueEntry(valuesBox, 0x353, "1", QLCDNumber.Dec) self.createCANIdValueEntry(valuesBox, 0x351, "1", QLCDNumber.Dec) self.createCANIdValueEntry(valuesBox, 0x571, "0", QLCDNumber.Dec) rpmBox = QVBoxLayout() dashTabLayout.addLayout(rpmBox) # rpmBox.setAlignment(Qt.AlignCenter|Qt.AlignHCenter) self.rpmGauge=QtPngDialGauge(self, "rpm", "rpm1.png") self.rpmGauge.setMinimum(0) self.rpmGauge.setMaximum(8000) self.rpmGauge.setStartAngle(125) self.rpmGauge.setValue(2500) # self.rpmGauge.setMaximumSize(400, 400) rpmBox.addWidget(self.rpmGauge) self.createCANIdValueEntry(rpmBox, 0x353, "0", QLCDNumber.Dec) self.gpsBox=GPSMonitor(self) gpsTabLayout.setAlignment(Qt.AlignLeft|Qt.AlignTop) self.gpsBox.loadConfig(self.config) self.gpsBox.addToWidget(gpsTabLayout) self.osmWidget=OSMWidget(self) osmTabLayout.setAlignment(Qt.AlignLeft|Qt.AlignTop) self.osmWidget.addToWidget(osmTabLayout) self.osmWidget.loadConfig(self.config) self.osmWidget.initWorkers() self.connect(self.osmWidget.mapWidgetQt, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.osmWidget.downloadThread, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.osmWidget, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.osmWidget, SIGNAL("startProgress()"), self.startProgress) self.connect(self.osmWidget, SIGNAL("stopProgress()"), self.stopProgress) self.osmWidget.initHome() connectBox=QHBoxLayout() top.addLayout(connectBox) section="connect" self.connectCANButton = QCheckBox('CAN Connect', self) self.connectCANButton.clicked.connect(self._connectCAN) self.connectCANEnable=self.config.getSection(section).getboolean("CANconnect", False) self.connectCANButton.setChecked(self.connectCANEnable) self.connectCANButton.setIcon(self.ampelRot) connectBox.addWidget(self.connectCANButton) self.connectGPSButton = QCheckBox('GPS Connect', self) self.connectGPSButton.clicked.connect(self._connectGPS) self.connectGPSEnable=self.config.getSection(section).getboolean("GPSconnect", False) self.connectGPSButton.setChecked(self.connectGPSEnable) self.connectGPSButton.setIcon(self.ampelRot) connectBox.addWidget(self.connectGPSButton) self.setGeometry(0, 0, 900, 600) self.setWindowTitle("candash") self.show() self.updateCANThread = CANSocketWorker(self) self.connect(self.updateCANThread, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.updateCANThread, SIGNAL("updateCANThreadState(QString)"), self.updateCANThreadState) self.connect(self.updateCANThread, SIGNAL("clearAllLCD()"), self.clearAllLCD) self.connect(self.updateCANThread, SIGNAL("connectCANFailed()"), self.connectCANFailed) self.connect(self.updateCANThread, SIGNAL("replayModeDone()"), self.replayModeDone) self.connect(self.updateCANThread, SIGNAL("processCANData(PyQt_PyObject)"), self.canDecoder.scan_can_frame) self._connectCAN() self.updateGPSThread=getGPSUpdateThread(self) if self.updateGPSThread!=None: self.connect(self.updateGPSThread, SIGNAL("updateStatus(QString)"), self.updateStatusBarLabel) self.connect(self.updateGPSThread, SIGNAL("updateGPSThreadState(QString)"), self.updateGPSThreadState) self.connect(self.updateGPSThread, SIGNAL("connectGPSFailed()"), self.connectGPSFailed) self.connect(self.updateGPSThread, SIGNAL("updateGPSDisplay(PyQt_PyObject)"), self.updateGPSDisplay) self._connectGPS() #def mousePressEvent(self, event): # print("CANMonitor mousePressEvent") # self.tabs.mousePressEvent(event) def getWidget(self, canId, subId): try: return self.lcdDict[hex(canId)+":"+subId] except KeyError: return list() def setValueDashDisplayRPM(self, value): if value!=self.rpmGauge.value(): self.rpmGauge.setValue(value) def setValueDashDisplayVel(self, value): if value!=self.velGauge.value(): self.velGauge.setValue(value) def displayIntValue(self, canId, subId, value, formatString): lcdList=self.getWidget(canId, subId) for lcdItem in lcdList: if lcdItem.intValue()!=int(value): lcdItem.display(formatString % value) def displayBinValue(self, canId, subId, value, formatString): lcdList=self.getWidget(canId, subId) for lcdItem in lcdList: if lcdItem.intValue()!=int(value): lcdItem.display(formatString % value) def displayFloatValue(self, canId, subId, value, formatString): lcdList=self.getWidget(canId, subId) for lcdItem in lcdList: if lcdItem.value()!=value: lcdItem.display(formatString % value) def addToLogView(self, line): tableEntry=[self.logEntryCount, self.createTimeStamp()] tableEntry.extend(line[0:]) if self.logFile!=None: self.addToLogFile(tableEntry) if self.logViewTableBox1.update==True: canId=line[0] if not self.logViewFilerBox1.matchFilter(canId, line, None): return self.logBuffer.appendleft(tableEntry) self.logEntryCount=self.logEntryCount+1 if self.logEntryCount==self.maxLogEntryCount: self.logEntryCount=1 self.tableUpdateCouter=self.tableUpdateCouter+1 if self.tableUpdateCouter==10: self.logViewModel.update(self.logBuffer, None) self.tableUpdateCouter=0 def addToLogView2(self, line): if self.logViewTableBox2.update==True: canId=line[0] if not canId in self.logBufferInit.keys(): self.logBufferInit[canId]=line if not self.logViewFilterBox2.matchFilter(canId, line, self.logBufferInit[canId]): try: del self.logBuffer2[canId] except KeyError: None else: self.logBuffer2[canId]=line self.logViewModel2.update(list(self.logBuffer2.values()), self.logBufferInit) def createTimeStamp(self): stamp=datetime.fromtimestamp(time.time()) return "".join(["%02d:%02d:%02d.%06d"%(stamp.hour, stamp.minute, stamp.second, stamp.microsecond)]) def dumpLogLine(self, line): logLine="%s %s %s"% (line[1], hex(line[2]), line[3]) dataLine="".join(["0x%02X " % x for x in line[4]]) return logLine+" "+dataLine def addToLogFile(self, line): if self.logFile!=None: self.logFile.write(self.dumpLogLine(line)+"\n") def setupLogFile(self, filePath): if self.logFile==None: self.logFile=open(filePath,"a") self.logFile.write("# Log started: "+time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())+"\n") self.logFile.write("# -------------------------------------------------------\n") def closeLogFile(self): if self.logFile!=None: self.logFile.write("# Log stoped: "+time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())+"\n") self.logFile.write("# -------------------------------------------------------\n") self.logFile.close() self.logFile=None def logFileAvailable(self): try: open(self.logFileName, "r") return True except IOError: return False def readLogFile(self): try: logFileEntries=list() readLogFile=open(self.logFileName, "r") while True: line=readLogFile.readline() if not line: break if line[0]=="#": continue lineParts=line.split(" ") strippedLen=len(lineParts)-1 neededLineParts=lineParts[1:strippedLen] addLen=8-len(neededLineParts[2:]) for _ in range(addLen): neededLineParts.append("%s" % "0x00") logFileEntries.append(struct.pack("IIBBBBBBBB", int(neededLineParts[0], 16), int(neededLineParts[1], 10), int(neededLineParts[2], 16), int(neededLineParts[3], 16),int(neededLineParts[4], 16),int(neededLineParts[5], 16),int(neededLineParts[6], 16), int(neededLineParts[7], 16), int(neededLineParts[8], 16), int(neededLineParts[9], 16))) return logFileEntries except IOError: return list() @pyqtSlot() def _enableFilter(self): self.filter=self.filterButton.isChecked() self.filterEdit.setDisabled(self.filter==False) self.applyFilterButton.setDisabled(self.filter==False) self.filterAll.setDisabled(self.filter==False) self.filterKnown.setDisabled(self.filter==False) self.filterUnknown.setDisabled(self.filter==False) self.filterRingIdsButton.setDisabled(self.filter==False) @pyqtSlot() def _applyFilter(self): if self.filter==True: self.filterValue=self.filterEdit.text() else: self.filterValue="" @pyqtSlot() def _cleanup(self): self.osmWidget._cleanup() self.gpsBox._cleanup() if self.updateCANThread.isRunning(): self.updateCANThread.stop() if self.updateGPSThread.isRunning(): self.updateGPSThread.stop() self.closeLogFile() section="connect" self.config.removeSection(section) self.config.addSection(section) self.config.getSection(section)["canConnect"]=str(self.connectCANEnable) self.config.getSection(section)["gpsConnect"]=str(self.connectGPSEnable) self.osmWidget.saveConfig(self.config) self.gpsBox.saveConfig(self.config) self.config.writeConfig() self.log.writeLogtoFile() @pyqtSlot() def _enableLogFile(self): if self.logFileButton.isChecked()==True: if self.logFile==None: self.setupLogFile(self.logFileName) else: self.closeLogFile() self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) @pyqtSlot() def _startReplayMode(self): self.closeLogFile() self.logFileButton.setChecked(False) self.replayButton.setDisabled(True) self.replayMode=True self.stopReplayButton.setDisabled(self.replayMode==False) self.logFileButton.setDisabled(self.replayMode==True) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) replayLines=self.readLogFile() self.logViewTableBox1._clearTable() self.logViewTableBox2._clearTable() self.updateCANThread.setup(self.app, self, self.test, True, replayLines) @pyqtSlot() def _stopReplayMode(self): self.updateCANThread.stop() self.replayModeDone() def replayModeDone(self): self.replayMode=False self.stopReplayButton.setDisabled(self.replayMode==False) self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.logFileButton.setDisabled(self.replayMode==True) self.clearLogButton.setDisabled(not self.logFileAvailable() or self.replayMode==True) @pyqtSlot() def _clearLogFile(self): if self.logFileAvailable(): self.closeLogFile() os.remove(self.logFileName) self.logFile=None self._enableLogFile() @pyqtSlot() def _connectCAN(self): self.connectCANEnable=self.connectCANButton.isChecked() if self.replayMode==True: self._stopReplayMode() if self.connectCANEnable==True: # self.connectCANButton.setDisabled(True) self.logViewTableBox1._clearTable() self.logViewTableBox2._clearTable() self.updateCANThread.setup(self.app, self.connectCANEnable, self.test, False, None) else: if self.updateCANThread.isRunning(): # self.connectCANButton.setDisabled(True) self.updateCANThread.stop() self.replayButton.setDisabled(not self.logFileAvailable() or self.connectCANEnable==True) self.connectCANButton.setChecked(self.connectCANEnable==True) @pyqtSlot() def _connectGPS(self): self.connectGPSEnable=self.connectGPSButton.isChecked() if self.connectGPSEnable==True: # self.connectGPSButton.setDisabled(True) self.updateGPSThread.setup(self.connectGPSEnable) else: if self.updateGPSThread.isRunning(): # self.connectGPSButton.setDisabled(True) self.updateGPSThread.stop() self.connectGPSButton.setChecked(self.connectGPSEnable==True) @pyqtSlot() def _enableFilterRingIds(self): self.filterRingIds=self.filterRingIdsButton.isChecked() def connectCANEnabled(self): return self.connectCANEnable def connectCANFailed(self): self.connectCANEnable=False self.connectCANButton.setChecked(False) # self.connectCANButton.setDisabled(False) self.connectCANButton.setIcon(self.ampelRot) def updateStatusBarLabel(self, text): self.statusbar.showMessage(text) logLine=self.log.addLineToLog(text) self.debugLogWidget.addLineToLog(logLine) def stopProgress(self): self.progress.setMinimum(0) self.progress.setMaximum(1) self.progress.reset() def startProgress(self): self.progress.setMinimum(0) self.progress.setMaximum(0) # def connectCANSuccessful(self): # self.connectCANEnable=True ## self.connectCANButton.setChecked(True) ## self.connectCANButton.setDisabled(False) # self.connectCANButton.setIcon(self.ampelGruen) # def stopCANSuccesful(self): # self.connectCANButton.setDisabled(False) # self.connectCANButton.setIcon(self.ampelRot) def canIdIsInKnownList(self, canId): return canId in self.canIdList def updateGPSDisplay(self, gpsData): self.gpsBox.update(gpsData) def showError(self, title, text): msgBox=QMessageBox(QMessageBox.Warning, title, text, QMessageBox.Ok, self) font = self.font() font.setPointSize(14) msgBox.setFont(font) msgBox.exec() def connectGPSFailed(self): self.connectGPSButton.setChecked(False) self.connectGPSEnable=False # self.connectGPSButton.setDisabled(False) self.connectGPSButton.setIcon(self.ampelRot) self.showError("GPS Error", "Error connecing to GPS") # def connectGPSSuccesful(self): ## self.connectGPSButton.setChecked(True) # self.connectGPSEnable=True ## self.connectGPSButton.setDisabled(False) # self.connectGPSButton.setIcon(self.ampelGruen) def connectGPSEnabled(self): return self.connectGPSEnable # def stopGPSSuccesful(self): # self.connectGPSButton.setDisabled(False) # self.connectGPSButton.setIcon(self.ampelRot) def updateCANThreadState(self, state): if state!=self.lastCANState: if state==canIdleState: self.connectCANButton.setIcon(self.ampelGelb) elif state==canRunState: self.connectCANButton.setIcon(self.ampelGruen) elif state==canStoppedState: self.connectCANButton.setIcon(self.ampelRot) self.connectCANEnable=False self.lastCANState=state def updateGPSThreadState(self, state): if state!=self.lastGPSState: if state==gpsRunState: self.connectGPSButton.setIcon(self.ampelGruen) elif state==gpsStoppedState: self.connectGPSButton.setIcon(self.ampelRot) self.connectGPSnable=False self.lastGPSState=state def hasOSMWidget(self): return self.osmWidget!=None
class Ui_Form (QWidget): ''' Ui class. Generated with pyuic4. ''' def __init__ (self, parent=None): QWidget.__init__(self, parent) self.timer = QTimer (self) self.image = QImage (720, 450, QImage.Format_RGB888) self.__engine = REngineThread () self.__model = Model () self.__fsm = DebugStateMachine (self) def wireEngineUp (self): ''' this method connects the REngine's signals. ''' self.connect (self.__engine, SIGNAL ("update (float)"), self.updateImage) self.connect (self.__engine, SIGNAL ("thread_completed()"), self.__fsm.finaliseRender) self.connect (self.__engine, SIGNAL ("inters_created (PyQt_PyObject, PyQt_PyObject)"), self.widget.addIntersection) self.connect (self.__engine, SIGNAL ("vector_created (PyQt_PyObject, PyQt_PyObject, QString)"), self.widget.addArrow) self.connect (self.__engine, SIGNAL ("line_created (PyQt_PyObject, PyQt_PyObject, QString)"), self.widget.addLine) def wireOGLViewerUp (self): ''' this method connects the REngine's signals. ''' self.widget.setModel (self.__model) QObject.connect (self.widget, SIGNAL ("MatrixChanged (PyQt_PyObject)"), self.displayGLMatrix) # call the function run regularly when the focus is on it. (60 FPS if interval = 20) QObject.connect (self.timer, SIGNAL ('timeout()'), self.widget.run) def freezeGLFrameRate (self): self.timer.stop () def speedUpGLFrameRate (self): self.timer.start () self.timer.setInterval (20) def setupUi (self, Form): font = QFont () font.setPointSize (9) font.setBold (False) font.setWeight (50) sizePolicy = QSizePolicy (QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch (0) sizePolicy.setVerticalStretch (0) Form.setObjectName (_fromUtf8("Form")) Form.resize (971, 930) self.plainTextEdit = QPlainTextEdit (Form) self.plainTextEdit.setGeometry (QRect (740, 280, 221, 611)) self.plainTextEdit.setObjectName (_fromUtf8 ("plainTextEdit")) self.plainTextEdit.setFont (font) self.widget = OGLViewer (Form) self.widget.setUi_Form (self) self.widget.setGeometry (QRect (10, 10, 720, 450)) sizePolicy.setHeightForWidth (self.widget.sizePolicy().hasHeightForWidth()) self.widget.setSizePolicy (sizePolicy) self.widget.setObjectName (_fromUtf8 ("widget")) self.wireOGLViewerUp () self.wireEngineUp () self.label_view = QLabel (Form) self.label_view.setGeometry (QRect (10, 470, 720, 450)) sizePolicy.setHeightForWidth (self.label_view.sizePolicy().hasHeightForWidth()) self.label_view.setSizePolicy (sizePolicy) self.label_view.setObjectName (_fromUtf8 ("label_view")) self.initLabel () self.pixmap_item = self.label_view.setPixmap (QPixmap.fromImage (self.image)) # buttons definitions self.renderBtn = QPushButton (Form) self.pauseBtn = QPushButton (Form) self.stopBtn = QPushButton (Form) self.upBtn = QPushButton (Form) self.downBtn = QPushButton (Form) self.moreDownBtn = QPushButton (Form) self.moreUpBtn = QPushButton (Form) self.rightBtn = QPushButton (Form) self.moreRightBtn = QPushButton (Form) self.leftBtn = QPushButton (Form) self.furtherLeft = QPushButton (Form) self.grid_switch = QPushButton (Form) buttons_properties_list = [[self.renderBtn, True, QRect (740, 140, 61, 21), "render"], [self.pauseBtn, False, QRect (740, 120, 61, 21), "pause"], [self.stopBtn, False, QRect (740, 100, 61, 21), "stop"], [self.upBtn, False, QRect (820, 120, 21, 21), "one_row_up"], [self.downBtn, False, QRect (820, 140, 21, 21), "one_row_down"], [self.moreDownBtn, False, QRect (820, 160, 21, 21), "ten_rows_down"], [self.moreUpBtn, False, QRect (820, 100, 21, 21), "ten_rows_up"], [self.rightBtn, False, QRect (780, 180, 21, 21), "one_column_right"], [self.moreRightBtn, False, QRect (800, 180, 21, 21), "ten_columns_right"], [self.leftBtn, False, QRect (760, 180, 21, 21), "one_column_left"], [self.furtherLeft, False, QRect (740, 180, 21, 21), "ten_columns_left"], [self.grid_switch, False, QRect (870, 230, 91, 31), "grid_switch"]] for button in buttons_properties_list: button[0].setEnabled (button[1]) button[0].setGeometry (button[2]) button[0].setFont (font) button[0].setObjectName (_fromUtf8 (button[3])) # other UI elements self.progressBar = QProgressBar (Form) self.progressBar.setGeometry (QRect (740, 901, 221, 20)) self.progressBar.setProperty ("value", 0) self.progressBar.setObjectName (_fromUtf8("progressBar")) self.progressBar.setMinimum (0) self.progressBar.setMaximum (100) self.slider_label = QLabel (Form) self.slider_label.setGeometry (QRect(900, 260, 61, 16)) self.slider_label.setFont(font) self.slider_label.setObjectName (_fromUtf8("slider_label")) self.slider_label.setEnabled (True) self.arrowSizeSlider = QSlider (Form) self.arrowSizeSlider.setGeometry (QRect (740, 258, 151, 22)) self.arrowSizeSlider.setMinimum (2) self.arrowSizeSlider.setMaximum (40) self.arrowSizeSlider.setSingleStep (1) self.arrowSizeSlider.setProperty ("value", 4) self.arrowSizeSlider.setOrientation (Qt.Horizontal) self.arrowSizeSlider.setObjectName (_fromUtf8("arrowSizeSlider")) self.retranslateUi (Form) QMetaObject.connectSlotsByName (Form) def retranslateUi (self, Form): Form.setWindowTitle (_translate ("Form", "RayTracing Debugging Tool", None)) self.renderBtn.setText (_translate ("Form", "Render", None)) self.pauseBtn.setText (_translate ("Form", "Pause", None)) self.stopBtn.setText (_translate ("Form", "Stop", None)) self.upBtn.setText (_translate ("Form", "^", None)) self.downBtn.setText (_translate ("Form", "v", None)) self.moreDownBtn.setText (_translate ("Form", "+", None)) self.moreUpBtn.setText (_translate ("Form", "-", None)) self.rightBtn.setText (_translate ("Form", ">", None)) self.moreRightBtn.setText (_translate ("Form", "+", None)) self.leftBtn.setText (_translate ("Form", "<", None)) self.furtherLeft.setText (_translate ("Form", "-", None)) self.grid_switch.setText (_translate ("Form", "Grid on/off", None)) self.slider_label.setText (_translate ("Form", "Arrows size", None)) self.connect (self.renderBtn, SIGNAL ("clicked()"), self.__fsm.startRendering) self.connect (self.pauseBtn, SIGNAL ("clicked()"), self.__fsm.pauseRendering) self.connect (self.stopBtn, SIGNAL ("clicked()"), self.__fsm.stopRendering) self.connect (self.arrowSizeSlider, SIGNAL ("sliderMoved(int)"), self.resizeArrows) def initLabel (self): color = QColor (250, 250, 250) self.image.fill (color) ''' # test init for i in range (0, 200, 20): for x in range (i, i+20): for y in range (i, i+20): self.image.setPixel (x,y, qRgb (0, 0, 0)) ''' def enableUIButtons (self, boolean_dict): ''' method used by the debug state machine to manage the greyed-out state of buttons. ''' b_dict = dict (boolean_dict) self.renderBtn.setEnabled (b_dict['renderBtn']) self.pauseBtn.setEnabled (b_dict['pauseBtn']) self.stopBtn.setEnabled (b_dict['stopBtn']) self.upBtn.setEnabled (b_dict['upBtn']) self.downBtn.setEnabled (b_dict['downBtn']) self.moreDownBtn.setEnabled (b_dict['moreDownBtn']) self.moreUpBtn.setEnabled (b_dict['moreUpBtn']) self.rightBtn.setEnabled (b_dict['rightBtn']) self.moreRightBtn.setEnabled (b_dict['moreRightBtn']) self.leftBtn.setEnabled (b_dict['leftBtn']) self.furtherLeft.setEnabled (b_dict['furtherLeft']) if b_dict['progressBar'] == 'completed': self.progressBar.setValue (100) elif b_dict['progressBar'] == 'reset': self.progressBar.reset () def addScreenshot (self): ''' it grabs a screenshot of OpenGL viewer and add it into the QImage instance. ''' self.image = self.widget.grabFrameBuffer () self.pixmap_item = self.label_view.setPixmap (QPixmap.fromImage (self.image)) def prepAndStartEngineUp (self): ''' it preps the engine and start it up. ''' self.__engine.setImage (self.image) self.__engine.setCameraNormalMatrix (self.widget.getNormalMatrix(), self.widget.getFovy ()) self.__engine.setModel (self.__model) self.__engine.start () def addCamera (self): self.widget.addCamera () def setIsStoppedFlag (self, boo): self.__engine.setIsStoppedFlag (boo) def setIsPausedFlag (self, boo): self.__engine.setIsPausedFlag (boo) def changeRenderBtnName (self, title): self.renderBtn.setText (_translate ("Form", title, None)) # listeners - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def resizeArrows (self, e): self.widget.changeArrowsSize (e*0.5) def updateImage (self, e): self.pixmap_item = self.label_view.setPixmap (QPixmap.fromImage (self.image)) self.progressBar.setValue (int(100*e)) def displayGLMatrix (self, e): ''' this method is registered to the MatrixChanged event fired from the OGLViewer component. It prints the model matrix. Only for debugging purposes. ''' pass
class dialog_auto_prog(QDialog): #----------------------------------------------------------------------- # DEFINE THE INITIALIZATION FUNCTION. #----------------------------------------------------------------------- def __init__(self, time_strt, time_stop): # Inherit all attributes of an instance of "QDialog". super(dialog_auto_prog, self).__init__() # Make this a non-modal dialog (i.e., allow the user to still # interact with the main application window). self.setModal(False) # Set the title of this dialog window. self.setWindowTitle('Progress') # Give this widget a grid layout, "self.grd". self.grd = QGridLayout() self.grd.setContentsMargins(6, 6, 6, 6) self.setLayout(self.grd) # Initialize the progress bar and set its minimum, maximum, and # initial values. self.bar = QProgressBar() self.bar.setMinimum(calc_time_val(time_strt)) self.bar.setMaximum(calc_time_val(time_stop)) self.bar.setValue(self.bar.minimum()) # Initialize the event button. self.btn_exit = event_PushButton(self, 'exit', 'Close') # Initialize the label. self.lab = QLabel('Note: closing this window will *NOT* ' + 'interrupt the automated analysis.') self.lab.setWordWrap(True) # Row by row, add the bar and buttons to the grid layout. self.grd.addWidget(self.bar, 0, 0, 1, 1) self.grd.addWidget(self.btn_exit, 0, 1, 1, 1) self.grd.addWidget(self.lab, 1, 0, 1, 2) # Display this dialog. self.show() #----------------------------------------------------------------------- # DEFINE THE FUNCTION FOR UPDATING THE PROGRESS BAR. #----------------------------------------------------------------------- def updt_bar(self, time): # Convert this functions argument (i.e., the timestamp of the # current spectrum) to Unix time. time_curr = calc_time_val(time) # If necessary, adjust the minimum or maximum of the progress # bar based on the new timestamp. if (time_curr < self.bar.minimum()): self.bar.setMinimum(time_curr) if (time_curr > self.bar.maximum()): self.bar.setMaximum(time_curr) # Update the value of the progress bar. self.bar.setValue(time_curr) #----------------------------------------------------------------------- # DEFINE THE FUNCTION FOR RESPONDING TO A USER-INITIATED EVENT. #----------------------------------------------------------------------- def user_event(self, event, fnc): # If the close button was pressed, close this dialog. if (fnc == 'exit'): self.close() return