def statusBarTimer(self): q = self.q ret = QTimer(q) ret.setSingleShot(True) ret.setInterval(5000) ret.timeout.connect(q.statusBar().hide) return ret
class ColumnResizer(QObject): def __init__(self): super(ColumnResizer, self).__init__() self._widgets = [] self._gridColumnInfoList = [] self._updateTimer = QTimer(self) self._updateTimer.setSingleShot(True) self._updateTimer.setInterval(0) self._updateTimer.timeout.connect(self._updateWidth) # Public methods def addWidgetsFromLayout(self, layout, column): """ :type layout: QGridLayout :type column: int """ assert column >= 0 if isinstance(layout, QGridLayout): self._addWidgetsFromGridLayout(layout, column) else: print "ColumnResizerResizer does not support layouts of type:", type(layout) def eventFilter(self, obj, event): """ Overrides QObject.eventFilter() """ if event.type() == QEvent.Resize: self._scheduleWidthUpdate() return False # Private methods @Slot() def _updateWidth(self): width = 0 for widget in self._widgets: width = max(widget.sizeHint().width(), width) for info in self._gridColumnInfoList: info[0].setColumnMinimumWidth(info[1], width) def _addWidget(self, widget): self._widgets.append(widget) widget.installEventFilter(self) self._scheduleWidthUpdate() def _addWidgetsFromGridLayout(self, layout, column): for row in range(layout.rowCount()): item = layout.itemAtPosition(row, column) if not item: continue widget = item.widget() if not widget: continue self._addWidget(widget) self._gridColumnInfoList.append([layout, column]) def _scheduleWidthUpdate(self): self._updateTimer.start()
class _SkWindowObject(object): def __init__(self, q, wid=0, pyobj=None): if not pyobj: pyobj = SkWindowPyObject(wid) self.obj = pyobj self.valid = self.obj.valid # Refresh timer self.refreshTimer = QTimer(q) self.refreshTimer.setInterval(200) self.refreshTimer.timeout.connect(q.refresh) self.refreshCount = 0 # int def reset(self): """Reset cached fields""" self.valid = False if hasattr(self, 'geometry'): del self.geometry if hasattr(self, 'visible'): del self.visible if hasattr(self, 'windowState'): del self.windowState if hasattr(self, 'contentSize'): del self.contentSize def updateWindowState(self): self.windowState = ( Qt.WindowFullScreen if self.obj.fullscreen else Qt.WindowMinimized if self.obj.minimized else Qt.WindowNoState)
def __init__(self, process, input_queue, output_queue): super(MainWidget, self).__init__() self.done = False layout = QtGui.QVBoxLayout() logo = QtGui.QLabel() logo.setPixmap('./data/logo.png') logo.setAlignment(Qt.AlignVCenter | Qt.AlignHCenter) layout.addWidget(logo) status_list = self.status_list = QtGui.QListWidget() status_list.addItem('Chowdren, the blazingly fast runtime for ' 'Clickteam Fusion.') status_list.addItem(u'Copyright (c) Mathias K\xe6rlev 2012-2015.') status_list.addItem('Applications made with Chowdren are subject to ' 'the GNU General Public License.') layout.addWidget(status_list) self.setLayout(layout) timer = QTimer(self) timer.setInterval(100) timer.timeout.connect(self.process_console) timer.start() self.process = process self.output_queue = output_queue self.input_queue = input_queue self.log = open('chowdrenlog.txt', 'wb')
class RecomenDesktopApp(TaskTrayApp): def __init__(self, parent=None): super(RecomenDesktopApp, self).__init__(parent) # :: DBへのアップデートチェック self.updateChecker = DBUpdateChecker() self.updateChecker.start() self.updateChecker.finished.connect(self.add_news) # :: DBの新規更新の定期チェック self.updateCheck_timer = QTimer() self.updateCheck_timer.setInterval(10) self.stack = [] @Slot() def add_news(self, news): print "add_news" if not news.hasupdate: return for new in news.get_datas(): if new in self.get_local_db(): print "Non News late" continue self.add_stack(new) print "add stack" def add_stack(self, n): self.stack.append(n) def get_local_db(self): return [2,3,4,5]
class Mlt(QtCore.QThread): s_producer_update = QtCore.Signal(object) s_play = QtCore.Signal(object) s_stop = QtCore.Signal(object) s_seek = QtCore.Signal(object) def __init__(self, parent=None): super(Mlt, self).__init__() self.parent = parent self.consumer = None self.producer = None self.movie_file = None self.profile = None self.position_timer = QTimer() self.position_timer.setInterval(125) self.position_timer.timeout.connect(self.onPositionTimeout) def onPositionTimeout(self): self.s_producer_update.emit(self.producer) def run(self): """ starts thread """ try: self.setup() except RuntimeError, err: print 'ERROR: Mlt.run: starting thread:', err self.quit()
class Panel(QWidget): def __init__(self, parent=None, instr=None, lock=None, title="Instrument Panel"): # This class derivates from a Qt Widget so we have to call # the class builder ".__init__()" QWidget.__init__(self) # "self" is now a Qt Widget, then we load the user interface # generated with QtDesigner and call it self.ui self.ui = Keithley6221_Ui.Ui_Panel() # Now we have to feed the GUI building method of this object (self.ui) # with the current Qt Widget 'self', but the widgets from the design will actually be built as children # of the object self.ui self.ui.setupUi(self) self.setWindowTitle(title) self.reserved_access_to_instr = lock self.instr = instr self.monitor_timer = QTimer() # The timer would not wait for the completion of the task otherwise self.monitor_timer.setSingleShot(True) self.monitor_timer.timeout.connect(self.monitor) self.firsttime = 0 # bug: if the box is checked in the .ui file, the system freezes # if self.ui.monitor.isChecked():self.monitor() def monitor(self, state=1): if state != 1: self.monitor_timer.stop() elif state and not (self.monitor_timer.isActive()): with self.reserved_access_to_instr: I = self.instr.query_current_source_amplitude() Vcomp = self.instr.query_voltage_compliance() outstate = self.instr.query_output_ON() self.ui.I_disp.setText(str(I * 1e6) + u" μA") self.ui.V_disp.setText(str(Vcomp) + " V") self.ui.outputON.setChecked(outstate) self.monitor_timer.start(self.ui.refresh_rate.value() * 1000) def update_timer_timeout(self, secs): # The value must be converted to milliseconds self.monitor_timer.setInterval(secs * 1000) def change_I(self, value=0): with self.reserved_access_to_instr: self.instr.set_current_source_amplitude(value * 1e6) def change_V_comp(self, value=0): with self.reserved_access_to_instr: self.instr.set_voltage_compliance(value) def switch_output(self, value=False): if value: with self.reserved_access_to_instr: self.instr.output_ON() else: with self.reserved_access_to_instr: self.instr.output_OFF() def reset_inst(self): with self.reserved_access_to_instr: self.instr.reset()
class PhotoListModel(QAbstractListModel): URL_ROLE = Qt.UserRole + 1 IMAGE_URL_ROLE = Qt.UserRole + 2 HEIGHT_ROLE = Qt.UserRole + 3 WIDTH_ROLE = Qt.UserRole + 4 def __init__(self, album, parent=None): super(PhotoListModel, self).__init__(parent) self._album = album self._photos = [] self._cache = [] self._done = False keys = {} keys[PhotoListModel.URL_ROLE] = "url" keys[PhotoListModel.IMAGE_URL_ROLE] = "imageUrl" keys[PhotoListModel.HEIGHT_ROLE] = "height" keys[PhotoListModel.WIDTH_ROLE] = "width" self.setRoleNames(keys) self._load = PhotoLoad(self) self._load.start() self._timer = QTimer() self._timer.setInterval(1000) self._timer.timeout.connect(self.loadCache) self._timer.start() def rowCount(self, index): return len(self._photos) def appendCache(self, itens): self._cache += itens def loadCache(self): self.beginInsertRows(QModelIndex(), len(self._photos), len(self._photos) + len(self._cache)) self._photos += self._cache self.endInsertRows() self._cache = [] if self._done: self._timer.stop() def data(self, index, role): if not index.isValid(): return None if index.row() > len(self._photos): return None img = self._photos[index.row()] if role == PhotoListModel.URL_ROLE: return img.url elif role == PhotoListModel.IMAGE_URL_ROLE: return img.imageUrl elif role == PhotoListModel.HEIGHT_ROLE: return img.height elif role == PhotoListModel.WIDTH_ROLE: return img.width else: return None
class Watcher(QObject): fileDeleted = Signal((str,str,)) fileAdded = Signal((str,str,)) fileChanged = Signal((str,str,bool,)) checked = Signal() ioError = Signal((str,)) TOLERANCE = 15 def __init__(self, parent=None): super(Watcher, self).__init__(parent) self.fileAdded.connect(self.added) self.fileChanged.connect(self.changed) self.fileDeleted.connect(self.deleted) @Slot() def checkout(self): raise NotImplementedError @Slot() def startCheckout(self): self.checkTimer = QTimer() self.checkTimer.setInterval(self.interval) self.checkTimer.timeout.connect(self.checkout) self.checkTimer.start() @Slot(str, str) def added(self, location, serverpath): print 'Added {0}: {1}'.format(self.LOCATION, serverpath) @Slot(str, str) def changed(self, location, serverpath): print 'Changed {0}: {1}'.format(self.LOCATION, serverpath) @Slot(str, str) def deleted(self, location, serverpath): print 'Deleted {0}: {1}'.format(self.LOCATION, serverpath) def localFromServer(self, serverpath): # Removing leading '/' so `os.path.join` doesn't treat # `localpath` as an absolute path localpath = serverpath[1:] if serverpath.startswith('/') else serverpath localpath = QDir.toNativeSeparators(localpath) localpath = os.path.join(self.localdir, localpath) return localpath def serverFromLocal(self, localpath): serverpath = localpath.replace(self.localdir, '') serverpath = QDir.fromNativeSeparators(serverpath) return serverpath
def onLoopRequested(loopRequest): print 'l: ', l if l: l.pop() led.toggle(not led.isToggled()) ledTimer = QTimer(toggleObject) ledTimer.setSingleShot(True) ledTimer.setInterval(200) ledTimer.timeout.connect( partial(loopRequest.completeRequest, True if l else False)) ledTimer.start() if not l: l.extend(range(20))
class Reader(QThread): data = Signal(Meter) warning = Signal(str) error = Signal(str) def __init__(self, port): QThread.__init__(self) self._port = port self._serial = None self._parser = Parser() self._cancel = False self._timeout = None def run(self): self._timeout = QTimer() self._timeout.setInterval(2000) self._timeout.timeout.connect(self.__onTimeout) try: self._serial = serial.Serial(self._port, baudrate=19200, bytesize=serial.SEVENBITS, stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_ODD, timeout=1) self._serial.dtr = True self._serial.rts = False while not self._cancel: if not self._timeout.isActive(): self._timeout.start() data = self._serial.readline() data = data.strip() if len(data) == 12: timestamp = time.time() result = self._parser.parse(data, timestamp) if result is not None: self._timeout.stop() self.data.emit(result) else: self.warning.emit('Invalid data received') QApplication.processEvents() self._serial.close() except serial.SerialException as e: self.error.emit(e.message) def __onTimeout(self): self.warning.emit('No data received') def stop(self): self._cancel = True
class _ThreadPoolStatus(object): def __init__(self, q): self.activeThreadCount = 0 self.refreshTimer = QTimer(q) self.refreshTimer.setInterval(500) self.refreshTimer.timeout.connect(self.refresh) self.refreshTimer.start() def refresh(self): value = QThreadPool.globalInstance().activeThreadCount() if self.activeThreadCount != value: self.activeThreadCount = value self.q.threadCountChanged.emit(value)
class MidiMonitorUnit(unit.Sink, unit.Unit): def __init__(self, style='hex', show_time=False, *args, **kwargs): unit.Unit.__init__(self, *args, **kwargs) unit.Sink.__init__(self) self._style = style self._show_time = show_time self.messages = list() self._max_messages = 100 self._client = jackpatch.Client('jackdaw-monitor') self._client.activate() self._sink_type = 'midi' self._sink_port = jackpatch.Port(client=self._client, name='capture', flags=jackpatch.JackPortIsInput) self._timer = QTimer() self._timer.setInterval(0) self._timer.timeout.connect(self.receive) self._timer.start() @property def style(self): return(self._style) @style.setter def style(self, value): if (value != self._style): self._style = value self.on_change() @property def show_time(self): return(self._show_time) @show_time.setter def show_time(self, value): if (value != self._show_time): self._show_time = value self.on_change() def receive(self): message_added = False while (True): result = self._sink_port.receive() if (result is None): break (data, time) = result self.messages.append((data, time)) message_added = True if (message_added): # trim the message list if it gets too long to conserve memory if (len(self.messages) > self._max_messages): self.messages = self.messages[-self._max_messages:] self.on_change() def serialize(self): obj = unit.Unit.serialize(self) obj['style'] = self.style obj['show_time'] = self.show_time return(obj)
class MyGlWidget(QGLWidget): "PySideApp uses Qt library to create an opengl context, listen to keyboard events, and clean up" def __init__(self, renderer, glformat, app): "Creates an OpenGL context and a window, and acquires OpenGL resources" super(MyGlWidget, self).__init__(glformat) self.renderer = renderer self.app = app # Use a timer to rerender as fast as possible self.timer = QTimer(self) self.timer.setSingleShot(True) self.timer.setInterval(0) self.timer.timeout.connect(self.render_vr) # Accept keyboard events self.setFocusPolicy(Qt.StrongFocus) def __enter__(self): "setup for RAII using 'with' keyword" return self def __exit__(self, type_arg, value, traceback): "cleanup for RAII using 'with' keyword" self.dispose_gl() def initializeGL(self): if self.renderer is not None: self.renderer.init_gl() self.timer.start() def paintGL(self): "render scene one time" self.renderer.render_scene() self.swapBuffers() # Seems OK even in single-buffer mode def render_vr(self): self.makeCurrent() self.paintGL() self.doneCurrent() self.timer.start() # render again real soon now def disposeGL(self): if self.renderer is not None: self.makeCurrent() self.renderer.dispose_gl() self.doneCurrent() def keyPressEvent(self, event): "press ESCAPE to quit the application" key = event.key() if key == Qt.Key_Escape: self.app.quit()
class InputHandler(observable.Object): def __init__(self, port, target): observable.Object.__init__(self) # store the source port and the target to send data to self._port = port self._target = target # add an idle timer to check for input self._timer = QTimer() self._timer.setInterval(0) self._timer.timeout.connect(self.receive) self._timer.start() def destroy(self): self._timer.timeout.disconnect(self.receive) self._timer.stop() @property def port(self): return(self._port) @property def target(self): return(self._target) # check for input def receive(self, limit_time=True): # limit processing time to maintain responsiveness time_limit = time.time() + 0.100 # wrap the target in a change block so each midi event doesn't waste a lot # of time causing cascading changes target_and_refs = (self._target,) try: target_and_refs += self._target.model_refs except AttributeError: pass for model in target_and_refs: try: model.begin_change_block() except AttributeError: pass while (True): result = self._port.receive() if (result is None): break (data, msg_time) = result self.handle_message(data, msg_time) # handle at least one message per run, but limit overall processing time # to keep the UI responsive, allowing the jackpatch buffer to handle # the backlog if ((limit_time) and (time.time() > time_limit)): break for model in target_and_refs: try: model.end_change_block() except AttributeError: pass # handle input, reimplement to pass data to the target def handle_message(data, time): pass
def onLoopRequested(loopRequest): print 'l: ', l if l: l.pop() led.toggle(not led.isToggled()) ledTimer = QTimer(toggleObject) ledTimer.setSingleShot(True) ledTimer.setInterval(200) ledTimer.timeout.connect( partial( loopRequest.completeRequest, True if l else False ) ) ledTimer.start() if not l: l.extend(range(20))
class WidgetLed(QWidget): def __init__(self, parent, colour='#000000'): QWidget.__init__(self, parent) self._colour = QColor(colour) self.setMinimumSize(20, 20) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self._lit = False self._timer = QTimer(self) self._timer.setInterval(200) self._timer.timeout.connect(self.__flash_off) def paintEvent(self, event): painter = QPainter() painter.begin(self) colour = self._colour if not self._lit: colour = self._colour.darker(300) painter.setPen(QPen(Qt.black, 1)) painter.setBrush(QBrush(colour)) rect = event.rect() radius = min(rect.width(), rect.height()) / 3 painter.drawEllipse(rect.center(), radius, radius) painter.end() def __flash_off(self): self._timer.stop() self._lit = False self.repaint() def flash(self): self._lit = True self._timer.start() self.repaint() def light(self, on): self._timer.stop() self._lit = on self.repaint() def set_colour(self, colour): self._colour = QColor(colour)
class WalletController(QObject): onError = Signal(unicode) onConnected = Signal(bool) onTxSent = Signal(bool) onBusy = Signal() onDoubleEncrypted = Signal() onBalance = Signal() onWalletUnlocked = Signal() onCurrentBalance = Signal() onCurrentLabel = Signal() onCurrentAddress = Signal() onCurrentDoubleEncrypted = Signal() onCurrentPassKey = Signal() onCurrentWatchOnly = Signal() def __init__(self,): QObject.__init__(self,) self.thread = None self._balance = '<b>0.00</b>000000' self._wallet = Wallet() self._walletUnlocked = False self.settings = Settings() self.addressesModel = AddressesModel() self.transactionsModel = TransactionsModel() self.timer = QTimer(self) self.timer.setInterval(900000) # 15 min update self.timer.timeout.connect(self.update) self.timer.start() if self.settings.storePassKey: self._currentPassKey = self.settings.passKey try: self.unlockWallet(self._currentPassKey) except: self.onError.emit('Stored pass phrase is invalid') else: self._currentPassKey = None self._currentAddressIndex = 0 @Slot(unicode) def newAddr(self, doubleKey): try: self._wallet.createAddr(doubleKey) self.storeWallet() self.update() except (WrongPassword, DataError), err: self.onError.emit(unicode(err))
class _VideoComponentEditor(_LaserComponentEditor): """ """ playTimer = Any fps = Int stop_timer = Event def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ super(_VideoComponentEditor, self).init(parent) self.playTimer = QTimer(self.control) # self.playTimer.timeout.connect(self.update) self.control.connect(self.playTimer, SIGNAL('timeout()'), self.update) if self.value.fps: self.playTimer.setInterval(1000 / float(self.value.fps)) self.playTimer.start() self.value.on_trait_change(self.stop, 'closed_event') self.value.on_trait_change(self._update_fps, 'fps') self.sync_value('stop_timer', 'stop_timer', mode='from') def _update_fps(self): if self.value.fps: self.playTimer.setInterval(1000 / float(self.value.fps)) def stop(self): print 'VideoComponentEditor stop' try: self.playTimer.stop() except RuntimeError: pass def update(self): if self.control: # invoke_in_main_thread(self.value.request_redraw) self.value.request_redraw() def _stop_timer_fired(self): print 'VideoComponentEditor stopping playTimer' self.playTimer.stop()
class demo(QApplication): "Simple application for testing OpenGL rendering" def __init__(self, number=1): QApplication.__init__(self, sys.argv) self.setApplicationName("SphereTest") self.mainWindow = QMainWindow() self.gl_widget = proPixx480_1440test() self.mainWindow.setCentralWidget(self.gl_widget) self.mainWindow.setGeometry( QtGui.QDesktopWidget().availableGeometry(1)) self.mainWindow.showFullScreen() self.curr_time = time.time() self.timer = QTimer() self.timer.setInterval(0) self.timer.timeout.connect(self.gl_widget.update) self.timer.start() self.timer2 = QTimer() self.timer2.setInterval(3000) self.timer2.timeout.connect(self.printFrames) self.timer2.start() self.gl_widget.mode = number self.gl_widget.mouseDoubleClickEvent = lambda x: self.mainWindow.close( ) self.previous_time = 0 self.previous_total = 0 my_device = PROPixx() if number is 0: # 480 Hz my_device.setDlpSequencerProgram('QUAD4X') else: # 1440 Hz my_device.setDlpSequencerProgram('QUAD12X') my_device.updateRegisterCache() sys.exit(self.exec_()) # Start Qt main loop def printFrames(self): time_ela = self.gl_widget.time - self.curr_time new_time = time_ela - self.previous_time self.previous_time = time_ela new_frames = self.gl_widget.frame_number - self.previous_total self.previous_total = self.gl_widget.frame_number print "There have been %d frames in %f seconds, so %f FPS" % ( new_frames, new_time, new_frames / float(new_time))
class Render(QWebView): def __init__(self, url, filename, image_crop, translate_page, parent=None): super(Render, self).__init__(parent) self.image_crop = image_crop self.fileName = time.strftime("%Y%m%d%H%M%S", time.localtime()) + "_test.jpg" self.finished = False # Settings s = self.page().settings() s.setAttribute(QWebSettings.AutoLoadImages, True) s.setAttribute(QWebSettings.PluginsEnabled, True) s.setAttribute(QWebSettings.JavascriptEnabled, True) s.setAttribute(QWebSettings.JavaEnabled, False) s.setAttribute(QWebSettings.JavascriptCanOpenWindows, False) s.setAttribute(QWebSettings.DeveloperExtrasEnabled, True) #self.page().mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.page().mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self.timerScreen = QTimer() self.timerScreen.setInterval(10000) self.timerScreen.setSingleShot(True) self.timerScreen.timeout.connect(self.takeScreenshot) self.loadFinished.connect(self.timerScreen.start) self.load(QUrl(url)) @Slot(QNetworkReply) def takeScreenshot(self): [x, y, width, height] = self.image_crop frame = self.page().mainFrame() size = frame.contentsSize() size.setWidth(1000) size.setHeight(2000) self.page().setViewportSize(size) image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) painter = QPainter(image) frame.render(painter) painter.end() image1 = image.copy(x, y, width, height) image1.save(self.fileName) self.finished = True
class _VideoComponentEditor(_LaserComponentEditor): """ """ playTimer = Any fps = Int stop_timer = Event def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ super(_VideoComponentEditor, self).init(parent) self.playTimer = QTimer(self.control) self.playTimer.timeout.connect(self.update) if self.value.fps: self.playTimer.setInterval(1000 / self.value.fps) self.playTimer.start() self.value.on_trait_change(self.stop, "closed_event") self.value.on_trait_change(self._update_fps, "fps") self.sync_value("stop_timer", "stop_timer", mode="both") def _update_fps(self): if self.value.fps: self.playTimer.setInterval(1000 / self.value.fps) def stop(self): try: self.playTimer.stop() except RuntimeError: del self.playTimer def update(self): if self.control: self.value.draw_valid = False self.control.repaint() def _stop_timer_fired(self): print "VideoComponentEditor stopping playTimer" self.playTimer.stop()
class WidgetLed(QWidget): def __init__(self, parent, colour='#000000'): QWidget.__init__(self, parent) self._colour = QColor(colour) self.setMinimumSize(10, 10) self._lit = False self._timer = QTimer(self) self._timer.setInterval(200) self._timer.timeout.connect(self.__flashOff) def paintEvent(self, event): painter = QPainter() painter.begin(self) if self._lit: self._colour.setAlphaF(1) else: self._colour.setAlphaF(.25) painter.setPen(QPen(self._colour, 1)) painter.setBrush(QBrush(self._colour)) rect = event.rect() radius = min(rect.width(), rect.height()) / 3 painter.drawEllipse(rect.center(), radius, radius) painter.end() def __flashOff(self): self._timer.stop() self._lit = False self.repaint() def flash(self): self._lit = True self._timer.start() self.repaint() def light(self, on): self._timer.stop() self._lit = on self.repaint()
class _CameraEditor(Editor): timer = Instance(QTimer) swap = False def init(self, parent): self.control = self._create_control(parent) def update_editor(self): self._setup_loop() def dispose(self): self.timer.stop() def _setup_loop(self): self.timer = QTimer(self.control) self.timer.timeout.connect(self._update) if self.factory.fps: self.timer.setInterval(1000 / self.factory.fps) self.timer.start() def _update(self): # w, h = self.control.width(), self.control.height() # img = self.value.get_image_data(size=(w, h)) img = self.value.get_image_data() if img is not None: s = img.shape if s: im = QImage(img, s[1], s[0], QImage.Format_RGB32) # im = QImage(img, s[1], s[0], QImage.Format_RGB16) if self.swap: im = QImage.rgbSwapped(im) pix = QPixmap.fromImage(im) self.control.setPixmap(pix) def _create_control(self, parent): label = QLabel() width, height = self.item.width, self.item.height if self.item.width != -1.0: label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) label.setFixedWidth(abs(width)) label.setFixedHeight(abs(height)) return label
class Render(QWebView): def __init__(self, url, filename, image_crop, translate_page, parent=None): super(Render, self).__init__(parent) self.image_crop = image_crop self.fileName = time.strftime("%Y%m%d%H%M%S",time.localtime()) +"_test.jpg" self.finished = False # Settings s = self.page().settings() s.setAttribute(QWebSettings.AutoLoadImages, True) s.setAttribute(QWebSettings.PluginsEnabled, True) s.setAttribute(QWebSettings.JavascriptEnabled, True) s.setAttribute(QWebSettings.JavaEnabled, False) s.setAttribute(QWebSettings.JavascriptCanOpenWindows, False) s.setAttribute(QWebSettings.DeveloperExtrasEnabled, True) #self.page().mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.page().mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self.timerScreen = QTimer() self.timerScreen.setInterval(10000) self.timerScreen.setSingleShot(True) self.timerScreen.timeout.connect(self.takeScreenshot) self.loadFinished.connect(self.timerScreen.start) self.load(QUrl(url)) @Slot(QNetworkReply) def takeScreenshot(self): [x,y,width,height] = self.image_crop frame = self.page().mainFrame() size = frame.contentsSize() size.setWidth(1000) size.setHeight(2000) self.page().setViewportSize(size) image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) painter = QPainter(image) frame.render(painter) painter.end() image1 = image.copy(x,y,width,height) image1.save(self.fileName) self.finished = True
def _create_timer(self, interval, single_shot, handler): timer = QTimer() timer.setInterval(1000 * interval) timer.setSingleShot(single_shot) self._timers.add(timer) wref = weakref.ref(timer) def callback(): timer = wref() if single_shot and timer: timer.stop() self._timers.discard(timer) self._processor.submit(handler) timer.timeout.connect(callback) def cancel(): timer = wref() if timer: timer.stop() self._timers.discard(timer) handler.cancel_callback = cancel timer.start() return timer
class QtOneSecondTimer(OneSecondTimer): """ Concrete implementation of the timer based on Qt classes """ def __init__(self): OneSecondTimer.__init__(self) self.__timer = QTimer() self.__timer.setInterval(1000) self.__timer.setSingleShot(False) self.__timer.timeout.connect(self._timerElapsed) def start(self): """Start the timer""" self.__timer.start() def _timerElapsed(self): """Process notification from the timer""" self.elapsed.fire() def stop(self): """Stop the timer""" self.__timer.stop()
class MainWindow(QWidget): def __init__(self, grid, U): assert isinstance(U, Communicable) super(MainWindow, self).__init__() U = U.data layout = QVBoxLayout() plotBox = QHBoxLayout() plot = GlumpyPatchWidget(self, grid, vmin=np.min(U), vmax=np.max(U), bounding_box=bounding_box, codim=codim) bar = ColorBarWidget(self, vmin=np.min(U), vmax=np.max(U)) plotBox.addWidget(plot) plotBox.addWidget(bar) layout.addLayout(plotBox) if len(U) == 1: plot.set(U.ravel()) else: plot.set(U[0]) hlayout = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(len(U) - 1) self.slider.setTickPosition(QSlider.TicksBelow) hlayout.addWidget(self.slider) lcd = QLCDNumber(m.ceil(m.log10(len(U)))) lcd.setDecMode() lcd.setSegmentStyle(QLCDNumber.Flat) hlayout.addWidget(lcd) layout.addLayout(hlayout) hlayout = QHBoxLayout() toolbar = QToolBar() self.a_play = QAction(self.style().standardIcon(QStyle.SP_MediaPlay), 'Play', self) self.a_play.setCheckable(True) self.a_rewind = QAction(self.style().standardIcon(QStyle.SP_MediaSeekBackward), 'Rewind', self) self.a_toend = QAction(self.style().standardIcon(QStyle.SP_MediaSeekForward), 'End', self) self.a_step_backward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipBackward), 'Step Back', self) self.a_step_forward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipForward), 'Step', self) self.a_loop = QAction(self.style().standardIcon(QStyle.SP_BrowserReload), 'Loop', self) self.a_loop.setCheckable(True) toolbar.addAction(self.a_play) toolbar.addAction(self.a_rewind) toolbar.addAction(self.a_toend) toolbar.addAction(self.a_step_backward) toolbar.addAction(self.a_step_forward) toolbar.addAction(self.a_loop) hlayout.addWidget(toolbar) self.speed = QSlider(Qt.Horizontal) self.speed.setMinimum(0) self.speed.setMaximum(100) hlayout.addWidget(QLabel('Speed:')) hlayout.addWidget(self.speed) layout.addLayout(hlayout) self.timer = QTimer() self.timer.timeout.connect(self.update_solution) self.slider.valueChanged.connect(self.slider_changed) self.slider.valueChanged.connect(lcd.display) self.speed.valueChanged.connect(self.speed_changed) self.a_play.toggled.connect(self.toggle_play) self.a_rewind.triggered.connect(self.rewind) self.a_toend.triggered.connect(self.to_end) self.a_step_forward.triggered.connect(self.step_forward) self.a_step_backward.triggered.connect(self.step_backward) self.speed.setValue(50) self.setLayout(layout) self.plot = plot self.U = U def slider_changed(self, ind): self.plot.set(self.U[ind]) def speed_changed(self, val): self.timer.setInterval(val * 20) def update_solution(self): ind = self.slider.value() + 1 if ind >= len(self.U): if self.a_loop.isChecked(): ind = 0 else: self.a_play.setChecked(False) return self.slider.setValue(ind) def toggle_play(self, checked): if checked: if self.slider.value() + 1 == len(self.U): self.slider.setValue(0) self.timer.start() else: self.timer.stop() def rewind(self): self.slider.setValue(0) def to_end(self): self.a_play.setChecked(False) self.slider.setValue(len(self.U) - 1) def step_forward(self): self.a_play.setChecked(False) ind = self.slider.value() + 1 if ind == len(self.U) and self.a_loop.isChecked(): ind = 0 if ind < len(self.U): self.slider.setValue(ind) def step_backward(self): self.a_play.setChecked(False) ind = self.slider.value() - 1 if ind == -1 and self.a_loop.isChecked(): ind = len(self.U) - 1 if ind >= 0: self.slider.setValue(ind)
class Loader(QMainWindow): def __init__(self, parent=None): super(Loader, self).__init__(parent) self.initUI() def updateDeviceList(self): self.statusBar().showMessage("Device list updating...", timeout=STATUS_BAR_TIMEOUT) self.deviceListWidget.updateList() self.statusBar().showMessage("Device list updated finished!", timeout=STATUS_BAR_TIMEOUT) def getFileName(self, ext): fname = QFileDialog.getOpenFileName(self, 'Open file', '/home') # if fname[0]: # f = open(fname[0], 'r') # with f: # data = f.read() # self.textEdit.setText(data) def initUI(self): # textEdit = QTextEdit() # self.setCentralWidget(textEdit) # self.setStyleSheet("QGroupBox { border: 1px solid gray; padding: 5px;}"); # Action to quit program exitAction = QAction(QIcon(None), 'Quit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) # # Action to update device list # self.refreshAction = QAction(QIcon('img/reload.png'), 'Refresh', self) # self.refreshAction.setShortcut('F5') # self.refreshAction.setStatusTip('Refresh list of connected devices.') # self.refreshAction.triggered.connect(self.updateDeviceList) # Action to show program information helpAction = QAction(QIcon(None), 'Help', self) helpAction.setShortcut('F1') helpAction.triggered.connect(self.showHelpDialog) # Action to help aboutAction = QAction(QIcon(None), 'About', self) aboutAction.triggered.connect(self.showAboutDialog) self.statusBar() # Add the file menu menubar = self.menuBar() fileMenu = menubar.addMenu('&File') # fileMenu.addAction(self.refreshAction) fileMenu.addAction(exitAction) fileMenu = menubar.addMenu('&Help') fileMenu.addAction(helpAction) fileMenu.addAction(aboutAction) # # Add the toolbar # toolbar = self.addToolBar('Exit') # # toolbar.addAction(self.refreshAction) # toolbar.setMovable(False) # Add the main windows widgets self.deviceListWidget = DeviceList(self.programDeviceHandler, self.infoDeviceHandler, self.resetDeviceHandler) self.fileSelectorWidget = FileSelector() self.setStyleSheet(""" QStatusBar { border-top: 1px solid #CCC; } QToolBar { border-top: 1px solid #DDD; border-bottom: 1px solid #CCC; } """) gbox = QGroupBox("Connected USB devices:") gboxLayout = QVBoxLayout() gboxLayout.addWidget(self.deviceListWidget) gbox.setLayout(gboxLayout) self.refreshEvent = QTimer() self.refreshEvent.setInterval(1250) self.refreshEvent.timeout.connect(self.USBUpdate) self.refreshEvent.start() layout = QVBoxLayout() layout.addWidget(self.fileSelectorWidget) layout.addWidget(gbox) self.setCentralWidget(QWidget()) self.centralWidget().setLayout(layout) self.setMinimumSize(620, 700) self.setMaximumWidth(620) self.setWindowFlags(Qt.Window | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) self.setGeometry(300, 300, 350, 250) self.setWindowTitle('keyplus layout and firmware loader') self.show() def abort_update(self, target_device): try: target_device.close() except: pass self.deviceListWidget.updateList() def abort_update2(self): self.deviceListWidget.updateList() @Slot(str) def programDeviceHandler(self, device_path): target_device = self.tryOpenDevicePath(device_path) if target_device == None: self.abort_update(target_device) return programmingMode = self.fileSelectorWidget.getProgramingInfo() if is_bootloader_device( target_device ) and programmingMode != FileSelector.ScopeFirmware: error_msg_box("The device's bootloader is running. " "Choose 'Update Firmware' from the drop down box " "to flash new firmware, or reset it to use to run " "the currently loaded firmware (if any).") self.abort_update(target_device) return if programmingMode == FileSelector.ScopeLayout: target_device.close() kb = self.tryOpenDevicePath2(device_path) if kb == None: return self.statusBar().showMessage("Started updating layout", timeout=STATUS_BAR_TIMEOUT) layout_file = self.fileSelectorWidget.getLayoutFile() if layout_file == '': error_msg_box("No layout file given.") return try: kp_layout = KeyplusLayout() warnings = [] kp_layout.from_yaml_file(layout_file, warnings=warnings) device_target = kb.get_device_target() settings_data = kp_layout.build_settings_section(device_target) layout_data = kp_layout.build_layout_section(device_target) except (KeyplusError, IOError) as err: error_msg_box(str(err)) return print('#' * 80) print("settings_data:", type(settings_data), settings_data) print('#' * 80) print("layout_data:", type(layout_data), layout_data) print('#' * 80) hexdump.hexdump(bytes(settings_data)) hexdump.hexdump(bytes(layout_data)) with kb: old_name = copy.copy(kb.name) kb.update_settings_section(settings_data, keep_rf=True) kb.update_layout_section(layout_data) if old_name != kb.name: kb.reset(reset_type=RESET_TYPE_HARDWARE) needs_label_update = True else: kb.reset(reset_type=RESET_TYPE_SOFTWARE) needs_label_update = False if needs_label_update: for widget in self.deviceListWidget.deviceWidgets: try: widget.updateLabel() except easyhid.HIDException: pass if warnings != []: error_msg_box( "The device was programmed successfully, but some " "non-critical errors were encountered:\n" + "\n".join([str(warn) for warn in warnings]), title="Warnings", ) self.statusBar().showMessage("Finished updating layout", timeout=STATUS_BAR_TIMEOUT) elif programmingMode == FileSelector.ScopeDevice: target_device.close() kb = self.tryOpenDevicePath2(device_path) if kb == None: return layout_file = self.fileSelectorWidget.getRFLayoutFile() rf_file = self.fileSelectorWidget.getRFFile() target_id = self.fileSelectorWidget.getTargetID() self.statusBar().showMessage("Started updating RF settings", timeout=STATUS_BAR_TIMEOUT) if layout_file == '': error_msg_box("No layout file given.") self.abort_update(target_device) return elif rf_file == '': error_msg_box("No RF settings file given.") self.abort_update(target_device) return elif target_id == None: error_msg_box("No device id file given.") self.abort_update(target_device) return try: kp_layout = KeyplusLayout() warnings = [] kp_layout.from_yaml_file(layout_file, rf_file, warnings=warnings) device_target = kb.get_device_target() device_target.device_id = target_id settings_data = kp_layout.build_settings_section(device_target) layout_data = kp_layout.build_layout_section(device_target) except (KeyplusError, IOError) as err: error_msg_box(str(err)) self.abort_update(target_device) return with kb: old_name = copy.copy(kb.name) kb.update_settings_section(settings_data, keep_rf=False) kb.update_layout_section(layout_data) if old_name != kb.name: kb.reset(reset_type=RESET_TYPE_HARDWARE) needs_label_update = True else: kb.reset(reset_type=RESET_TYPE_SOFTWARE) needs_label_update = False if needs_label_update: for widget in self.deviceListWidget.deviceWidgets: try: widget.updateLabel() except easyhid.HIDException: pass if warnings != []: error_msg_box( "The device was programmed successfully, but some " "non-critical errors were encountered:\n" + "\n".join([str(warn) for warn in warnings]), title="Warnings", ) self.statusBar().showMessage("Finished updating RF settings", timeout=STATUS_BAR_TIMEOUT) elif programmingMode == FileSelector.ScopeFirmware: fw_file = self.fileSelectorWidget.getFirmwareFile() self.statusBar().showMessage("Starting update firmware", timeout=STATUS_BAR_TIMEOUT) if fw_file == '': error_msg_box("No firmware file given.") else: if is_xusb_bootloader_device(target_device): self.program_xusb_boot_firmware_hex(target_device, fw_file) elif is_kp_boot_device(target_device): self.program_kp_boot_32u4_firmware_hex( target_device, fw_file) elif is_keyplus_device(target_device): try: serial_num = target_device.serial_number boot_vid, boot_pid = protocol.enter_bootloader( target_device) self.bootloaderProgramTimer = QTimer() self.bootloaderProgramTimer.setInterval(3000) self.bootloaderProgramTimer.setSingleShot(True) self.bootloaderProgramTimer.timeout.connect( lambda: self.programFirmwareHex( boot_vid, boot_pid, serial_num, fw_file)) self.bootloaderProgramTimer.start() except (easyhid.HIDException, protocol.KBProtocolException): error_msg_box( "Programming hex file failed: '{}'".format( fw_file)) else: error_msg_box("This bootloader is currently unsupported") else: try: target_device.close() except: pass raise Exception("Unimplementend programming mode") def programFirmwareHex(self, boot_vid, boot_pid, serial_num, file_name): device = None for i in range(1): en = easyhid.Enumeration(vid=boot_vid, pid=boot_pid).find() # Look for devices with matching serial_num number for dev in en: if dev.serial_number == serial_num: device = dev break # if a device was found with matching vid:pid, but it doesn't have # a matching serial_num number, then assume that the bootloader/firmware # doesn't set the serial_num number to the same value, so just program # the first matching device if len(en) != 0: device = en[0] break if device == None: error_msg_box("Couldn't connect to the device's bootloader") return else: if self.tryOpenDevice(device): return self.program_xusb_boot_firmware_hex(device, file_name) self.statusBar().showMessage("Finished updating firmware", timeout=STATUS_BAR_TIMEOUT) def program_xusb_boot_firmware_hex(self, device, file_name): try: xusbboot.write_hexfile(device, file_name) except xusbboot.BootloaderException as err: error_msg_box("Error programming the bootloader to hex file: " + str(err)) finally: device.close() def program_kp_boot_32u4_firmware_hex(self, device, file_name): try: device.close() boot_dev = kp_boot_32u4.BootloaderDevice(device) with boot_dev: boot_dev.write_flash_hex(file_name) boot_dev.reset_mcu() except Exception as err: error_msg_box("Error programming the bootloader to hex file: " + str(err)) def tryOpenDevicePath2(self, device_path): try: print(device_path) device = easyhid.Enumeration().find(path=device_path)[0] return KeyplusKeyboard(device) except Exception as err: msg_box( description="Failed to open device! Check it is still present " "and you have permission to write to it. ErrorMsg: {}".format( err), title="USB Device write error") traceback.print_exc(file=sys.stderr) return None def tryOpenDevicePath(self, device_path): try: device = easyhid.Enumeration().find(path=device_path)[0] device.open() return device except: msg_box( description="Failed to open device! Check it is still present " "and you have permission to write to it.", title="USB Device write error") return None def tryOpenDevice(self, device): try: device.open() return False except: msg_box( description="Failed to open device! Check it is still present " "and you have permission to write to it.", title="USB Device write error") return True @Slot(str) def resetDeviceHandler(self, device_path): device = self.tryOpenDevicePath(device_path) if device == None: return if is_keyplus_device(device): protocol.reset_device(device) elif is_xusb_bootloader_device(device): xusbboot.reset(device) elif is_kp_boot_device(device): device.close() dev = kp_boot_32u4.BootloaderDevice(device) with dev: dev.reset_mcu() elif is_nrf24lu1p_bootloader_device(device): print("TODO: reset: ", device_path, file=sys.stderr) else: print("Can't reset device: ", device_path, file=sys.stderr) @Slot(str) def infoDeviceHandler(self, device_path): device = self.tryOpenDevicePath(device_path) if device == None: return settingsInfo = protocol.get_device_info(device) firmwareInfo = protocol.get_firmware_info(device) rfInfo = protocol.get_rf_info(device) if firmwareInfo.has_at_least_version('0.2.2'): errorInfo = protocol.get_error_info(device) else: errorInfo = None device.close() def ms_str(x): return "{}ms".format(x) def us_str(x): return "{0:.1f}µs".format(x / 255 * 48.0) header = ["Attribute", "Value"] device_settings = [ ("Device ID", settingsInfo.id), ("Device name", settingsInfo.device_name_str()), ("Device serial number", device.serial_number), ("Last layout update", settingsInfo.timestamp_str()), ("Default report mode", settingsInfo.default_report_mode_str()), ("Matrix scan mode", settingsInfo.scan_mode_str()), ("Matrix columns", settingsInfo.col_count), ("Matrix rows", settingsInfo.row_count), ("Key debounce press time", ms_str(settingsInfo.debounce_time_press)), ("Key debounce release time", ms_str(settingsInfo.debounce_time_release)), ("Key press trigger time", ms_str(settingsInfo.trigger_time_press)), ("Key release trigger time", ms_str(settingsInfo.trigger_time_release)), ("Key discharge idle time", us_str(settingsInfo.parasitic_discharge_delay_idle)), ("Key discharge debouncing time", us_str(settingsInfo.parasitic_discharge_delay_debouncing)), ("Settings stored CRC", hex(settingsInfo.crc)), ("Settings computed CRC", hex(settingsInfo.computed_crc)), ("USB", (settingsInfo.has_usb() and firmwareInfo.has_fw_support_usb())), ("I2C", (settingsInfo.has_i2c() and firmwareInfo.has_fw_support_i2c())), ("nRF24 wireless", (settingsInfo.has_nrf24() and firmwareInfo.has_fw_support_nrf24())), ("Unifying mouse", (settingsInfo.has_unifying_mouse() and firmwareInfo.has_fw_support_unifying())), ("Bluetooth", (settingsInfo.has_bluetooth() and firmwareInfo.has_fw_support_bluetooth())), ("RF pipe0", binascii.hexlify(rfInfo.pipe0).decode('ascii')), ("RF pipe1", binascii.hexlify(rfInfo.pipe1).decode('ascii')), ("RF pipe2", "{:02x}".format(rfInfo.pipe2)), ("RF pipe3", "{:02x}".format(rfInfo.pipe3)), ("RF pipe4", "{:02x}".format(rfInfo.pipe4)), ("RF pipe5", "{:02x}".format(rfInfo.pipe5)), ("RF channel", str(rfInfo.channel)), ("RF auto retransmit count", str(rfInfo.arc)), ("RF data rate", protocol.data_rate_to_str(rfInfo.data_rate)), ] firmware_settings = [ ("Firmware version", "{}.{}.{}".format(firmwareInfo.version_major, firmwareInfo.version_minor, firmwareInfo.version_patch)), ("Firmware build date", str(datetime.datetime.fromtimestamp(firmwareInfo.timestamp))), ("Firmware git hash", "{:08x}".format(firmwareInfo.git_hash)), ("Microcontroller", chip_id.get_chip_name_from_id(firmwareInfo.chip_id)), ("Board ID", hex(firmwareInfo.board_id)), ("Internal scan method", firmwareInfo.get_interal_scan_method_as_str()), ("Layout storage size", firmwareInfo.layout_flash_size), ("Bootloader VID", "{:04x}".format(firmwareInfo.bootloader_vid)), ("Bootloader PID", "{:04x}".format(firmwareInfo.bootloader_pid)), ("Support scanning", firmwareInfo.has_fw_support_scanning()), ("Support scanning col to row", firmwareInfo.has_fw_support_scanning_col_row()), ("Support scanning row to col", firmwareInfo.has_fw_support_scanning_row_col()), ("Media keys", firmwareInfo.has_fw_support_key_media()), ("Mouse keys", firmwareInfo.has_fw_support_key_mouse()), ("Layer keys", firmwareInfo.has_fw_support_key_layers()), ("Sticky keys", firmwareInfo.has_fw_support_key_sticky()), ("Tap keys", firmwareInfo.has_fw_support_key_tap()), ("Hold keys", firmwareInfo.has_fw_support_key_hold()), ("Support 6KRO", firmwareInfo.has_fw_support_6kro()), ("Support NKRO", firmwareInfo.has_fw_support_key_hold()), ("Support indicator LEDs", firmwareInfo.has_fw_support_led_indicators()), ("Support LED backlighting", firmwareInfo.has_fw_support_led_backlighting()), ("Support ws2812 LEDs", firmwareInfo.has_fw_support_led_ws2812()), ("Support USB", firmwareInfo.has_fw_support_usb()), ("Support nRF24 wireless", firmwareInfo.has_fw_support_nrf24()), ("Support Unifying", firmwareInfo.has_fw_support_unifying()), ("Support I2C", firmwareInfo.has_fw_support_i2c()), ("Support Bluetooth", firmwareInfo.has_fw_support_bluetooth()), ] if errorInfo: error_codes = [] for code in errorInfo.get_error_codes(): error_codes.append((errorInfo.error_code_to_name(code), code)) else: error_codes = [ ('Error codes require firmware version 0.2.2 or greater', ) ] self.info_window = DeviceInformationWindow( self, header, device_settings, firmware_settings, error_codes, ) self.info_window.exec_() self.deviceListWidget.updateList() def USBUpdate(self): self.deviceListWidget.updateList() def showAboutDialog(self): QMessageBox.about(self, "About keyplus Loader", """ The keyplus layout and firmware loader. """) def showHelpDialog(self): QMessageBox.about( self, "keyplus Loader Help", """ This is the layout and firmware loader for the keyplus keyboard firmware. The layout files are *.yaml files. For documentation and examples see here: TODO The rf files are *.yaml files. For documentation and examples see here: TODO The firmware loader accepts *.hex files. For the latest keyplus firmware see here: TODO """)
class Sync(QObject): deleteServerFile = Signal((str, )) deleteLocalFile = Signal((str, )) downloadFile = Signal((str, )) uploadFile = Signal((str, )) checkServer = Signal() checkLocal = Signal() statusChanged = Signal((str, )) def __init__(self, host, ssl, parent=None): super(Sync, self).__init__(parent) self.server = ServerWatcher(host, ssl, self) self.preloaedActions = [] self.doPreemptive = empty_db() self.connected = False self.firstScan = True def setLocalDir(self, localdir): if not os.path.exists(localdir): # Creates the directory if it doesn't already exists. os.makedirs(localdir) self.local = LocalWatcher(localdir) self.server.setLocalDir(localdir) self.local.moveToThread(self.thread()) self.local.setParent(self) def connections(self): if not self.connected: self.connected = True self.server.fileAdded.connect(self.onAdded) self.server.fileChanged.connect(self.onChanged) self.server.fileDeleted.connect(self.onDeleted) self.local.fileAdded.connect(self.onAdded) self.local.fileChanged.connect(self.onChanged) self.local.fileDeleted.connect(self.onDeleted) self.deleteLocalFile.connect(self.local.deleteFile) self.deleteServerFile.connect(self.server.onDelete) self.downloadFile.connect(self.server.onDownload) self.uploadFile.connect(self.server.onUpload) @Slot() def initQueue(self): self.actionQueue = ActionQueue() self.actionTimer = QTimer() self.actionTimer.setInterval(1) self.actionTimer.timeout.connect(self.takeAction) self.actionTimer.start() @Slot() def takeAction(self): self.actionTimer.stop() if self.doPreemptive: # Preemptive check is a bit of a workaround to deal with # initial unexpected conditions: database file is gone self.doPreemptive = False self.server.preemptiveCheck = True self.local.fileAdded.connect(self.server.added) self.local.checkout() self.server.checkout() self.local.fileAdded.disconnect(self.server.added) self.server.preemptiveCheck = False for action in self.server.preemptiveActions: self.actionQueue.add(action) # After preemptive check, it is safe to do the connections # for normal operations self.connections() serverActionCount = 0 localActionCount = 0 for action in self.actionQueue: if action is not None: print 'Next action: %s' % action path = action.path do = action.action location = action.location if location == FileAction.LOCAL and (do == FileAction.UPLOAD \ or do == FileAction.DELETE): if not engine_tools.file_exists_local(path): # File no longer exists at the time of processing. # Maybe it was temporary or a quick rename. # So we ignore it print "Ignored action on " + path + ": File doesn't exist on local." continue if do == FileAction.UPLOAD: self.uploadFile.emit(path) localActionCount += 1 elif do == FileAction.DOWNLOAD: self.downloadFile.emit(path) serverActionCount += 1 elif do == FileAction.DELETE: with File.fromPath(path) as deleted_file: # `action.location` attribute only makes sense when deciding # whether to delete a file on the server or local. if location == FileAction.LOCAL: localpath = self.local.localFromServer(path) self.deleteLocalFile.emit(localpath) deleted_file.inlocal = False localActionCount += 1 elif location == FileAction.SERVER: self.deleteServerFile.emit(path) deleted_file.inserver = False serverActionCount += 1 self.actionQueue.clear() # Scan server for file changes self.statusChanged.emit('Scanning remote files for changes') self.server.checkout() if self.firstScan: # First do a full scan to check for offline changes. # From there we will rely on real time notifications watchdog. self.firstScan = False self.statusChanged.emit('Scanning local files for changes') self.local.checkout() self.local.startObserver() # Si Added # Since its the first scan, we should also # set the timer interval self.actionTimer.setInterval(5000) self.cleanSync() # Si Added # Set check interval intelligently. # If there's no activity there, wait longer. # Since if there's just no usage, then # no reason to take up CPU cycles. tempInterval = 0 if serverActionCount + localActionCount > 0: tempInterval = 5000 else: tempInterval = 1000 * 10 self.actionTimer.start() @Slot() def cleanSync(self): """ Removes entries from the database for deleted files """ session = Session() session.query(File).filter(File.inserver == False).filter( File.inlocal == False).delete(synchronize_session=False) session.commit() self.statusChanged.emit('Sync completed. Waiting for changes') @Slot(str, str, bool) def onChanged(self, location, serverpath, skipDeltaCheck): changed_file = File.fromPath(serverpath) action = None #if not changed_file.servermdate: # Probably a local added event that also # spawned a modified event. #return file_name_only = os.path.basename(serverpath) if engine_tools.isTemporaryFile(file_name_only): print 'File ' + serverpath + ' ignored since it is a temporary file' return print 'File ' + serverpath + ':' if changed_file.servermdate == None: mydiff = "** File Not in Server **" edit_time = "(not in server)" else: ttt = (changed_file.localmdate - changed_file.servermdate).total_seconds() mydiff = str(ttt) edit_time = str(changed_file.servermdate) print 'Changed here %s, there %s delta %s' % (changed_file.localmdate, edit_time, mydiff) try: if changed_file.inserver: diff = changed_file.timeDiff() MY_TOLERANCE = 10 if skipDeltaCheck == False and abs(diff) < MY_TOLERANCE: return if location == FileAction.SERVER: if changed_file.inlocal: if changed_file.localmdate < changed_file.servermdate: action = FileAction(serverpath, FileAction.DOWNLOAD, FileAction.LOCAL) else: action = FileAction(serverpath, FileAction.DOWNLOAD, FileAction.LOCAL) elif location == FileAction.LOCAL: if changed_file.inserver: try: if changed_file.servermdate < changed_file.localmdate: action = FileAction(serverpath, FileAction.UPLOAD, FileAction.SERVER) except: print 'Error:', changed_file, changed_file.servermdate, changed_file.localmdate else: action = FileAction(serverpath, FileAction.UPLOAD, FileAction.SERVER) if action is not None: self.actionQueue.add(action) except: info = traceback.format_exception(*sys.exc_info()) for i in info: sys.stderr.write(i) @Slot(str, str) def onAdded(self, location, serverpath): file_name_only = os.path.basename(serverpath) if engine_tools.isTemporaryFile(file_name_only): print 'File ' + serverpath + ' was created but ignored since it is a temporary file' return added_file = File.fromPath(serverpath) action = None if location == FileAction.SERVER and not added_file.inlocal: action = FileAction(serverpath, FileAction.DOWNLOAD, FileAction.LOCAL) elif location == FileAction.LOCAL and not added_file.inserver: action = FileAction(serverpath, FileAction.UPLOAD, FileAction.SERVER) if action is not None: self.actionQueue.add(action) @Slot(str, str) def onDeleted(self, location, serverpath): # NOTE: For temporary files, the current action is to delete it. # Reason 1: We need to remove it from the database. # Reason 2: If somehow there is a temporary file # there on the other side, then it makes sense to delete it. deleted_file = File.fromPath(serverpath) action = None if location == FileAction.SERVER: if deleted_file.inlocal: action = FileAction(serverpath, FileAction.DELETE, FileAction.LOCAL) elif location == FileAction.LOCAL: if deleted_file.inserver: action = FileAction(serverpath, FileAction.DELETE, FileAction.SERVER) if action is not None: self.actionQueue.add(action)
def repaintTimer(self): q = self.q ret = QTimer(q) ret.setInterval(200) ret.timeout.connect(q.repaint) return ret
""" print('~~~~ Pure Python method called') self.windowTitle() # generate exception app = QApplication([]) app.setQuitOnLastWindowClosed(False) lineEdit = LineEdit() lineEdit.deleteLater() if USE_SINGLESHOT: #QTimer.singleShot(1000, lineEdit.clear) #QTimer.singleShot(1000, lineEdit.purePythonMethod) QTimer.singleShot(1000, lineEdit.selectAll) # pure C++ method else: timer = QTimer(None) timer.setSingleShot(True) timer.setInterval(1000) timer.start() #timer.timeout.connect(lineEdit.clear) #timer.timeout.connect(lineEdit.purePythonMethod) timer.timeout.connect(lineEdit.selectAll) # pure C++ method QTimer.singleShot(2000, app.quit) app.exec_() print('~~~~ Application exited')
class RunnerDialog(QDialog): options_added = Signal(Options) options_running = Signal(Options) options_simulated = Signal(Options) options_error = Signal(Options, Exception) results_saved = Signal(Results, str) results_error = Signal(Results, Exception) def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Runner') self.setMinimumWidth(750) # Runner self._runner = None self._running_timer = QTimer() self._running_timer.setInterval(500) # Widgets self._dlg_progress = QProgressDialog() self._dlg_progress.setRange(0, 100) self._dlg_progress.setModal(True) self._dlg_progress.hide() lbl_outputdir = QLabel("Output directory") self._txt_outputdir = DirBrowseWidget() max_workers = cpu_count() #@UndefinedVariable lbl_workers = QLabel('Number of workers') self._spn_workers = QSpinBox() self._spn_workers.setRange(1, max_workers) self._spn_workers.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) lbl_max_workers = QLabel('(max: %i)' % max_workers) self._chk_overwrite = QCheckBox("Overwrite existing results in output directory") self._chk_overwrite.setChecked(True) self._lbl_available = QLabel('Available') self._lst_available = QListView() self._lst_available.setModel(_AvailableOptionsListModel()) self._lst_available.setSelectionMode(QListView.SelectionMode.MultiSelection) tlb_available = QToolBar() spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) tlb_available.addWidget(spacer) act_open = tlb_available.addAction(getIcon("document-open"), "Open") act_open.setShortcut(QKeySequence.Open) tlb_available.addSeparator() act_remove = tlb_available.addAction(getIcon("list-remove"), "Remove") act_clear = tlb_available.addAction(getIcon("edit-clear"), "Clear") self._btn_addtoqueue = QPushButton(getIcon("go-next"), "") self._btn_addtoqueue.setToolTip("Add to queue") self._btn_addtoqueue.setEnabled(False) self._btn_addalltoqueue = QPushButton(getIcon("go-last"), "") self._btn_addalltoqueue.setToolTip("Add all to queue") self._btn_addalltoqueue.setEnabled(False) self._lbl_options = QLabel('Queued/Running/Completed') self._tbl_options = QTableView() self._tbl_options.setModel(_StateOptionsTableModel()) self._tbl_options.setItemDelegate(_StateOptionsItemDelegate()) self._tbl_options.setSelectionMode(QListView.SelectionMode.NoSelection) self._tbl_options.setColumnWidth(1, 60) self._tbl_options.setColumnWidth(2, 80) header = self._tbl_options.horizontalHeader() header.setResizeMode(0, QHeaderView.Interactive) header.setResizeMode(1, QHeaderView.Fixed) header.setResizeMode(2, QHeaderView.Fixed) header.setResizeMode(3, QHeaderView.Stretch) self._btn_start = QPushButton(getIcon("media-playback-start"), "Start") self._btn_cancel = QPushButton("Cancel") self._btn_cancel.setEnabled(False) self._btn_close = QPushButton("Close") self._btn_import = QPushButton("Import") self._btn_import.setEnabled(False) # Layouts layout = QVBoxLayout() sublayout = QGridLayout() sublayout.addWidget(lbl_outputdir, 0, 0) sublayout.addWidget(self._txt_outputdir, 0, 1) sublayout.addWidget(lbl_workers, 1, 0) subsublayout = QHBoxLayout() subsublayout.addWidget(self._spn_workers) subsublayout.addWidget(lbl_max_workers) sublayout.addLayout(subsublayout, 1, 1) layout.addLayout(sublayout) sublayout.addWidget(self._chk_overwrite, 2, 0, 1, 3) sublayout = QGridLayout() sublayout.setColumnStretch(0, 1) sublayout.setColumnStretch(2, 3) sublayout.addWidget(self._lbl_available, 0, 0) sublayout.addWidget(self._lst_available, 1, 0) sublayout.addWidget(tlb_available, 2, 0) subsublayout = QVBoxLayout() subsublayout.addStretch() subsublayout.addWidget(self._btn_addtoqueue) subsublayout.addWidget(self._btn_addalltoqueue) subsublayout.addStretch() sublayout.addLayout(subsublayout, 1, 1) sublayout.addWidget(self._lbl_options, 0, 2) sublayout.addWidget(self._tbl_options, 1, 2) layout.addLayout(sublayout) sublayout = QHBoxLayout() sublayout.addStretch() sublayout.addWidget(self._btn_import) sublayout.addWidget(self._btn_start) sublayout.addWidget(self._btn_cancel) sublayout.addWidget(self._btn_close) layout.addLayout(sublayout) self.setLayout(layout) # Signal self._running_timer.timeout.connect(self._onRunningTimer) act_open.triggered.connect(self._onOpen) act_remove.triggered.connect(self._onRemove) act_clear.triggered.connect(self._onClear) self._btn_addtoqueue.released.connect(self._onAddToQueue) self._btn_addalltoqueue.released.connect(self._onAddAllToQueue) self._btn_start.released.connect(self._onStart) self._btn_cancel.released.connect(self._onCancel) self._btn_close.released.connect(self._onClose) self._btn_import.released.connect(self._onImport) self.options_added.connect(self._onOptionsAdded) self.options_running.connect(self._onOptionsRunning) self.options_simulated.connect(self._onOptionsSimulated) self.options_error.connect(self._onOptionsError) self.results_error.connect(self._onResultsError) # Defaults settings = get_settings() section = settings.add_section('gui') if hasattr(section, 'outputdir'): self._txt_outputdir.setPath(section.outputdir) if hasattr(section, 'maxworkers'): self._spn_workers.setValue(int(section.maxworkers)) if hasattr(section, 'overwrite'): state = True if section.overwrite.lower() == 'true' else False self._chk_overwrite.setChecked(state) def _onDialogProgressProgress(self, progress, status): self._dlg_progress.setValue(progress * 100) self._dlg_progress.setLabelText(status) def _onDialogProgressCancel(self): self._dlg_progress.hide() if self._options_reader_thread is None: return self._options_reader_thread.cancel() self._options_reader_thread.quit() self._options_reader_thread.wait() def _onDialogProgressException(self, ex): self._dlg_progress.hide() self._options_reader_thread.quit() self._options_reader_thread.wait() messagebox.exception(self, ex) def _onRunningTimer(self): self._tbl_options.model().reset() def _onOpen(self): settings = get_settings() curdir = getattr(settings.gui, 'opendir', os.getcwd()) filepath, namefilter = \ QFileDialog.getOpenFileName(self, "Open", curdir, 'Options [*.xml] (*.xml)') if not filepath or not namefilter: return settings.gui.opendir = os.path.dirname(filepath) if not filepath.endswith('.xml'): filepath += '.xml' self._options_reader_thread = _OptionsReaderWrapperThread(filepath) self._dlg_progress.canceled.connect(self._onDialogProgressCancel) self._options_reader_thread.resultReady.connect(self._onOpened) self._options_reader_thread.progressUpdated.connect(self._onDialogProgressProgress) self._options_reader_thread.exceptionRaised.connect(self._onDialogProgressException) self._options_reader_thread.start() self._dlg_progress.reset() self._dlg_progress.show() def _onOpened(self, options): self._dlg_progress.hide() self._options_reader_thread.quit() self._options_reader_thread.wait() self._options_reader_thread = None try: self._lst_available.model().addOptions(options) except Exception as ex: messagebox.exception(self, ex) def _onRemove(self): selection = self._lst_available.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Queue", "Select an options") return model = self._lst_available.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): model.popOptions(row) def _onClear(self): self._lst_available.model().clearOptions() def _onAddToQueue(self): selection = self._lst_available.selectionModel().selection().indexes() if len(selection) == 0: QMessageBox.warning(self, "Queue", "Select an options") return model = self._lst_available.model() for row in sorted(map(methodcaller('row'), selection), reverse=True): options = model.options(row) try: self._runner.put(options) except Exception as ex: messagebox.exception(self, ex) return def _onAddAllToQueue(self): model = self._lst_available.model() for row in reversed(range(0, model.rowCount())): options = model.options(row) try: self._runner.put(options) except Exception as ex: messagebox.exception(self, ex) return def _onStart(self): outputdir = self._txt_outputdir.path() if not outputdir: QMessageBox.critical(self, 'Start', 'Missing output directory') return max_workers = self._spn_workers.value() overwrite = self._chk_overwrite.isChecked() self.start(outputdir, overwrite, max_workers) def _onCancel(self): self.cancel() def _onClose(self): if self._runner is not None: self._runner.close() self._running_timer.stop() self.close() def _onImport(self): list_options = self._lst_available.model().listOptions() if not list_options: return # Select options dialog = _OptionsSelector(list_options) if not dialog.exec_(): return options = dialog.options() # Start importer outputdir = self._runner.outputdir max_workers = self._runner.max_workers importer = LocalImporter(outputdir, max_workers) importer.start() importer.put(options) self._dlg_progress.show() try: while importer.is_alive(): if self._dlg_progress.wasCanceled(): importer.cancel() break self._dlg_progress.setValue(importer.progress * 100) finally: self._dlg_progress.hide() def _onOptionsAdded(self, options): logging.debug('runner: optionsAdded') self._tbl_options.model().addOptions(options) def _onOptionsRunning(self, options): logging.debug('runner: optionsRunning') self._tbl_options.model().resetOptions(options) def _onOptionsSimulated(self, options): logging.debug('runner: optionsSimulated') self._tbl_options.model().resetOptions(options) def _onOptionsError(self, options, ex): logging.debug('runner: optionsError') self._tbl_options.model().resetOptions(options) def _onResultsError(self, results, ex): logging.debug('runner: resultsError') self._tbl_options.model().reset() def closeEvent(self, event): if self.is_running(): message = 'Runner is running. Do you want to continue?' answer = QMessageBox.question(self, 'Runner', message, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.No: event.ignore() return self.cancel() self._dlg_progress.close() settings = get_settings() section = settings.add_section('gui') path = self._txt_outputdir.path() if path: section.outputdir = path section.maxworkers = str(self._spn_workers.value()) section.overwrite = str(self._chk_overwrite.isChecked()) settings.write() event.accept() def addAvailableOptions(self, options): self._lst_available.model().addOptions(options) def removeAvailableOptions(self, options): self._lst_available.model().removeOptions(options) def clearAvailableOptions(self): self._lbl_available.model().clearOptions() def start(self, outputdir, overwrite, max_workers): self._runner = LocalRunner(outputdir=outputdir, overwrite=overwrite, max_workers=max_workers) self._tbl_options.setModel(_StateOptionsTableModel(self._runner)) self._spn_workers.setEnabled(False) self._txt_outputdir.setEnabled(False) self._chk_overwrite.setEnabled(False) self._btn_addtoqueue.setEnabled(True) self._btn_addalltoqueue.setEnabled(True) self._btn_start.setEnabled(False) self._btn_cancel.setEnabled(True) self._btn_close.setEnabled(False) self._btn_import.setEnabled(True) self._runner.options_added.connect(self.options_added.emit) self._runner.options_running.connect(self.options_running.emit) self._runner.options_simulated.connect(self.options_simulated.emit) self._runner.options_error.connect(self.options_error.emit) self._runner.results_saved.connect(self.results_saved.emit) self._runner.results_error.connect(self.results_error.emit) self._running_timer.start() self._runner.start() def cancel(self): if self._runner is None: return self._runner.cancel() self._running_timer.stop() self._runner.options_added.disconnect(self.options_added.emit) self._runner.options_running.disconnect(self.options_running.emit) self._runner.options_simulated.disconnect(self.options_simulated.emit) self._runner.options_error.disconnect(self.options_error.emit) self._runner.results_saved.disconnect(self.results_saved.emit) self._runner.results_error.disconnect(self.results_error.emit) self._runner = None self._spn_workers.setEnabled(True) self._txt_outputdir.setEnabled(True) self._chk_overwrite.setEnabled(True) self._btn_addtoqueue.setEnabled(False) self._btn_addalltoqueue.setEnabled(False) self._btn_start.setEnabled(True) self._btn_cancel.setEnabled(False) self._btn_close.setEnabled(True) self._btn_import.setEnabled(False) def is_running(self): return self._runner is not None and self._runner.is_alive()
class SpiderTab(QWidget): """Has handlers for spider data and events. It houses the results table of the spider, controls for the spider and progress indication It implicitly conforms to IEventHandler interface""" TIMER_CHECK_INTERVAL = 3000 favicon_received = Signal(str) # send the url or path to the handler, which should be the tab widget stop_spider_signal = Signal(int) became_current = Signal(bool) # tell the table it has become active. it's an interesting property for producers! def __init__(self, parent=None, **kwargs): super(SpiderTab, self).__init__(parent) self._event_queue = None self._data_queue = None self._engine = None self._favicon_received = False self._spider_id = None self._item_count = 0 self.setContextMenuPolicy(Qt.ContextMenuPolicy.DefaultContextMenu) self.initInterface(kwargs) self._context_menu = None self._setupContextMenu() self.became_current.connect(self._set_table_activity) self._queue_check_timer = QTimer() self._queue_check_timer.setInterval(self.TIMER_CHECK_INTERVAL) self._queue_check_timer.timeout.connect(self._checkQueues) self._queue_check_timer.start() def initInterface(self, kwargs): layout = QGridLayout() self._data_table = SearchTable(name=kwargs.get("name")) self._progress_spider = QProgressBar() self._label_count = QLabel(self.tr("0 items scraped")) # make it a busy indicator. you don't know when it'll finish self._progress_spider.setMinimum(0); self._progress_spider.setMaximum(0) self._progress_spider.setTextVisible(False) self._btn_stop_spider = QPushButton(self.tr("Stop Spider")) self._btn_stop_spider.clicked.connect(self.stop_spider) row = 0; col = 0; layout.addWidget(self._data_table, row, col, 1, 4) row += 1; layout.addWidget(self._progress_spider, row, col, 1, 1) col += 1 layout.addWidget(self._label_count, row, col, 1, 2) col += 2 layout.addWidget(self._btn_stop_spider, row, col, 1, 1) self.setLayout(layout) def _setupContextMenu(self): from visualscrape.lib.data import ActionStore self._context_menu = QMenu(self) # get the export action from the action store action_store = ActionStore.get_instance() for action in action_store: if action.get_name() == "export": export_action = action break self._context_menu.addAction(export_action) def export_table(self): export_dialog = ExportDialog() export_dialog.exec_() export_info = export_dialog.data() if export_info: data = self._data_table.get_visible_data() FileExporter.export(data, self._data_table.name.lower(), export_info.location, export_info.format) def set_event_queue(self, eq): self._event_queue = eq def set_data_queue(self, dq): self._data_queue = dq def stop_spider(self): if self._spider_id is None: # do not stop the the spider before receiving data pass else: if self._queue_check_timer.isActive(): confirm_stop = QMessageBox(self) confirm_stop.setIcon(QMessageBox.Warning) confirm_stop.setStandardButtons(QMessageBox.Yes | QMessageBox.No) confirm_stop.setText(self.tr("Scraping process still running")) confirm_stop.setDetailedText(self.tr("Are you sure you want to stop it?")) confirm_stop.setWindowTitle(self.tr("Spider still running")) ret = confirm_stop.exec_() if ret == QMessageBox.Yes: self.stop_spider_signal.emit(self._spider_id) return True else: return False # I won't whip you if you stop it accidentally else: return True # already over def configure_searchlineedit(self, lineEdit): self._data_table.configure_search_lineedit(lineEdit) def _checkQueues(self): while not self._event_queue.empty(): event = self._event_queue.get(block=False, timeout=0) if isinstance(event, SpiderClosed): self._queue_check_timer.stop() self._progress_spider.setMinimum(0) self._progress_spider.setMaximum(100) self._progress_spider.setValue(100) self._btn_stop_spider.setEnabled(False) while not self._data_queue.empty(): item = self._data_queue.get(block=False, timeout=0) if not self._favicon_received: # the first item on the data queue should be the favicon favicon_data = item["images"][0] self.favicon_received.emit(favicon_data["path"]) # note that icons are not guaranteed to have a path. Not everybody wants to save images self._favicon_received = True self._spider_id = item["_id"] else: item.pop("_id") # the table has nothing to do with spider ids self._data_table.addItem(item) self._item_count += 1 self._label_count.setText(self.tr("{0:n} items scraped".format(self._item_count))) def _set_table_activity(self, state): self._data_table.set_active(state)
def searchTimer(self): ret = QTimer(self.q) ret.setInterval(3000) ret.timeout.connect(self._search) ret.setSingleShot(True) return ret
class WalletController(QObject): onError = Signal(unicode) onConnected = Signal(bool) onTxSent = Signal(bool) onBusy = Signal() onDoubleEncrypted = Signal() onBalance = Signal() onFiatBalance = Signal() onWalletUnlocked = Signal() onCurrentBalance = Signal() onCurrentFiatBalance = Signal() onCurrentLabel = Signal() onCurrentAddress = Signal() onCurrentDoubleEncrypted = Signal() onCurrentPassKey = Signal() onCurrentWatchOnly = Signal() def __init__(self,): QObject.__init__(self,) self.thread = None self._balance = '<b>0.00</b>000000' self._fiatSymbol = u'€' self._fiatRate = 0 self._fiatBalance = u'0 €' self._wallet = Wallet() self._wallet.onNewTransaction.connect(self.notifyNewTx) self._walletUnlocked = False self.settings = Settings() self.addressesModel = AddressesModel() self.transactionsModel = TransactionsModel() self.timer = QTimer(self) self.timer.setInterval(900000) # 15 min update self.timer.timeout.connect(self.update) self.timer.start() if self.settings.storePassKey: self._currentPassKey = self.settings.passKey try: self.unlockWallet(self._currentPassKey) except: self.onError.emit('Stored pass phrase is invalid') else: self._currentPassKey = None self._currentAddressIndex = 0 def on_event_data_received(self, *args): print 'BitPurse received DATA:', args def notifyNewTx(self, address, datas, amount): from eventfeed import EventFeedService, EventFeedItem service = EventFeedService('BitPurse', 'BitPurse', self.on_event_data_received) item = EventFeedItem( '/usr/share/icons/hicolor/80x80/apps/bitpurse.png', 'BitPurse') item.set_body('New transaction on address %s : %f BTC' % (address, amount / float(10 ** 8))) # item.set_custom_action(self.notifyCallback) service.add_item(item) @Slot(unicode) def newAddr(self, doubleKey): try: self._wallet.createAddr(doubleKey) self.storeWallet() self.update() except (WrongPassword, DataError), err: self.onError.emit(unicode(err))
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): super(MainWindow, self).__init__() self.setupUi(self) self.setFixedSize(960, 640) #不会出现对toolbar的隐藏 self.toolBar.toggleViewAction().setVisible(False) self.finishingLayout() self.setupValue() self.setupSignal() self.setupAction(config=False, start=False, reset=False, result=False, printer=False, back=False) self.setShow(1) self.setShow(3) def setupValue(self): self.__action = { "config": False, "start": False, "reset": False, "result": False, "print": False, "back": False, "exit": True } self.color_sheet = [ '#0000ff', '#ff0000', '#ffff00', '#00ff40', '#00ffff', '#0080c0', '#8080c0', '#ff00ff', '#800000', '#ff8000', '#008040', '#800080', 'black' ] self.lcd_group = [ self.lcd_window.press_lcd1, self.lcd_window.press_lcd2, self.lcd_window.press_lcd3, self.lcd_window.press_lcd4, self.lcd_window.press_lcd5, self.lcd_window.press_lcd6, self.lcd_window.digital_lcd1, self.lcd_window.digital_lcd2, self.lcd_window.digital_lcd3, self.lcd_window.digital_lcd4, self.lcd_window.speed_lcd, self.lcd_window.acceleration_lcd, self.lcd_window.shift_lcd ] self.chk_group = [ self.lcd_window.press_chk1, self.lcd_window.press_chk2, self.lcd_window.press_chk3, self.lcd_window.press_chk4, self.lcd_window.press_chk5, self.lcd_window.press_chk6, self.lcd_window.digital_chk1, self.lcd_window.digital_chk2, self.lcd_window.digital_chk3, self.lcd_window.digital_chk4, self.lcd_window.speed_chk, self.lcd_window.acceleration_chk, self.lcd_window.shift_chk ] self.tcp_link = TcpLink() #比例转换系数1,5,10 self.scaleRegion = (40, 10, 5, 2, 1) self.scaleFactor = [10, 10, 10, 10, 10, 10] self.lines_data = [None] * 14 self.report = {} self.report['PRESS'] = {} self.report['DIGITAL'] = {} self.ST_flag = False self.init_press = 0 def setupSignal(self): self.connect(self.action_exit, SIGNAL("triggered()"), self.actionExit) self.connect(self.action_config, SIGNAL("triggered()"), self.actionConfig) self.connect(self.action_start, SIGNAL("triggered()"), self.actionStart) self.connect(self.action_reset, SIGNAL("triggered()"), self.actionReset) self.connect(self.action_result, SIGNAL("triggered()"), self.actionResult) self.connect(self.action_print, SIGNAL("triggered()"), self.actionPrint) self.connect(self.action_back, SIGNAL("triggered()"), self.actionBack) self.connect(self.action_read_report, SIGNAL("triggered()"), self.actionReadReport) self.connect(self.notice_window.default_part.connect_button, SIGNAL("clicked()"), self.connectButtonClicked) self.connect(self.notice_window.default_part.read_file_button, SIGNAL("clicked()"), self.readFileButtonClicked) self.notice_window.current_press.ready_button.clicked.connect( self.readyButtonClicked) self.lcd_window.st_transfer.clicked.connect(self.setShiftTimeChange) #不能在外界直接操作GUI只能采用信号槽方式 self.tcp_link.signal_tips.connect(self.notice_window.setLblNotice) self.tcp_link.signal_noticeText.connect( self.notice_window.setNoticeText) self.tcp_link.signal_progressBar.connect(self.notice_window.setValue) self.tcp_link.signal_lcd.connect(self.setPress6LCDValue) self.tcp_link.signal_trigger.connect(self.actionStart) self.tcp_link.signal_result.connect(self.connectResult) self.tcp_link.signal_timeout.connect(self.dataTimeout) #右侧LCD 显示 self.curve_window.lcd_signal.connect(self.lcdDisplay) for i in self.chk_group: i.toggled.connect(self.lcdCheck) #数据收集阶段定时器,根据具体情况删减 self.draw_timer = QTimer(self) self.connect(self.draw_timer, SIGNAL("timeout()"), self.waitDraw) def finishingLayout(self): self.left_layout = QVBoxLayout() self.right_layout = QHBoxLayout() self.notice_window = NoticeWidget(self) self.curve_window = CurveWidget(self) self.left_layout.addWidget(self.curve_window) self.left_layout.addWidget(self.notice_window) self.curve_window.hide() self.widget_container.setLayout(self.left_layout) self.explain_window = Explain(self) self.configuration_window = Configuration(self) self.lcd_window = LCDGroup(self) self.right_layout.addWidget(self.explain_window) self.right_layout.addWidget(self.configuration_window) self.right_layout.addWidget(self.lcd_window) self.configuration_window.hide() self.lcd_window.hide() self.frame_container.setLayout(self.right_layout) def setShow(self, flag): """flag must a int""" if flag == 1: self.curve_window.hide() self.notice_window.show() self.notice_window.update() elif flag == 2: #print self.notice_window.geometry() self.notice_window.hide() self.curve_window.show() self.curve_window.update() #print self.curve_window.geometry() #print self.widget_container.geometry() elif flag == 3: self.explain_window.show() self.explain_window.update() self.configuration_window.hide() self.lcd_window.hide() elif flag == 4: self.explain_window.hide() self.configuration_window.show() self.configuration_window.update() self.lcd_window.hide() elif flag == 5: self.explain_window.hide() self.configuration_window.hide() self.lcd_window.show() self.lcd_window.update() def setupAction(self, **kwargs): """ kwargs = {"config":False,"start":False,"reset":False,"result":False,"print":False,"back":False, "exit":False} """ for i in kwargs.keys(): self.__action[i] = kwargs[i] self.action_config.setEnabled(self.__action["config"]) self.action_start.setEnabled(self.__action["start"]) self.action_reset.setEnabled(self.__action["reset"]) self.action_result.setEnabled(self.__action["result"]) self.action_print.setEnabled(self.__action["printer"]) self.action_back.setEnabled(self.__action["back"]) self.action_exit.setEnabled(self.__action["exit"]) def actionOrder(self, order): if order == 'init': self.setupAction(config=False, start=False, reset=False, result=False, printer=False, back=False) self.setShow(1) self.setShow(3) self.notice_window.setShow(1) self.notice_window.reset() self.notice_window.setLblNotice(u"点击[检测连接(Ctrl+Alt+L)]与下位机建立通信连接\ \n点击[读取文档(Ctrl+Alt+R)]读取已保存的数据文档") self.action_back.setText(u"首页/断开") elif order == 'config': self.setupAction(config=True, back=True) self.notice_window.setShow(2) self.setShow(1) self.setShow(4) self.notice_window.reset() self.notice_window.setLblNotice(u"点击[参数设置(F1)]对要进行测量的项目进行相关参数的设置\n" u"点击[断开连接(F7)]断开与下位机的通信") self.action_back.setText(u"断开连接") elif order == 'ready': self.setupAction(config=False, reset=True) self.setShow(1) self.setShow(4) self.notice_window.setShow(3) self.notice_window.setLblNotice(u"点击[准备测试(Ctrl+Alt+R)]进入测量\n" u"点击[复位(F3)]对配置信息进行重新配置") elif order == 'reset': self.setupAction(config=True, start=False, reset=False, result=False, printer=False) self.notice_window.setShow(2) self.setShow(1) self.setShow(4) self.notice_window.setLblNotice(u"点击[参数设置(F1)]对要进行测量的项目进行相关参数的设置\ \n点击[断开连接(F7)]断开与下位机的通信") self.notice_window.setNoticeText(u"对下次测试进行重新配置") elif order == 'trigger': self.notice_window.setShow(2) self.notice_window.setLblNotice(u'此时请勿进行其他操作,若要停止测试请点击[复位(F3)]') self.notice_window.setNoticeText(u'等待触发......') elif order == 'start': self.setupAction(start=True) self.notice_window.setShow(2) self.notice_window.setLblNotice( u'点击[开始(F2)]进行测量,若要重新测试请点击[复位(F3)]') self.notice_window.setNoticeText(u'手动触发方式') elif order == 'draw': self.setupAction(result=True, printer=True) elif order == 'tips': pass elif order == 'read': self.setShow(2) self.setShow(5) self.setupAction(back=True, result=True) self.action_back.setText(u"返回首页") def actionConfig(self): """根据配置对话框的内容获取相关参数""" config_dialog = ConfigDialog(self.tcp_link.getLineState) config_dialog.show() config_dialog.exec_() if config_dialog.getPassFlag(): self.group_digital = [(i[0].text(), i[1].isChecked()) for i in config_dialog.group_digital] self.group_press = [(i[0].text(), i[1].isChecked(), i[2].currentIndex()) for i in config_dialog.group_press] self.group_speed_trigger = [ config_dialog.speed_chk.isChecked(), config_dialog.trigger_combo.currentIndex() ] #测试项目,项目名称,测试人员,测试日期 self.groupNPTInfo = [ config_dialog.testProject.currentIndex(), config_dialog.projectName_edit.text(), config_dialog.person_edit.text(), config_dialog.time_edit.text() ] #测试时长 self.measure_time = config_dialog.measureTime #测试距离 self.measure_distance = config_dialog.measureDistance #set默认通道 self.default_press = config_dialog.default_press.currentIndex() #设置默认膛压通道 self.notice_window.setDefault(self.default_press) self.default_digital = config_dialog.default_digital.currentIndex() self.tcp_link.setPressChannel(self.default_press) self.tcp_link.setDigitalChannel(self.default_digital) self.tcp_link.setThresholdPress(config_dialog.threshold_press) self.tcp_link.setCalibration(config_dialog.calibration) self.tcp_link.setSpeedFactor(self.groupNPTInfo[0]) #需要绘制的坐标系 self.exist_axis = [] #需要调整宽度的坐标系 axis_num = [] for i, j in enumerate(self.group_press): if j[1]: self.exist_axis.append(i) axis_num.append((i, j[2])) self.scaleFactor[i] = self.scaleRegion[j[2]] #if j[0]: #self.report['PRESS'][i] = j[0] #else: #self.report['PRESS'][i] = u'通道%d' %(i + 1) else: self.scaleFactor[i] = 0 #self.report['PRESS'][i] = None for i, j in enumerate(self.group_digital): if j[1]: self.exist_axis.append(i + 6) #if j[0]: #self.report['DIGITAL'][i] = j[0] #else: #self.report['DIGITAL'][i] = '通道%d' %(i + 1) #else: #self.report['DIGITAL'][i] = None if self.group_speed_trigger[0]: self.exist_axis.extend([10, 11, 12]) if self.groupNPTInfo[0] == 0: axis_num.append((12, 1)) else: axis_num.append((12, 4)) self.tcp_link.setFactor(self.scaleFactor[:]) #print self.scaleFactor self.curve_window.produceAxis(self.exist_axis[:]) for i in (axis_num): self.curve_window.setTicker(i[0], i[1]) #开始根据配置获取需求值并显示当前压力 self.tcp_link.setTestFlag(False) self.tcp_link.setCurrentFlag(True) #报告关键值 #序列号 self.report['SERIAL'] = self.groupNPTInfo[1] _test_type = [u'鱼雷', u'诱饵'] self.report['TYPE'] = _test_type[self.groupNPTInfo[0]] _trigger = [u'自动触发', u'手动触发', u'外触发'] self.report['TRIGGER'] = _trigger[ self.group_speed_trigger[1]] #触发方式 self.report['PERSON'] = self.groupNPTInfo[2] #测试人员 self.report['DATE'] = self.groupNPTInfo[3] #测试日期 self.tcp_link.setCurrentFlag(True) self.actionOrder('ready') #print self.measure_distance self.configuration_window.readConfig() def actionStart(self): #print 'start' self.lcd_window.check([i[1] for i in self.group_press], [i[1] for i in self.group_digital], self.group_speed_trigger[0]) #print self.group_speed_trigger[0] self.tcp_link.setTriggerFlag(False) self.tcp_link.setClearFlag(False) self.setupAction(start=False) self.notice_window.reset() self.setShow(1) self.notice_window.setLblNotice(u'正在接收数据中,若想停止测量可直接点击[复位(F3)]终止本次测量') self.notice_window.setShow(2) self.notice_window.setNoticeText(u'系统正在测量,请等待......') self.notice_window.setValue(1) self.draw_count = 0 self.draw_timer.start(100) self.draw_timer.setInterval(100) def waitDraw(self): self.draw_count += 0.1 value = 100 / (self.measure_time) * self.draw_count self.notice_window.setValue(value) if self.draw_count >= self.measure_time: self.draw() def draw(self): #关闭时间 self.tcp_link.setClearFlag(True) self.draw_timer.stop() self.notice_window.setNoticeText(u'数据接收完毕,处理中......') data = self.tcp_link.getData() #若无数据直接返回 if not data: self.actionReset() return #print len(data), 'total data' speed_data = data[15::16] self.handle = HandleData(speed_data, self.measure_distance) length = len(speed_data) #开始运动点num num = self.handle.getStartTime() shift = self.handle.shift() if self.groupNPTInfo[0] == 0: speed_out = self.handle.getOutTime(shift) else: speed_out = self.handle.getStopTime(shift, self.measure_distance) #所截取数据的长度 right_limit = speed_out + 100 if right_limit > length: right_limit = speed_out + 1 if self.group_speed_trigger[0]: x_data = [(i - num) * 5E-4 for i in range(length)] else: x_data = [i * 5E-4 for i in range(length)] self.lines_data[0] = x_data[:right_limit] #print self.exist_axis for i in range(10): y_data = data[i::16] self.lines_data[i + 1] = y_data[:right_limit] if i < 6: if i in self.exist_axis: #不同测试类型取值不同 if self.groupNPTInfo[0] == 0: _value = y_data[int(self.measure_time * 2000)] #_value = max(y_data) self.report['PRESS'][i + 1] = '%0.2f' % _value if i == self.default_press: self.report['PRESS'][ i + 1] = '%0.2f' % (_value - self.init_press) self.handle.setChamberPressure( self.lines_data[i + 1], self.init_press) else: # _value = y_data[speed_out] _value = y_data[int(self.measure_time * 2000)] self.report['PRESS'][i + 1] = '%0.2f' % _value self.curve_window.drawLine2D(self.exist_axis.index(i), self.lines_data[0], self.lines_data[i + 1], self.color_sheet[i]) else: self.report['PRESS'][i + 1] = '--' else: if i in self.exist_axis: begin = self.handle.bleedTime(y_data) #dead = length - begin #self.report['DIGITAL'][i - 5] = ('%0.2f' %(begin*5E-4), '%0.2f' %(dead*5E-4)) self.report['DIGITAL'][i - 5] = '%0.1f' % (begin * 5E-4) self.curve_window.drawLine2D(self.exist_axis.index(i), self.lines_data[0], self.lines_data[i + 1], self.color_sheet[i]) else: self.report['DIGITAL'][i - 5] = ('--') self.lines_data[11] = speed_data[:right_limit] #加速度 acceleration = self.handle.acceleration() self.lines_data[12] = acceleration[:right_limit] self.lines_data[13] = shift[:right_limit] if 10 in self.exist_axis: self.report['SPEED'] = '%0.1f' % speed_data[speed_out] self.curve_window.drawLine2D(self.exist_axis.index(10), self.lines_data[0], self.lines_data[11], self.color_sheet[10]) self.report['ACCELERATION'] = '%0.1f' % acceleration[speed_out] self.curve_window.drawLine2D(self.exist_axis.index(11), self.lines_data[0], self.lines_data[12], self.color_sheet[11]) self.curve_window.drawLine2D(self.exist_axis.index(12), self.lines_data[0], self.lines_data[13], self.color_sheet[12]) else: self.report['SPEED'] = '--' self.report['ACCELERATION'] = '--' #图像填充全屏 self.curve_window.setXFull(self.lines_data[0][0], self.lines_data[0][-1]) #延迟时间 self.report['DELAY'] = '%0.1f' % (num * 5E-4) #发射时间 self.report['SHOOT'] = '%0.1f' % (speed_out * 5E-4) #flag = self.report['DIGITAL'].get(self.default_digital + 1, ('--', '--')) if self.group_digital[self.default_digital][1]: begin, dead = self.handle.getStartClock( data[6 + self.default_digital::16]) #print begin, dead #泄放阀开启时间 self.report['OPEN'] = '%0.1f' % (begin * 5E-4) #泄放阀开启时机 self.report['BLEED'] = '%0.1f' % shift[dead] else: self.report['OPEN'] = '--' self.report['BLEED'] = '--' now_time = datetime.datetime.now() file_path = now_time.strftime("%Y%m%d%H%M%S") if self.groupNPTInfo[0] == 0: filename = u'鱼雷' + self.groupNPTInfo[1] + file_path else: filename = u'诱饵' + self.groupNPTInfo[1] + file_path #self.tempHTML(self.group_press, self.group_digital, './template/'+'image.png') self.tempPicture("./template/" + "image.png") self.saveReport('./report/' + filename + '.pdf') self.saveFile('./DigitalSheet/' + filename + '.csv') self.curve_window.updateDraw() self.curve_window._init_View() self.notice_window.setValue(100) self.setShow(2) self.setShow(5) self.actionOrder('draw') def tempPicture(self, filename): directory = os.path.dirname(filename) if not os.path.isdir(directory): os.makedirs(directory) self.curve_window.canvas.print_figure(filename, dpi=300) def saveReport(self, filename): directory = os.path.dirname(filename) if not os.path.isdir(directory): os.makedirs(directory) printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOrientation(QPrinter.Landscape) printer.setPageSize(QPrinter.A4) printer.setOutputFileName(filename) if filename: self.print_(printer) def print_(self, printer): painter = QPainter(printer) pageRect = printer.pageRect() w = pageRect.width() * 0.85 h = pageRect.height() painter.drawPixmap(0, 0, w, h, './template/image.png') sansFont = QFont("Helvetica", 10) painter.setFont(sansFont) fm = QFontMetrics(sansFont) height = fm.height() + 10 vmargin = 40 x0 = w + 1 y = 25 width = fm.width(u"测试编号") + 25 x1 = x0 + width painter.drawText(x0, y, u"报告编号") painter.drawText(x1, y, self.report['SERIAL']) y += height painter.drawText(x0, y, u"测试类型") painter.drawText(x1, y, self.report['TYPE']) y += height painter.drawText(x0, y, u"触发方式") painter.drawText(x1, y, self.report['TRIGGER']) y += height painter.drawText(x0, y, u"测试人员") painter.drawText(x1, y, self.report['PERSON']) y += height painter.drawText(x0, y, u"测试日期") painter.drawText(x1, y, self.report['DATE']) y += vmargin width = fm.width(u"通道1") + 50 x1 = x0 + width space = 0 painter.drawText(x0 + 20, y, u"压力通道(Mpa)") for i, j in enumerate(self.group_press): if j[1]: y += height if j[0]: painter.drawText(x0, y, j[0]) else: painter.drawText(x0, y, '通道%d'.decode("utf-8") % (i + 1)) painter.drawText(x1, y, self.report['PRESS'][i + 1]) else: space += height y += (vmargin + space) width = fm.width(u"通道计量1") + 15 x1 = x0 + width #x2 = x1 + width painter.drawText(x0 + 20, y, u"数字量计时通道(s)") y += height painter.drawText(x0, y, u"通道") painter.drawText(x1, y, u"开启时间") #painter.drawText(x2, y, u"关闭") space = 0 for i, j in enumerate(self.group_digital): if j[1]: y += height if j[0]: painter.drawText(x0, y, j[0]) else: painter.drawText(x0, y, '通道%d'.decode("utf-8") % (i + 1)) painter.drawText(x1, y, self.report['DIGITAL'][i + 1][0]) #painter.drawText(x2, y, self.report['DIGITAL'][i + 1][1]) else: space += height y += (vmargin + space) width = fm.width(u"出管速度(m/s)") + 25 x1 = x0 + width painter.drawText(x0, y, u"加速度(g)") painter.drawText(x1, y, self.report['ACCELERATION']) y += height painter.drawText(x0, y, u"出管速度(m/s)") painter.drawText(x1, y, self.report['SPEED']) y += height painter.drawText(x0, y, u"延迟时间(s)") painter.drawText(x1, y, self.report['DELAY']) y += height painter.drawText(x0, y, u"发射时间(s)") painter.drawText(x1, y, self.report['SHOOT']) y += height painter.drawText(x0, y, u"发射深度(s)") painter.drawText(x1, y, self.report['DEEP']) width = fm.width(u"泄放装置泄放时间(s)") + 5 y += height painter.drawText(x0, y, u"泄放阀开启时机(m)") x1 = x0 + width painter.drawText(x1, y, self.report['BLEED']) y += height painter.drawText(x0, y, u"泄放阀开启时间(s)") x1 = x0 + width + 1 painter.drawText(x1, y, self.report['OPEN']) def saveFile(self, filename): directorys = os.path.dirname(filename) if not os.path.isdir(directorys): os.makedirs(directorys) if not os.path.isfile(filename): try: file = open(filename, 'w') except Exception, e: file.close() return press = '&'.join([self.report['PRESS'][i] for i in range(1, 7)]) digital = '&'.join( [self.report['DIGITAL'][i] for i in range(1, 5)]) bleed_value = '&'.join([self.report['OPEN'], self.report['BLEED']]) #20131216对保存的数据进行修改 datapool = [ 'startest', self.report['SERIAL'], self.report['TYPE'], self.report['TRIGGER'], self.report['PERSON'], self.report['DATE'], press, digital, self.report['ACCELERATION'], self.report['SPEED'], self.report['DELAY'], self.report['SHOOT'], bleed_value, self.report['DEEP'] ] saveString = self.setText(','.join(datapool)) #print saveString file.write(saveString) file.write('\n') datapool = [] datapool.append('0') for i in range(6): datapool.append('%d' % self.group_press[i][2]) for i in range(4): datapool.append('0') datapool.append('0') datapool.append('0') if self.groupNPTInfo[0] == 0: datapool.append('1') else: datapool.append('4') saveString = ','.join(['%s' % i for i in datapool]) file.write(saveString) file.write('\n') datapool = [] datapool.append(True) datapool.extend([chk[1] for chk in self.group_press]) datapool.extend([chk[1] for chk in self.group_digital]) datapool.extend([self.group_speed_trigger[0] for i in range(3)]) saveString = ','.join(['%s' % i for i in datapool]) file.write(saveString) file.write('\n') datapool = [] for i, j in enumerate(self.lines_data[0]): for k in range(14): datapool.append(self.lines_data[k][i]) saveString = ','.join(['%s' % v for v in datapool]) file.write(saveString) file.write('\n') datapool = [] file.close()
class VideoMediaView(MediaView): def __init__(self, media, parent): super(VideoMediaView, self).__init__(media, parent) self._widget = QWidget(parent) self._process = QProcess(self._widget) self._process.setObjectName('%s-process' % self.objectName()) self._std_out = [] self._errors = [] self._stopping = False self._mute = False if 'mute' in self._options: self._mute = bool(int(self._options['mute'])) self._widget.setGeometry(media['_geometry']) self.connect(self._process, SIGNAL("error()"), self._process_error) self.connect(self._process, SIGNAL("finished()"), self.stop) self.connect(self._process, SIGNAL("readyReadStandardOutput()"), self.__grep_std_out) self.set_default_widget_prop() self._stop_timer = QTimer(self) self._stop_timer.setSingleShot(True) self._stop_timer.setInterval(1000) self._stop_timer.timeout.connect(self._force_stop) @Slot() def _force_stop(self): os.kill(self._process.pid(), signal.SIGTERM) self._stopping = False if not self.is_started(): self.started_signal.emit() super(VideoMediaView, self).stop() @Slot(object) def _process_error(self, err): self._errors.append(err) self.stop() @Slot() def play(self): self._finished = 0 path = "%s/%s" % (self._save_dir, self._options['uri']) self._widget.show() args = [ '-slave', '-identify', '-input', 'nodefault-bindings:conf=/dev/null', '-wid', str(int(self._widget.winId())), path ] if self._mute: args += ['-ao', 'null'] self._process.start('mplayer', args) self._stop_timer.start() @Slot() def stop(self, delete_widget=False): if self._stopping or self.is_finished(): return False self._stop_timer.start() self._stopping = True if self._process.state() == QProcess.ProcessState.Running: self._process.write("quit\n") self._process.waitForFinished(50) self._process.close() super(VideoMediaView, self).stop(delete_widget) self._stopping = False self._stop_timer.stop() return True @Slot() def __grep_std_out(self): lines = self._process.readAllStandardOutput().split("\n") for line in lines: if not line.isEmpty(): if line.startsWith("Starting playback"): self._widget.raise_() self._play_timer.start() self.started_signal.emit() self._stop_timer.stop() else: part = line.split("=") if 'ID_LENGTH' == part[0]: if float( self._duration ) > 0: # user set the video duration manually. self._play_timer.setInterval( int(1000 * float(self._duration))) else: # use duration found by mplayer. self._play_timer.setInterval( int(1000 * float(part[1])))
class Plot2DDataWidget(QWidget): def __init__(self,parent=None,measdata=[[1,3,2],[3,5,7]],header=["index","prime numbers"],SymbolSize=10,linecolor='y',pointcolor='b',title='Plot Window'): # This class derivates from a Qt MainWindow so we have to call # the class builder ".__init__()" #QMainWindow.__init__(self) QWidget.__init__(self) # "self" is now a Qt Mainwindow, then we load the user interface # generated with QtDesigner and call it self.ui self.ui = Plot2DDataWidget_Ui.Ui_Plot2DData() # Now we have to feed the GUI building method of this object (self.ui) # with a Qt Mainwindow, but the widgets will actually be built as children # of this object (self.ui) self.ui.setupUi(self) self.setWindowTitle(title) self.x_index=0 self.y_index=0 self.curve=self.ui.plot_area.plot(pen=linecolor) self.curve.setSymbolBrush(pointcolor) self.curve.setSymbol('o') self.curve.setSymbolSize(SymbolSize) self.parent=parent self.measdata=measdata self.header=header self.update_dropdown_boxes(header) self.update_plot_timer = QTimer() self.update_plot_timer.setSingleShot(True) #The timer would not wait for the completion of the task otherwise self.update_plot_timer.timeout.connect(self.autoupdate) if self.ui.auto_upd.isChecked():self.autoupdate() def update_timer_timeout(self,msec): self.update_plot_timer.setInterval(msec) def updateX(self,value): self.x_index=value #self.update_plot() #that was the bug #This created a loop because update_plot called check_connection #which called update_dropdown_boxes, which cleared the x_axis_box #which triggered a call to updateX def updateY(self,value): self.y_index=value #self.update_plot() def change_line_color(self,color=None): if color==None:color=QColorDialog.getColor() if color.isValid(): self.curve.setPen(color) def change_point_color(self,color=None): if color==None:color=QColorDialog.getColor() if color.isValid(): self.curve.setSymbolBrush(color) def change_symbol_size(self,value): self.curve.setSymbolSize(value) def check_connection(self,state=1): """check if the pointer to the Master dataset to display (self.measdata in Main.py) has changed""" if state and hasattr(self.parent,"measdata"): if self.parent.measdata!=self.measdata:self.measdata=self.parent.measdata if self.parent.current_header!=self.header:self.update_dropdown_boxes(self.parent.current_header) #print "Reestablishing connection" def autoupdate(self,state=1): if state: self.update_plot() self.update_plot_timer.start(self.ui.refresh_rate.value()*1000)#The value must be converted to milliseconds else: self.update_plot_timer.stop() def update_plot(self): """plot the data columns selected in the drop-down menu boxes""" if self.ui.autoconnect.isChecked():self.check_connection() if self.x_index!=-1 and self.y_index!=-1 and self.measdata[self.x_index]!=[] and self.measdata[self.y_index]!=[]: self.curve.setData(self.measdata[self.x_index],self.measdata[self.y_index]) def update_dropdown_boxes(self,header): """Update the drop-down boxes that select the content of the plot""" self.ui.x_axis_box.clear() self.ui.x_axis_box.addItems(header) self.ui.y_axis_box.clear() self.ui.y_axis_box.addItems(header) self.header=header
class _CompletionList(QListView): """Completion list widget """ closeMe = pyqtSignal() itemSelected = pyqtSignal(int) tabPressed = pyqtSignal() _MAX_VISIBLE_ROWS = 20 # no any technical reason, just for better UI _ROW_MARGIN = 6 def __init__(self, qpart, model): QListView.__init__(self, qpart.viewport()) self.setItemDelegate(HTMLDelegate(self)) self._qpart = qpart self.setFont(qpart.font()) self.setCursor(QCursor(Qt.PointingHandCursor)) self.setFocusPolicy(Qt.NoFocus) self.setModel(model) self._selectedIndex = -1 # if cursor moved, we shall close widget, if its position (and model) hasn't been updated self._closeIfNotUpdatedTimer = QTimer() self._closeIfNotUpdatedTimer.setInterval(200) self._closeIfNotUpdatedTimer.setSingleShot(True) self._closeIfNotUpdatedTimer.timeout.connect(self._afterCursorPositionChanged) qpart.installEventFilter(self) qpart.cursorPositionChanged.connect(self._onCursorPositionChanged) self.clicked.connect(lambda index: self.itemSelected.emit(index.row())) self.updateGeometry() self.show() qpart.setFocus() def __del__(self): """Without this empty destructor Qt prints strange trace QObject::startTimer: QTimer can only be used with threads started with QThread when exiting """ pass def del_(self): """Explicitly called destructor. Removes widget from the qpart """ self._closeIfNotUpdatedTimer.stop() self._qpart.removeEventFilter(self) self._qpart.cursorPositionChanged.disconnect(self._onCursorPositionChanged) # if object is deleted synchronously, Qt crashes after it on events handling QTimer.singleShot(0, lambda: self.setParent(None)) def sizeHint(self): """QWidget.sizeHint implementation Automatically resizes the widget according to rows count FIXME very bad algorithm. Remove all this margins, if you can """ width = max([self.fontMetrics().width(word) \ for word in self.model().words]) width = width * 1.4 # FIXME bad hack. invent better formula width += 30 # margin # drawn with scrollbar without +2. I don't know why rowCount = min(self.model().rowCount(), self._MAX_VISIBLE_ROWS) height = (self.sizeHintForRow(0) * rowCount) + self._ROW_MARGIN return QSize(width, height) def minimumHeight(self): """QWidget.minimumSizeHint implementation """ return self.sizeHintForRow(0) + self._ROW_MARGIN def _horizontalShift(self): """List should be plased such way, that typed text in the list is under typed text in the editor """ strangeAdjustment = 2 # I don't know why. Probably, won't work on other systems and versions return self.fontMetrics().width(self.model().typedText()) + strangeAdjustment def updateGeometry(self): """Move widget to point under cursor """ WIDGET_BORDER_MARGIN = 5 SCROLLBAR_WIDTH = 30 # just a guess sizeHint = self.sizeHint() width = sizeHint.width() height = sizeHint.height() cursorRect = self._qpart.cursorRect() parentSize = self.parentWidget().size() spaceBelow = parentSize.height() - cursorRect.bottom() - WIDGET_BORDER_MARGIN spaceAbove = cursorRect.top() - WIDGET_BORDER_MARGIN if height <= spaceBelow or \ spaceBelow > spaceAbove: yPos = cursorRect.bottom() if height > spaceBelow and \ spaceBelow > self.minimumHeight(): height = spaceBelow width = width + SCROLLBAR_WIDTH else: if height > spaceAbove and \ spaceAbove > self.minimumHeight(): height = spaceAbove width = width + SCROLLBAR_WIDTH yPos = max(3, cursorRect.top() - height) xPos = cursorRect.right() - self._horizontalShift() if xPos + width + WIDGET_BORDER_MARGIN > parentSize.width(): xPos = max(3, parentSize.width() - WIDGET_BORDER_MARGIN - width) self.setGeometry(xPos, yPos, width, height) self._closeIfNotUpdatedTimer.stop() def _onCursorPositionChanged(self): """Cursor position changed. Schedule closing. Timer will be stopped, if widget position is being updated """ self._closeIfNotUpdatedTimer.start() def _afterCursorPositionChanged(self): """Widget position hasn't been updated after cursor position change, close widget """ self.closeMe.emit() def eventFilter(self, object, event): """Catch events from qpart Move selection, select item, or close themselves """ if event.type() == QEvent.KeyPress and event.modifiers() == Qt.NoModifier: if event.key() == Qt.Key_Escape: self.closeMe.emit() return True elif event.key() == Qt.Key_Down: if self._selectedIndex + 1 < self.model().rowCount(): self._selectItem(self._selectedIndex + 1) return True elif event.key() == Qt.Key_Up: if self._selectedIndex - 1 >= 0: self._selectItem(self._selectedIndex - 1) return True elif event.key() in (Qt.Key_Enter, Qt.Key_Return): if self._selectedIndex != -1: self.itemSelected.emit(self._selectedIndex) return True elif event.key() == Qt.Key_Tab: self.tabPressed.emit() return True elif event.type() == QEvent.FocusOut: self.closeMe.emit() return False def _selectItem(self, index): """Select item in the list """ self._selectedIndex = index self.setCurrentIndex(self.model().createIndex(index, 0))
class QtReactor(posixbase.PosixReactorBase): implements(IReactorFDSet) def __init__(self): self._reads = {} self._writes = {} self._notifiers = {} self._timer = QTimer() self._timer.setSingleShot(True) QObject.connect(self._timer, SIGNAL("timeout()"), self.iterate) if QCoreApplication.instance() is None: # Application Object has not been started yet self.qApp=QCoreApplication([]) self._ownApp=True else: self.qApp = QCoreApplication.instance() self._ownApp=False self._blockApp = None posixbase.PosixReactorBase.__init__(self) def _add(self, xer, primary, type): """ Private method for adding a descriptor from the event loop. It takes care of adding it if new or modifying it if already added for another state (read -> read/write for example). """ if xer not in primary: primary[xer] = TwistedSocketNotifier(None, self, xer, type) def addReader(self, reader): """ Add a FileDescriptor for notification of data available to read. """ self._add(reader, self._reads, QSocketNotifier.Read) def addWriter(self, writer): """ Add a FileDescriptor for notification of data available to write. """ self._add(writer, self._writes, QSocketNotifier.Write) def _remove(self, xer, primary): """ Private method for removing a descriptor from the event loop. It does the inverse job of _add, and also add a check in case of the fd has gone away. """ if xer in primary: notifier = primary.pop(xer) notifier.shutdown() def removeReader(self, reader): """ Remove a Selectable for notification of data available to read. """ self._remove(reader, self._reads) def removeWriter(self, writer): """ Remove a Selectable for notification of data available to write. """ self._remove(writer, self._writes) def removeAll(self): """ Remove all selectables, and return a list of them. """ rv = self._removeAll(self._reads, self._writes) return rv def getReaders(self): return self._reads.keys() def getWriters(self): return self._writes.keys() def callLater(self,howlong, *args, **kargs): rval = super(QtReactor,self).callLater(howlong, *args, **kargs) self.reactorInvocation() return rval def reactorInvocation(self): self._timer.stop() self._timer.setInterval(0) self._timer.start() def _iterate(self, delay=None, fromqt=False): """See twisted.internet.interfaces.IReactorCore.iterate. """ self.runUntilCurrent() self.doIteration(delay, fromqt) iterate = _iterate def doIteration(self, delay=None, fromqt=False): 'This method is called by a Qt timer or by network activity on a file descriptor' if not self.running and self._blockApp: self._blockApp.quit() self._timer.stop() delay = max(delay, 1) if not fromqt: self.qApp.processEvents(QEventLoop.AllEvents, delay * 1000) if self.timeout() is None: timeout = 0.1 elif self.timeout() == 0: timeout = 0 else: timeout = self.timeout() self._timer.setInterval(timeout * 1000) self._timer.start() def runReturn(self, installSignalHandlers=True): self.startRunning(installSignalHandlers=installSignalHandlers) self.reactorInvocation() def run(self, installSignalHandlers=True): if self._ownApp: self._blockApp = self.qApp else: self._blockApp = QEventLoop() self.runReturn() self._blockApp.exec_()
class Fight(QObject): def __init__(self, mw): super().__init__() self._mw = mw # Кнопка "Отнять у слабого" self._css_path_button_fight = "div[class='button-big btn f1']" # Кнопка поедания Сникерса self._css_path_button_snikers = 'div[onclick*=snikers]' # Кнопка использования Тонуса self._css_path_button_use_tonus = 'div[onclick*=tonus]' # Таймер для ожидания загрузки страницы с выбором противника self._timer_enemy_load = QTimer() self._timer_enemy_load.setInterval(333) self._timer_enemy_load.timeout.connect(self._check_enemy_load) # Таймер для поиска противника self._timer_next_enemy = QTimer() self._timer_next_enemy.setInterval(1000) self._timer_next_enemy.setSingleShot(True) self._timer_next_enemy.timeout.connect(self._next_enemy) # Информация о противнике: имя, уровень, url self.enemy_name = None self.enemy_level = None self.enemy_url = None # Выигрыш / проигрыш. Если проигрыш, self.is_winner будет равен False self.received_money = None # True если победили мы, False если противник и None если ничья self.is_winner = None # Минимальная разница в уровне с противником. Эта величина вычитается из текущего уровня персонажа. self.min_diff_levels = 0 # Максимальная разница в уровне с противником. Эта величина добавляется к текущему уровню персонажа. # Нельзя нападать на противника, у которого уровень больше трех от нашего self.max_diff_levels = 3 # Сигнал вызывается, когда противник на странице найден -- например, страница загрузилась _enemy_load_finished = Signal() # Сигнал вызывается, когда противник подходит для нападения _enemy_found = Signal() def is_ready(self): """Возвращает True, если вызов метода run будет иметь смысл -- можем напасть, иначе False.""" try: # TODO: для того, чтобы метод self.fight.is_ready() работал правильно, текущим адресом должны # быть Закоулки -- метод has_snikers, используемый в is_ready работает только в Закоулках # Идем в Закоулки self._mw.alley() # TODO: рефакторинг с self._timeout_fight() if self._timeout_fight() is not None: logger.info('Напасть можно будет через %s секунд.', self._timeout_fight()) logger.info('self._timeout_fight() = %s.', self._timeout_fight()) logger.info('self.has_snickers() = %s.', self.has_snickers()) logger.info('self.is_ready() = %s.', self._timeout_fight() is None or self.has_snickers()) # True, если таймер закончился или есть Сникерс return self._timeout_fight() is None or self.has_snickers() except MoswarClosedError: raise except Exception as e: raise MoswarBotError(e) return False def _timeout_fight(self): """Функция возвращает количество оставшихся секунд до возможности напасть. Если секунд осталось 0 или меньше 0, то вернется None.""" for timeout in self._mw.doc.findAll('[id*=timeout]'): timer = timeout.attribute('timer') if timer and 'alley' in timeout.attribute('href'): timer = int(timer) return timer if timer > 0 else None def run(self): """Функция для нападения на игроков. Ищем слабого горожанина (заброшенного персонажа) -- не нужно привлекать внимание к боту. Уровень противника в пределах нашего +/- 1 """ try: if self._mw._used: logger.warn('Бот в данный момент занят процессом "%s". Выхожу из функции.', self._mw._used_process) return self._mw._used_process = "Нападение на игроков" logger.debug('Выполняю задание "%s".', self._mw._used_process) self._mw.alley() # TODO: оптимиизровать использование сникерсов -- если они есть, сразу использовать и нападать и так, # пока не будут потрачены все if not self.is_ready(): logger.debug('Нападать еще нельзя.') return self._mw._used = True # TODO: если есть тонус, использовать, чтобы сразу напасть # TODO: флаг на разрешение использования тонуса, чтобы сразу напасть # self.use_tonus() # Если не получилось съесть Сникерс, восстанавливаем по старинке if not self.eat_snickers(): if self._mw.current_hp() < self._mw.max_hp(): self._mw.restore_hp.run() logger.debug('Нажимаю на кнопку "Отнять у слабого".') # TODO: в одном из запусков дальше этой строки, похоже дело не пошло, возможно, страница с кнопкой # не прогрузилась # Кликаем на кнопку "Отнять у слабого" self._mw.click_tag(self._css_path_button_fight) # Если не нашли подходящего противника, смотрим следующего if not self._check_enemy(): self._timer_next_enemy.start() # Ожидаем пока противник не будет найден loop = QEventLoop() self._enemy_found.connect(loop.quit) loop.exec_() logger.debug('Нападаем на "%s" [%s]: %s.', self.enemy_name, self.enemy_level, self.enemy_url) # Кликаем на кнопку "Напасть" self._mw.click_tag('.button-fight a') # Перемотка битвы forward = '#controls-forward' # Ждем пока после клика прогрузится страница и появится элемент Waitable(self._mw).wait(forward) # Перематываем бой self._mw.click_tag(forward) # Обрабатываем результаты боя self.handle_results() except MoswarClosedError: raise except Exception as e: raise MoswarBotError(e) finally: self._mw._used = False def name_winner(self): """Функция возвращает имя победителя в драке.""" try: name = self._mw.doc.findFirst('.result div').toPlainText() name = name.replace('Победитель:', '') name = name[:name.rindex('[')] return name.strip() except Exception as e: raise MoswarElementIsMissError(e) def handle_results(self): """Обработка результата боя.""" result = '.result' # Ждем пока после клика прогрузится страница и появится элемент Waitable(self._mw).wait(result) # Найдем элемент, в котором будут все результаты боя result = self._mw.doc.findFirst(result) if 'Ничья!' in result.toPlainText(): self.is_winner = None self.received_money = 0 logger.debug('Результат боя: Ничья.') return # Проверим по именам кто победил self.is_winner = self._mw.name() == self.name_winner() tugriki = result.findFirst('.tugriki').toPlainText().replace(',', '') tugriki = int(tugriki) self.received_money = tugriki # Сначала покажем выигранные монет и опыт, потом все остальное. Список используется для того, чтобы # порядок вывода результата боя был в порядке добавления элементов в этот список result_item_keys = ['Монеты', 'Опыт'] result_dict = { 'Монеты': tugriki, 'Опыт': result.findFirst('.expa').toPlainText(), } neft = result.findFirst('.neft') if not neft.isNull(): result_item_keys.append('Нефть') result_dict['Нефть'] = int(neft.toPlainText()) # Искры не всегда будут -- обычно перед праздниками они появляются sparkles = result.findFirst('.sparkles') if not sparkles.isNull(): result_item_keys.append('Искры') result_dict['Искры'] = sparkles.toPlainText() for img in result.findAll('.object-thumb'): obj = img.findFirst('img').attribute('alt') count = img.findFirst('.count').toPlainText() result_dict[obj] = count result_item_keys.append(obj) result_list = list() for key in result_item_keys: result_list.append(' {}: {}'.format(key, result_dict[key])) result_str = 'Результат боя:' if not self.is_winner: result_str += ' Бой проигран. Вся награда достается противнику.' result_str += '\n' result_str += '\n'.join(result_list) logger.debug(result_str) # TODO: работает только в Закоулках def has_tonus(self): """Функция возвратит True, если можно использовать Тонус для сброса таймера, иначе False.""" button = self._mw.doc.findFirst(self._css_path_button_use_tonus) return not button.isNull() def use_tonus(self): """Функция для использования Тонуса, для сброса таймаута между драками. Возвращает True, если получилось, иначе False.""" if self.has_tonus(): logger.debug('Использую Тонус.') self._mw.click_tag(self._css_path_button_use_tonus) # TODO: если Тонуса будет не хватать, то появится окошко с предложением восстановить за плату # Ждем пока после клика прогрузится страница и появится элемент Waitable(self._mw).wait(self._css_path_button_use_tonus) return True return False # TODO: работает только в Закоулках def has_snickers(self): """Функция возвратит True, если можно съесть Сникерс, иначе False.""" button = self._mw.doc.findFirst(self._css_path_button_snikers) return not button.isNull() def eat_snickers(self): """Функция для съедания Сникерса. Возвращает True, если получилось съесть, иначе False.""" if self.has_snickers(): logger.debug('Съедаю сникерс.') self._mw.click_tag(self._css_path_button_snikers) # Ждем пока после клика прогрузится страница и появится элемент Waitable(self._mw).wait(self._css_path_button_fight) return True return False def _check_enemy_load(self): """Функция для ожидания загрузки страницы с выбором противника.""" enemy = self._mw.doc.findFirst('.fighter2') # Если нашли элемент, описывающий противника if not enemy.isNull(): self._enemy_load_finished.emit() self._timer_enemy_load.stop() def _check_enemy(self): """Функция ищет противника на текущей странице и проверяет его тип и уровень. Возвращает True если нашелся подходящий противник, иначе False. """ self._timer_enemy_load.start() loop = QEventLoop() self._enemy_load_finished.connect(loop.quit) loop.exec_() enemy = self._mw.doc.findFirst('.fighter2') # Определим тип противника -- нам нужен горожанин (нпс) is_npc = enemy.findFirst('.npc') is_npc = not is_npc.isNull() # Узнаем уровень противника level = enemy.findFirst('.level') level = level.toPlainText() level = level.replace('[', '').replace(']', '') level = int(level) # Гиперссылка на профиль противника a = enemy.findFirst('a') # Имя противника name = a.toPlainText() # Адрес противника url = urljoin(self._mw.moswar_url, a.attribute('href')) my_level = self._mw.level() # TODO: добавить ограничение на количество попыток найти гражданина, перед тем как напасть на игрока # Проверяем, что уровень противника находится в пределе диапазона check_level = my_level - self.min_diff_levels <= level <= my_level + self.max_diff_levels found = is_npc and check_level if found: self.enemy_name = name self.enemy_level = level self.enemy_url = url return found def _next_enemy(self): """Функция для поиска следующего противника.""" logger.debug('Ищем следующего противника.') # Кликаем на кнопку "Искать другого" self._mw.click_tag(".button-search a") # Если нашли противника if self._check_enemy(): self._enemy_found.emit() self._timer_next_enemy.stop() else: # Ищем дальше self._timer_next_enemy.start()
class OverviewModel(QAbstractItemModel): def __init__(self, db, parent=None): """Creates a new instance of OverviewModel. The OverviewModel is used to display all trains for the selected travel connection.""" super(OverviewModel, self).__init__(parent) self._db = db self._columnHeaders = [ self.tr("From"), self.tr("To"), self.tr("Date"), self.tr("Departure"), self.tr("Product"), self.tr("Delay"), self.tr("Comment")] self._rescanTimer = QTimer(self) self._rescanTimer.setInterval(10000) self._rescanTimer.timeout.connect(self._rescan) self._rescanTimer.start() self._trains = [] self._trainFilter = None self._rescan() def _rescan(self): """Scans the database for changes and rebuilds the model.""" t = self._db.getTrainsFiltered(self._trainFilter) self._trains = [] for x in t: self._trains.append(x) self.reset() def setFilter(self, f): """Sets the TrainFilter to be used.""" self._trainFilter = f f.filterChanged.connect(self._rescan) def rowCount(self, parent=QModelIndex()): """Returns the row count.""" return len(self._trains) def columnCount(self, parent=QModelIndex()): """Returns the column count.""" return len(self._columnHeaders) def headerData(self, section, orientation, role=Qt.DisplayRole): """Returns the header data for the given column.""" if role == Qt.DisplayRole and section >= 0\ and section < self.columnCount(): return self._columnHeaders[section] return None def data(self, index, role=Qt.DisplayRole): """Returns the data stored under the tgiven role for the item referred by the index.""" if (not role == Qt.DisplayRole and not role == Qt.DecorationRole)\ or not index.isValid(): return None c = index.column() train = self._trains[index.row()] if role == Qt.DisplayRole: if c == 0: return train.start() if c == 1: return train.end() if c == 2: return train.date() elif c == 3: return train.departure() elif c == 4: return train.product() elif c == 5: return train.delay() if not train.delay() is None else\ self.tr("On Time") elif c == 6: return train.comment() else: if c == 5 and not train.delay() is None: return QColor(255, 0, 0) return None def index(self, row, column, parent=QModelIndex()): """Creates a new index based on given row and column""" if column >= 0 and column < self.columnCount(): return self.createIndex(row, column, None) return QModelIndex() def parent(self, index): """Always returns QModelIndex() because there is no parent/child relationship.""" return QModelIndex() def getTrains(self): """Gets all trains that match the current filter.""" return self._db.getTrainsFiltered(self._trainFilter) def getTrainsAsList(self): """Returns all trains for the current connection as a list.""" l = [] for t in self.getTrains(): l.append(t) return l
class WalletController(QObject): onError = Signal(unicode) onConnected = Signal(bool) onTxSent = Signal(bool) onBusy = Signal() onDoubleEncrypted = Signal() onBalance = Signal() onWalletUnlocked = Signal() onCurrentBalance = Signal() onCurrentLabel = Signal() onCurrentAddress = Signal() onCurrentDoubleEncrypted = Signal() onCurrentPassKey = Signal() def __init__(self,): QObject.__init__(self,) self.thread = None self._balance = '<b>0.00</b>000000' self._wallet = Wallet() self._walletUnlocked = False self.settings = Settings() self.addressesModel = AddressesModel() self.transactionsModel = TransactionsModel() self.timer = QTimer(self) self.timer.setInterval(900000) # 15 min update self.timer.timeout.connect(self.update) self.timer.start() if self.settings.storePassKey: self._currentPassKey = self.settings.passKey try: self.unlockWallet(self._currentPassKey) except: self.onError.emit('Stored pass phrase is invalid') else: self._currentPassKey = None self._currentAddressIndex = 0 @Slot() def newAddr(self): self._wallet.createAddr() self.storeWallet() self.update() @Slot(result=bool) def walletExists(self,): if not os.path.exists(os.path.join( os.path.expanduser('~'), '.bitpurse.wallet')): return False return True @Slot(unicode) def createWallet(self, passKey): self._currentPassKey = passKey self._walletUnlocked = True self._wallet.createAddr() self._wallet.store(passKey) self.update() def storeWallet(self): self._wallet.store(self._currentPassKey) self.addressesModel.setData(self._wallet.getActiveAddresses()) def getCurrentPassKey(self): return self._currentPassKey def setCurrentPassKey(self, value): self._currentPassKey = value self.settings.currentPassKey = value self.onCurrentPassKey.emit() def getCurrentBalance(self): try: return prettyPBitcoin(self._wallet.addresses[ self._currentAddressIndex].balance) except IndexError: return prettyPBitcoin(0) def getCurrentLabel(self): try: return self._wallet.addresses[ self._currentAddressIndex].label except IndexError: return '' def getCurrentAddress(self): try: return self._wallet.addresses[ self._currentAddressIndex].addr except IndexError: return '' def getCurrentDoubleEncrypted(self): try: return self._wallet.addresses[self._currentAddressIndex] \ .doubleEncrypted except IndexError: return False @Slot() def exportWithShareUI(self): import dbus import urllib import shutil shutil.copyfile(os.path.join(os.path.expanduser('~'), '.bitpurse.wallet'), os.path.join(os.path.expanduser('~'), 'MyDocs', 'bitpurse.wallet')) bus = dbus.SessionBus() shareService = bus.get_object('com.nokia.ShareUi', '/') share = shareService.get_dbus_method('share', 'com.nokia.maemo.meegotouch.ShareUiInterface') description = urllib.quote('BitPurse Wallet') title = urllib.quote('BitPurse Wallet') link = os.path.join(os.path.expanduser('~'), 'MyDocs', 'bitpurse.wallet') item = '%s'%link share([item,]) @Slot(unicode, unicode, unicode) def importFromBlockchainInfoWallet(self, guid, key, skey): if self.thread: if self.thread.isAlive(): self.onError.emit( u'Please wait, a communication is already in progress') self.thread = threading.Thread(None, self._importFromBlockchainInfoWallet, None, (guid, key, skey)) self.thread.start() @Slot(unicode, unicode, unicode) def importFromPrivateKey(self, privateKey, label='Undefined', doubleKey=''): try: self._wallet.importFromPrivateKey(self._currentPassKey, privateKey, label, doubleKey) self.storeWallet() self.onError.emit('Key imported') self.update() except Exception, err: print err import traceback traceback.print_exc() self.onError.emit(unicode(err))
class Sync(QObject): deleteServerFile = Signal((str,)) deleteLocalFile = Signal((str,)) downloadFile = Signal((str,)) uploadFile = Signal((str,)) checkServer = Signal() checkLocal = Signal() statusChanged = Signal((str,)) def __init__(self, host, ssl, parent=None): super(Sync, self).__init__(parent) self.server = ServerWatcher(host, ssl, self) self.preloaedActions = [] self.doPreemptive = empty_db() self.connected = False self.firstScan = True def setLocalDir(self, localdir): if not os.path.exists(localdir): # Creates the directory if it doesn't already exists. os.makedirs(localdir) self.local = LocalWatcher(localdir) self.server.setLocalDir(localdir) self.local.moveToThread(self.thread()) self.local.setParent(self) def connections(self): if not self.connected: self.connected = True self.server.fileAdded.connect(self.onAdded) self.server.fileChanged.connect(self.onChanged) self.server.fileDeleted.connect(self.onDeleted) self.local.fileAdded.connect(self.onAdded) self.local.fileChanged.connect(self.onChanged) self.local.fileDeleted.connect(self.onDeleted) self.deleteLocalFile.connect(self.local.deleteFile) self.deleteServerFile.connect(self.server.onDelete) self.downloadFile.connect(self.server.onDownload) self.uploadFile.connect(self.server.onUpload) @Slot() def initQueue(self): self.actionQueue = ActionQueue() self.actionTimer = QTimer() self.actionTimer.setInterval(1) self.actionTimer.timeout.connect(self.takeAction) self.actionTimer.start() @Slot() def takeAction(self): self.actionTimer.stop() if self.doPreemptive: # Preemptive check is a bit of a workaround to deal with # initial unexpected conditions: database file is gone self.doPreemptive = False self.server.preemptiveCheck = True self.local.fileAdded.connect(self.server.added) self.local.checkout() self.server.checkout() self.local.fileAdded.disconnect(self.server.added) self.server.preemptiveCheck = False for action in self.server.preemptiveActions: self.actionQueue.add(action) # After preemptive check, it is safe to do the connections # for normal operations self.connections() serverActionCount = 0 localActionCount = 0 for action in self.actionQueue: if action is not None: print 'Next action: %s' % action path = action.path do = action.action location = action.location if location == FileAction.LOCAL and (do == FileAction.UPLOAD \ or do == FileAction.DELETE): if not engine_tools.file_exists_local(path): # File no longer exists at the time of processing. # Maybe it was temporary or a quick rename. # So we ignore it print "Ignored action on " + path + ": File doesn't exist on local." continue if do == FileAction.UPLOAD: self.uploadFile.emit(path) localActionCount += 1 elif do == FileAction.DOWNLOAD: self.downloadFile.emit(path) serverActionCount += 1 elif do == FileAction.DELETE: with File.fromPath(path) as deleted_file: # `action.location` attribute only makes sense when deciding # whether to delete a file on the server or local. if location == FileAction.LOCAL: localpath = self.local.localFromServer(path) self.deleteLocalFile.emit(localpath) deleted_file.inlocal = False localActionCount += 1 elif location == FileAction.SERVER: self.deleteServerFile.emit(path) deleted_file.inserver = False serverActionCount += 1 self.actionQueue.clear() # Scan server for file changes self.statusChanged.emit('Scanning remote files for changes') self.server.checkout() if self.firstScan: # First do a full scan to check for offline changes. # From there we will rely on real time notifications watchdog. self.firstScan = False self.statusChanged.emit('Scanning local files for changes') self.local.checkout() self.local.startObserver() # Si Added # Since its the first scan, we should also # set the timer interval self.actionTimer.setInterval(5000) self.cleanSync() # Si Added # Set check interval intelligently. # If there's no activity there, wait longer. # Since if there's just no usage, then # no reason to take up CPU cycles. tempInterval = 0 if serverActionCount+localActionCount > 0: tempInterval = 5000 else: tempInterval = 1000 * 10 self.actionTimer.start() @Slot() def cleanSync(self): """ Removes entries from the database for deleted files """ session = Session() session.query(File).filter(File.inserver == False).filter(File.inlocal == False).delete(synchronize_session=False) session.commit() self.statusChanged.emit('Sync completed. Waiting for changes') @Slot(str, str, bool) def onChanged(self, location, serverpath, skipDeltaCheck): changed_file = File.fromPath(serverpath) action = None #if not changed_file.servermdate: # Probably a local added event that also # spawned a modified event. #return file_name_only = os.path.basename(serverpath) if engine_tools.isTemporaryFile(file_name_only): print 'File ' + serverpath + ' ignored since it is a temporary file' return print 'File ' + serverpath + ':' if changed_file.servermdate == None: mydiff = "** File Not in Server **" edit_time = "(not in server)" else: ttt = (changed_file.localmdate - changed_file.servermdate).total_seconds() mydiff = str( ttt ) edit_time = str(changed_file.servermdate) print 'Changed here %s, there %s delta %s' % ( changed_file.localmdate, edit_time, mydiff) try: if changed_file.inserver: diff = changed_file.timeDiff() MY_TOLERANCE = 10 if skipDeltaCheck == False and abs(diff) < MY_TOLERANCE: return if location == FileAction.SERVER: if changed_file.inlocal: if changed_file.localmdate < changed_file.servermdate: action = FileAction(serverpath, FileAction.DOWNLOAD, FileAction.LOCAL) else: action = FileAction(serverpath, FileAction.DOWNLOAD, FileAction.LOCAL) elif location == FileAction.LOCAL: if changed_file.inserver: try: if changed_file.servermdate < changed_file.localmdate: action = FileAction(serverpath, FileAction.UPLOAD, FileAction.SERVER) except: print 'Error:', changed_file, changed_file.servermdate, changed_file.localmdate else: action = FileAction(serverpath, FileAction.UPLOAD, FileAction.SERVER) if action is not None: self.actionQueue.add(action) except: info = traceback.format_exception(*sys.exc_info()) for i in info: sys.stderr.write(i) @Slot(str, str) def onAdded(self, location, serverpath): file_name_only = os.path.basename(serverpath) if engine_tools.isTemporaryFile(file_name_only): print 'File ' + serverpath + ' was created but ignored since it is a temporary file' return added_file = File.fromPath(serverpath) action = None if location == FileAction.SERVER and not added_file.inlocal: action = FileAction(serverpath, FileAction.DOWNLOAD, FileAction.LOCAL) elif location == FileAction.LOCAL and not added_file.inserver: action = FileAction(serverpath, FileAction.UPLOAD, FileAction.SERVER) if action is not None: self.actionQueue.add(action) @Slot(str, str) def onDeleted(self, location, serverpath): # NOTE: For temporary files, the current action is to delete it. # Reason 1: We need to remove it from the database. # Reason 2: If somehow there is a temporary file # there on the other side, then it makes sense to delete it. deleted_file = File.fromPath(serverpath) action = None if location == FileAction.SERVER: if deleted_file.inlocal: action = FileAction(serverpath, FileAction.DELETE, FileAction.LOCAL) elif location == FileAction.LOCAL: if deleted_file.inserver: action = FileAction(serverpath, FileAction.DELETE, FileAction.SERVER) if action is not None: self.actionQueue.add(action)
class WalletController(QObject): onError = Signal(unicode) onConnected = Signal(bool) onTxSent = Signal(bool) onBusy = Signal() onDoubleEncrypted = Signal() onBalance = Signal() onFiatBalance = Signal() onWalletUnlocked = Signal() onCurrentBalance = Signal() onCurrentFiatBalance = Signal() onCurrentLabel = Signal() onCurrentAddress = Signal() onCurrentDoubleEncrypted = Signal() onCurrentPassKey = Signal() onCurrentWatchOnly = Signal() def __init__(self,): QObject.__init__(self,) self.thread = None self._balance = '<b>0.00</b>000000' self._fiatSymbol = u'€' self._fiatRate = 0 self._fiatBalance = u'0 €' self._wallet = Wallet() self._wallet.onNewTransaction.connect(self.notifyNewTx) self._walletUnlocked = False self.settings = Settings() self.addressesModel = AddressesModel() self.transactionsModel = TransactionsModel() self.timer = QTimer(self) self.timer.setInterval(900000) # 15 min update self.timer.timeout.connect(self.update) self.timer.start() if self.settings.storePassKey: self._currentPassKey = self.settings.passKey try: self.unlockWallet(self._currentPassKey) except: self.onError.emit('Stored pass phrase is invalid') else: self._currentPassKey = None self._currentAddressIndex = 0 def on_event_data_received(self,*args): print 'BitPurse received DATA:', args # def notifyCallback(self): # print 'ohai! received something :)' # self.service.remove_items() def notifyNewTx(self, address, datas, amount): from eventfeed import EventFeedService, EventFeedItem service = EventFeedService('BitPurse', 'BitPurse', self.on_event_data_received) item = EventFeedItem('/usr/share/icons/hicolor/80x80/apps/bitpurse.png', 'BitPurse') item.set_body('New transaction on address %s : %f BTC' % (address, amount / float(10**8))) #item.set_custom_action(self.notifyCallback) service.add_item(item) @Slot(unicode) def newAddr(self, doubleKey): try: self._wallet.createAddr(doubleKey) self.storeWallet() self.update() except (WrongPassword, DataError), err: self.onError.emit(unicode(err))
def resizeTimer(self): ret = QTimer(self.q) ret.setSingleShot(True) ret.setInterval(200) ret.timeout.connect(self.updateSize) return ret
self.windowTitle() # generate exception app = QApplication([]) app.setQuitOnLastWindowClosed(False) lineEdit = LineEdit() lineEdit.deleteLater() if USE_SINGLESHOT: #QTimer.singleShot(1000, lineEdit.clear) #QTimer.singleShot(1000, lineEdit.purePythonMethod) QTimer.singleShot(1000, lineEdit.selectAll) # pure C++ method else: timer = QTimer(None) timer.setSingleShot(True) timer.setInterval(1000) timer.start() #timer.timeout.connect(lineEdit.clear) #timer.timeout.connect(lineEdit.purePythonMethod) timer.timeout.connect(lineEdit.selectAll) # pure C++ method QTimer.singleShot(2000, app.quit) app.exec_() print('~~~~ Application exited')
class PlotMainWindow(QWidget): """Base class for plot main windows.""" def __init__(self, U, plot, length=1, title=None): super(PlotMainWindow, self).__init__() layout = QVBoxLayout() if title: title = QLabel('<b>' + title + '</b>') title.setAlignment(Qt.AlignHCenter) layout.addWidget(title) layout.addWidget(plot) plot.set(U, 0) if length > 1: hlayout = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(length - 1) self.slider.setTickPosition(QSlider.TicksBelow) hlayout.addWidget(self.slider) lcd = QLCDNumber(m.ceil(m.log10(length))) lcd.setDecMode() lcd.setSegmentStyle(QLCDNumber.Flat) hlayout.addWidget(lcd) layout.addLayout(hlayout) hlayout = QHBoxLayout() toolbar = QToolBar() self.a_play = QAction(self.style().standardIcon(QStyle.SP_MediaPlay), 'Play', self) self.a_play.setCheckable(True) self.a_rewind = QAction(self.style().standardIcon(QStyle.SP_MediaSeekBackward), 'Rewind', self) self.a_toend = QAction(self.style().standardIcon(QStyle.SP_MediaSeekForward), 'End', self) self.a_step_backward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipBackward), 'Step Back', self) self.a_step_forward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipForward), 'Step', self) self.a_loop = QAction(self.style().standardIcon(QStyle.SP_BrowserReload), 'Loop', self) self.a_loop.setCheckable(True) toolbar.addAction(self.a_play) toolbar.addAction(self.a_rewind) toolbar.addAction(self.a_toend) toolbar.addAction(self.a_step_backward) toolbar.addAction(self.a_step_forward) toolbar.addAction(self.a_loop) if hasattr(self, 'save'): self.a_save = QAction(self.style().standardIcon(QStyle.SP_DialogSaveButton), 'Save', self) toolbar.addAction(self.a_save) self.a_save.triggered.connect(self.save) hlayout.addWidget(toolbar) self.speed = QSlider(Qt.Horizontal) self.speed.setMinimum(0) self.speed.setMaximum(100) hlayout.addWidget(QLabel('Speed:')) hlayout.addWidget(self.speed) layout.addLayout(hlayout) self.timer = QTimer() self.timer.timeout.connect(self.update_solution) self.slider.valueChanged.connect(self.slider_changed) self.slider.valueChanged.connect(lcd.display) self.speed.valueChanged.connect(self.speed_changed) self.a_play.toggled.connect(self.toggle_play) self.a_rewind.triggered.connect(self.rewind) self.a_toend.triggered.connect(self.to_end) self.a_step_forward.triggered.connect(self.step_forward) self.a_step_backward.triggered.connect(self.step_backward) self.speed.setValue(50) elif hasattr(self, 'save'): hlayout = QHBoxLayout() toolbar = QToolBar() self.a_save = QAction(self.style().standardIcon(QStyle.SP_DialogSaveButton), 'Save', self) toolbar.addAction(self.a_save) hlayout.addWidget(toolbar) layout.addLayout(hlayout) self.a_save.triggered.connect(self.save) self.setLayout(layout) self.plot = plot self.U = U self.length = length def slider_changed(self, ind): self.plot.set(self.U, ind) def speed_changed(self, val): self.timer.setInterval(val * 20) def update_solution(self): ind = self.slider.value() + 1 if ind >= self.length: if self.a_loop.isChecked(): ind = 0 else: self.a_play.setChecked(False) return self.slider.setValue(ind) def toggle_play(self, checked): if checked: if self.slider.value() + 1 == self.length: self.slider.setValue(0) self.timer.start() else: self.timer.stop() def rewind(self): self.slider.setValue(0) def to_end(self): self.a_play.setChecked(False) self.slider.setValue(self.length - 1) def step_forward(self): self.a_play.setChecked(False) ind = self.slider.value() + 1 if ind == self.length and self.a_loop.isChecked(): ind = 0 if ind < self.length: self.slider.setValue(ind) def step_backward(self): self.a_play.setChecked(False) ind = self.slider.value() - 1 if ind == -1 and self.a_loop.isChecked(): ind = self.length - 1 if ind >= 0: self.slider.setValue(ind)
class Loader(QMainWindow): def __init__(self, parent=None): super(Loader, self).__init__(parent) self.initUI() def updateDeviceList(self): self.statusBar().showMessage("Device list updating...", timeout=STATUS_BAR_TIMEOUT) self.deviceListWidget.updateList() self.statusBar().showMessage("Device list updated finished!", timeout=STATUS_BAR_TIMEOUT) def getFileName(self, ext): fname = QFileDialog.getOpenFileName(self, 'Open file', '/home') # if fname[0]: # f = open(fname[0], 'r') # with f: # data = f.read() # self.textEdit.setText(data) def initUI(self): # textEdit = QTextEdit() # self.setCentralWidget(textEdit) # self.setStyleSheet("QGroupBox { border: 1px solid gray; padding: 5px;}"); # Action to quit program exitAction = QAction(QIcon(None), 'Quit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.close) # # Action to update device list # self.refreshAction = QAction(QIcon('img/reload.png'), 'Refresh', self) # self.refreshAction.setShortcut('F5') # self.refreshAction.setStatusTip('Refresh list of connected devices.') # self.refreshAction.triggered.connect(self.updateDeviceList) # Action to show program information helpAction = QAction(QIcon(None), 'Help', self) helpAction.setShortcut('F1') helpAction.triggered.connect(self.showHelpDialog) # Action to help aboutAction = QAction(QIcon(None), 'About', self) aboutAction.triggered.connect(self.showAboutDialog) self.statusBar() # Add the file menu menubar = self.menuBar() fileMenu = menubar.addMenu('&File') # fileMenu.addAction(self.refreshAction) fileMenu.addAction(exitAction) fileMenu = menubar.addMenu('&Help') fileMenu.addAction(helpAction) fileMenu.addAction(aboutAction) # # Add the toolbar # toolbar = self.addToolBar('Exit') # # toolbar.addAction(self.refreshAction) # toolbar.setMovable(False) # Add the main windows widgets self.deviceListWidget = DeviceList(self.programDeviceHandler, self.infoDeviceHandler, self.resetDeviceHandler) self.fileSelectorWidget = FileSelector() self.setStyleSheet(""" QStatusBar { border-top: 1px solid #CCC; } QToolBar { border-top: 1px solid #DDD; border-bottom: 1px solid #CCC; } """) gbox = QGroupBox("Connected USB devices:") gboxLayout = QVBoxLayout() gboxLayout.addWidget(self.deviceListWidget) gbox.setLayout(gboxLayout) self.refreshEvent = QTimer() self.refreshEvent.setInterval(1250) self.refreshEvent.timeout.connect(self.USBUpdate) self.refreshEvent.start() layout = QVBoxLayout() layout.addWidget(self.fileSelectorWidget) layout.addWidget(gbox) self.setCentralWidget(QWidget()) self.centralWidget().setLayout(layout) self.setMinimumSize(620, 700) self.setMaximumWidth(620) self.setWindowFlags(Qt.Window | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) self.setGeometry(300, 300, 350, 250) self.setWindowTitle('keyplus layout and firmware loader') self.show() def process_layout(self, layout_json_obj, layout_file, device_id): try: settings_gen = layout.parser.SettingsGenerator( layout_json_obj, None) layout_data = settings_gen.gen_layout_section(device_id) settings_data = settings_gen.gen_settings_section(device_id) return layout_data, settings_data except (layout.parser.ParseError, layout.parser.ParseKeycodeError) as err: error_msg_box(str(err)) self.statusBar().showMessage( 'Error parsing "{}"'.format(layout_file), timeout=STATUS_BAR_TIMEOUT * 2) return None, None def abort_update(self, target_device): try: target_device.close() except: pass self.deviceListWidget.updateList() @Slot(str) def programDeviceHandler(self, device_path): target_device = self.tryOpenDevicePath(device_path) if target_device == None: self.abort_update(target_device) return programmingMode = self.fileSelectorWidget.getProgramingInfo() if is_bootloader_device( target_device ) and programmingMode != FileSelector.ScopeFirmware: error_msg_box( "Can only upload firmware while bootloader is running. " "Either reset it, or upload a firmware hex instead") self.abort_update(target_device) return if programmingMode == FileSelector.ScopeLayout: self.statusBar().showMessage("Started updating layout", timeout=STATUS_BAR_TIMEOUT) layout_file = self.fileSelectorWidget.getLayoutFile() if layout_file == '': error_msg_box("No layout file given.") self.abort_update(target_device) return else: pass layout_json_obj = None with open(layout_file) as file_obj: try: layout_json_obj = yaml.safe_load(file_obj.read()) except Exception as err: error_msg_box("Syntax error in yaml file: " + str(err)) self.abort_update(target_device) return device_info = protocol.get_device_info(target_device) layout_data, settings_data = self.process_layout( layout_json_obj, layout_file, device_info.id) if layout_data == None or settings_data == None: return protocol.update_layout_section(target_device, layout_data) protocol.update_settings_section(target_device, settings_data, keep_rf=True) protocol.reset_device(target_device) self.statusBar().showMessage("Finished updating layout", timeout=STATUS_BAR_TIMEOUT) elif programmingMode == FileSelector.ScopeDevice: layout_file = self.fileSelectorWidget.getRFLayoutFile() rf_file = self.fileSelectorWidget.getRFFile() target_id = self.fileSelectorWidget.getTargetID() self.statusBar().showMessage("Started updating RF settings", timeout=STATUS_BAR_TIMEOUT) if layout_file == '': error_msg_box("No layout file given.") self.abort_update(target_device) return elif rf_file == '': error_msg_box("No RF settings file given.") self.abort_update(target_device) return elif target_id == None: error_msg_box("No device id file given.") self.abort_update(target_device) return layout_json_obj = None rf_json_obj = None with open(layout_file) as file_obj: try: layout_json_obj = yaml.safe_load(file_obj.read()) except Exception as err: error_msg_box("Syntax error in yaml file: " + str(err)) self.abort_update(target_device) return with open(rf_file) as file_obj: try: rf_json_obj = yaml.safe_load(file_obj.read()) except Exception as err: error_msg_box("Syntax error in yaml file: " + str(err)) self.abort_update(target_device) return try: settings_gen = layout.parser.SettingsGenerator( layout_json_obj, rf_json_obj) except ParseError as err: error_msg_box("Error Generating RF settings data: " + str(err)) self.abort_update(target_device) return layout_data = settings_gen.gen_layout_section(target_id) settings_data = settings_gen.gen_settings_section(target_id) protocol.update_settings_section(target_device, settings_data) protocol.update_layout_section(target_device, layout_data) protocol.reset_device(target_device) self.statusBar().showMessage("Finished updating RF settings", timeout=STATUS_BAR_TIMEOUT) elif programmingMode == FileSelector.ScopeFirmware: fw_file = self.fileSelectorWidget.getFirmwareFile() self.statusBar().showMessage("Starting update firmware", timeout=STATUS_BAR_TIMEOUT) if fw_file == '': error_msg_box("No firmware file given.") else: if is_xusb_bootloader_device(target_device): self.program_xusb_boot_firmware_hex(target_device, fw_file) elif is_keyplus_device(target_device): try: serial_num = target_device.serial_number boot_vid, boot_pid = protocol.enter_bootloader( target_device) self.bootloaderProgramTimer = QTimer() self.bootloaderProgramTimer.setInterval(3000) self.bootloaderProgramTimer.setSingleShot(True) self.bootloaderProgramTimer.timeout.connect( lambda: self.programFirmwareHex( boot_vid, boot_pid, serial_num, fw_file)) self.bootloaderProgramTimer.start() except (easyhid.HIDException, protocol.KBProtocolException): error_msg_box( "Programming hex file failed: '{}'".format( fw_file)) else: try: target_device.close() except: pass raise Exception("Unimplementend programming mode") def programFirmwareHex(self, boot_vid, boot_pid, serial_num, file_name): device = None for i in range(1): en = easyhid.Enumeration(vid=boot_vid, pid=boot_pid).find() # Look for devices with matching serial_num number for dev in en: if dev.serial_number == serial_num: device = dev break # if a device was found with matching vid:pid, but it doesn't have # a matching serial_num number, then assume that the bootloader/firmware # doesn't set the serial_num number to the same value, so just program # the first matching device if len(en) != 0: device = en[0] break if device == None: error_msg_box("Couldn't connect to the device's bootloader") return else: if self.tryOpenDevice(device): return self.program_xusb_boot_firmware_hex(device, file_name) self.statusBar().showMessage("Finished updating firmware", timeout=STATUS_BAR_TIMEOUT) def program_xusb_boot_firmware_hex(self, device, file_name): try: xusb_boot.write_hexfile(device, file_name) except xusb_boot.BootloaderException as err: error_msg_box("Error programming the bootloader to hex file: " + str(err)) finally: device.close() def tryOpenDevicePath(self, device_path): try: device = easyhid.Enumeration().find(path=device_path)[0] device.open() return device except: msg_box( description="Failed to open device! Check it is still present " "and you have permission to write to it.", title="USB Device write error") return None def tryOpenDevice(self, device): try: device.open() return False except: msg_box( description="Failed to open device! Check it is still present " "and you have permission to write to it.", title="USB Device write error") return True @Slot(str) def resetDeviceHandler(self, device_path): device = self.tryOpenDevicePath(device_path) if device == None: return if is_keyplus_device(device): protocol.reset_device(device) elif is_xusb_bootloader_device(device): xusb_boot.reset(device) elif is_nrf24lu1p_bootloader_device(device): print("TODO: reset: ", device_path, file=sys.stderr) else: print("Can't reset device: ", device_path, file=sys.stderr) @Slot(str) def infoDeviceHandler(self, device_path): device = self.tryOpenDevicePath(device_path) if device == None: return settingsInfo = protocol.get_device_info(device) firmwareInfo = protocol.get_firmware_info(device) rfInfo = protocol.get_rf_info(device) if firmwareInfo.has_at_least_version('0.2.2'): errorInfo = protocol.get_error_info(device) else: errorInfo = None device.close() header = ["Attribute", "Value"] device_settings = [ ("Device ID", settingsInfo.id), ("Device name", settingsInfo.device_name_str()), ("Device serial number", device.serial_number), ("Last layout update", settingsInfo.timestamp_str()), ("Default report mode", settingsInfo.default_report_mode_str()), ("Matrix scan mode", settingsInfo.scan_mode_str()), ("Matrix columns", settingsInfo.col_count), ("Matrix rows", settingsInfo.row_count), ("Settings stored CRC", hex(settingsInfo.crc)), ("Settings computed CRC", hex(settingsInfo.computed_crc)), ("USB", not (settingsInfo.has_usb_disabled() or not firmwareInfo.has_fw_support_usb())), ("I2C", not (settingsInfo.has_i2c_disabled() or not firmwareInfo.has_fw_support_i2c())), ("nRF24 wireless", not (settingsInfo.has_nrf24_disabled() or not firmwareInfo.has_fw_support_nrf24())), ("Unifying mouse", not (settingsInfo.has_unifying_mouse_disabled() or not firmwareInfo.has_fw_support_unifying())), ("Bluetooth", not (settingsInfo.has_bluetooth_disabled() or not firmwareInfo.has_fw_support_bluetooth())), ("RF pipe0", binascii.hexlify(rfInfo.pipe0).decode('ascii')), ("RF pipe1", binascii.hexlify(rfInfo.pipe1).decode('ascii')), ("RF pipe2", "{:02x}".format(rfInfo.pipe2)), ("RF pipe3", "{:02x}".format(rfInfo.pipe3)), ("RF pipe4", "{:02x}".format(rfInfo.pipe4)), ("RF pipe5", "{:02x}".format(rfInfo.pipe5)), ("RF channel", str(rfInfo.channel)), ("RF auto retransmit count", str(rfInfo.arc)), ("RF data rate", protocol.data_rate_to_str(rfInfo.data_rate)), ] firmware_settings = [ ("Firmware version", "{}.{}.{}".format(firmwareInfo.version_major, firmwareInfo.version_minor, firmwareInfo.version_patch)), ("Firmware build date", str(datetime.datetime.fromtimestamp(firmwareInfo.timestamp))), ("Firmware git hash", "{:08x}".format(firmwareInfo.git_hash)), ("Layout storage size", firmwareInfo.layout_flash_size), ("Bootloader VID", "{:04x}".format(firmwareInfo.bootloader_vid)), ("Bootloader PID", "{:04x}".format(firmwareInfo.bootloader_pid)), ("Support scanning", firmwareInfo.has_fw_support_scanning()), ("Support scanning col to row", firmwareInfo.has_fw_support_scanning_col_row()), ("Support scanning row to col", firmwareInfo.has_fw_support_scanning_row_col()), ("Media keys", firmwareInfo.has_fw_support_key_media()), ("Mouse keys", firmwareInfo.has_fw_support_key_mouse()), ("Layer keys", firmwareInfo.has_fw_support_key_layers()), ("Sticky keys", firmwareInfo.has_fw_support_key_sticky()), ("Tap keys", firmwareInfo.has_fw_support_key_tap()), ("Hold keys", firmwareInfo.has_fw_support_key_hold()), ("Support 6KRO", firmwareInfo.has_fw_support_6kro()), ("Support NKRO", firmwareInfo.has_fw_support_key_hold()), ("Support indicator LEDs", firmwareInfo.has_fw_support_led_indicators()), ("Support LED backlighting", firmwareInfo.has_fw_support_led_backlighting()), ("Support ws2812 LEDs", firmwareInfo.has_fw_support_led_ws2812()), ("Support USB", firmwareInfo.has_fw_support_usb()), ("Support nRF24 wireless", firmwareInfo.has_fw_support_nrf24()), ("Support Unifying", firmwareInfo.has_fw_support_unifying()), ("Support I2C", firmwareInfo.has_fw_support_i2c()), ("Support Bluetooth", firmwareInfo.has_fw_support_bluetooth()), ] if errorInfo: error_codes = [] for code in errorInfo.get_error_codes(): error_codes.append((errorInfo.error_code_to_name(code), code)) else: error_codes = [ ('Error codes require firmware version 0.2.2 or greater', ) ] self.info_window = DeviceInformationWindow( self, header, device_settings, firmware_settings, error_codes, ) self.info_window.setModal(True) self.info_window.exec_() self.deviceListWidget.updateList() def USBUpdate(self): self.deviceListWidget.updateList() def showAboutDialog(self): QMessageBox.about(self, "About keyplus Loader", """ The keyplus layout and firmware loader. """) def showHelpDialog(self): QMessageBox.about( self, "keyplus Loader Help", """ This is the layout and firmware loader for the keyplus keyboard firmware. The layout files are *.yaml files. For documentation and examples see here: TODO The rf files are *.yaml files. For documentation and examples see here: TODO The firmware loader accepts *.hex files. For the latest keyplus firmware see here: TODO """)
def hoverTimer(self): ret = QTimer(self.q) ret.setInterval(400) ret.setSingleShot(False) ret.timeout.connect(self._hover) return ret
class Example(QtGui.QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def starty(self): data = { 'username': '******', 'msg': 'Hi from Main Gui Thread', 'random_number': 777, 'thread_number': 1 } # we convert the list into a string so the object is not connected in any way then mutate it over with ast downloader = SampleThread(str(data)) downloader.data_send.connect(self.echo) self.thread_pool = QtCore.QThreadPool() self.thread_pool.setMaxThreadCount(1) self.thread_pool.start(downloader) self.timer = QTimer() self.timer.setInterval(10000) #10 seconds self.timer.start() self.timer.timeout.connect(self.loop) #call loop every 10 seconds def loop(self): #Do Gui updating stuff here such as displaying data print 'Main Gui Loop every 10 seconds' thread_count = str(self.thread_pool.activeThreadCount()) self.console.addItem(thread_count) def initUI(self): '''Create GUI stuff here Random notes: QVBox = Vertical up/down QHBox = Horizonal left/right self.resize window height/width self.console this is our main widget to display data to the gui ''' self.resize(550, 300) # QVBox = Vertical up/down layout = QtGui.QVBoxLayout() self.console = QtGui.QListWidget() layout.addWidget(self.console) self.console.addItem( "Very Basic Gui displaying thread usage using python 2.7/Pyside ") btn = QtGui.QPushButton('Button', self) btn.clicked.connect(self.starty) layout.addWidget(btn) self.setLayout(layout) def echo(self, payload): print 'hi from echo' texty = 'payload -> ' + str(payload) self.console.addItem(texty) self.console.scrollToBottom() #scrolls down
class MapWidget(QGraphicsGeoMap): coordQueryResult = Signal(QGeoCoordinate) def __init__(self, manager): QGraphicsGeoMap.__init__(self, manager) self.coordQueryState = False self.panActive = False self.kineticTimer = QTimer() self.lastCircle = None self.lastMoveTime = None self.kineticPanSpeed = None self.panDecellerate = True self.remainingPan = QPointF() self.mouseHistory = deque([MouseHistoryEntry() for i in range(5)]) self.kineticTimer.timeout.connect(self.kineticTimerEvent) self.kineticTimer.setInterval(KINETIC_PANNING_RESOLUTION) def setMouseClickCoordQuery(self, state): self.coordQueryState = state def mousePressEvent(self, event): self.setFocus() if event.button() == Qt.LeftButton: if event.modifiers() & Qt.ControlModifier: pass else: if self.coordQueryState: self.coordQueryResult.emit(self.screenPositionToCoordinate(event.lastPos())) return self.panActive = True self.kineticTimer.stop() self.kineticPanSpeed = QPointF() self.lastMoveTime = QTime.currentTime() event.accept() def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: if self.panActive: self.panActive = False if not ENABLE_KINETIC_PANNING or self.lastMoveTime.msecsTo(QTime.currentTime()) > HOLD_TIME_THRESHOLD: return self.kineticPanSpeed = QPointF() entriesConsidered = 0 currentTime = QTime.currentTime() for entry in self.mouseHistory: if not entry.time: continue if entry.time.msecsTo(currentTime) < HOLD_TIME_THRESHOLD: self.kineticPanSpeed += entry.position entriesConsidered += 1 if entriesConsidered > 0: self.kineticPanSpeed /= entriesConsidered self.lastMoveTime = currentTime self.kineticTimer.start() self.panDecellerate = True event.accept() def mouseMoveEvent(self, event): if event.modifiers() & Qt.ControlModifier: if self.lastCircle: self.lastCircle.setCenter(self.screenPositionToCoordinate(event.pos())) elif self.panActive: currentTime = QTime.currentTime() deltaTime = self.lastMoveTime.msecsTo(currentTime) delta = event.lastPos() - event.pos() if deltaTime > 0: self.kineticPanSpeed = delta / deltaTime self.mouseHistory.popleft() self.mouseHistory.append(MouseHistoryEntry(self.kineticPanSpeed, currentTime)) self.panFloatWrapper(delta) event.accept() def kineticTimerEvent(self): currentTime = QTime.currentTime() deltaTime = self.lastMoveTime.msecsTo(currentTime) self.lastMoveTime = currentTime if self.panDecellerate: self.kineticPanSpeed *= pow(0.5, float(deltaTime / KINETIC_PANNING_HALFLIFE)) scaledSpeed = self.kineticPanSpeed * deltaTime if self.kineticPanSpeed.manhattanLength() < KINETIC_PAN_SPEED_THRESHOLD: self.kineticTimer.stop() return self.panFloatWrapper(scaledSpeed) def panFloatWrapper(self, delta): self.remainingPan += delta move = self.remainingPan.toPoint() self.pan(move.x(), move.y()) self.remainingPan -= move def mouseDoubleClickEvent(self, event): self.setFocus() self.pan(event.lastPos().x() - self.size().width() / 2.0, event.lastPos().y() - self.size().height() / 2.0) if self.zoomLevel() < self.maximumZoomLevel(): self.setZoomLevel(self.zoomLevel() + 1) event.accept() def keyPressEvent(self, event): if event.key() == Qt.Key_Minus: if self.zoomLevel() > self.minimumZoomLevel(): self.setZoomLevel(self.zoomLevel() - 1) elif event.key() == Qt.Key_Plus: if self.zoomLevel() < self.maximumZoomLevel(): self.setZoomLevel(self.zoomLevel() + 1) elif event.key() == Qt.Key_T: if self.mapType() == QGraphicsGeoMap.StreetMap: self.setMapType(QGraphicsGeoMap.SatelliteMapDay) elif self.mapType() == QGraphicsGeoMap.SatelliteMapDay: self.setMapType(QGraphicsGeoMap.StreetMap) event.accept() def wheelEvent(self, event): if event.delta() > 0: if self.zoomLevel() < self.maximumZoomLevel(): self.setZoomLevel(self.zoomLevel() + 1) else: if self.zoomLevel() > self.minimumZoomLevel(): self.setZoomLevel(self.zoomLevel() - 1) event.accept()
class QtReactor(posixbase.PosixReactorBase): implements(IReactorFDSet) def __init__(self): self._reads = {} self._writes = {} self._notifiers = {} self._timer = QTimer() self._timer.setSingleShot(True) QObject.connect(self._timer, SIGNAL("timeout()"), self.iterate) if QCoreApplication.instance() is None: # Application Object has not been started yet self.qApp = QCoreApplication([]) self._ownApp = True else: self.qApp = QCoreApplication.instance() self._ownApp = False self._blockApp = None posixbase.PosixReactorBase.__init__(self) def _add(self, xer, primary, type): """ Private method for adding a descriptor from the event loop. It takes care of adding it if new or modifying it if already added for another state (read -> read/write for example). """ if xer not in primary: primary[xer] = TwistedSocketNotifier(None, self, xer, type) def addReader(self, reader): """ Add a FileDescriptor for notification of data available to read. """ self._add(reader, self._reads, QSocketNotifier.Read) def addWriter(self, writer): """ Add a FileDescriptor for notification of data available to write. """ self._add(writer, self._writes, QSocketNotifier.Write) def _remove(self, xer, primary): """ Private method for removing a descriptor from the event loop. It does the inverse job of _add, and also add a check in case of the fd has gone away. """ if xer in primary: notifier = primary.pop(xer) notifier.shutdown() def removeReader(self, reader): """ Remove a Selectable for notification of data available to read. """ self._remove(reader, self._reads) def removeWriter(self, writer): """ Remove a Selectable for notification of data available to write. """ self._remove(writer, self._writes) def removeAll(self): """ Remove all selectables, and return a list of them. """ rv = self._removeAll(self._reads, self._writes) return rv def getReaders(self): return self._reads.keys() def getWriters(self): return self._writes.keys() def callLater(self, howlong, *args, **kargs): rval = super(QtReactor, self).callLater(howlong, *args, **kargs) self.reactorInvocation() return rval def reactorInvocation(self): self._timer.stop() self._timer.setInterval(0) self._timer.start() def _iterate(self, delay=None, fromqt=False): """See twisted.internet.interfaces.IReactorCore.iterate. """ self.runUntilCurrent() self.doIteration(delay, fromqt) iterate = _iterate def doIteration(self, delay=None, fromqt=False): 'This method is called by a Qt timer or by network activity on a file descriptor' if not self.running and self._blockApp: self._blockApp.quit() self._timer.stop() delay = max(delay, 1) if not fromqt: self.qApp.processEvents(QEventLoop.AllEvents, delay * 1000) if self.timeout() is None: timeout = 0.1 elif self.timeout() == 0: timeout = 0 else: timeout = self.timeout() self._timer.setInterval(timeout * 1000) self._timer.start() def runReturn(self, installSignalHandlers=True): self.startRunning(installSignalHandlers=installSignalHandlers) self.reactorInvocation() def run(self, installSignalHandlers=True): if self._ownApp: self._blockApp = self.qApp else: self._blockApp = QEventLoop() self.runReturn() self._blockApp.exec_()