def __delitem__(self, key): """ Delete the setting for key. If key is a group remove the whole group. .. note:: defaults cannot be deleted they are instead reverted to their original state. """ if key not in self: raise KeyError(key) if self.isgroup(key): group = self.group(key) for key in group: del group[key] else: fullkey = self.__key(key) oldValue = self.get(key) if self.__store.contains(fullkey): self.__store.remove(fullkey) newValue = None if fullkey in self.__defaults: newValue = self.__defaults[fullkey].default_value etype = SettingChangedEvent.SettingChanged else: etype = SettingChangedEvent.SettingRemoved QCoreApplication.sendEvent( self, SettingChangedEvent(etype, key, newValue, oldValue) )
def test_methodinvoke(self): executor = ThreadExecutor() state = [None, None] class StateSetter(QObject): @Slot(object) def set_state(self, value): state[0] = value state[1] = QThread.currentThread() def func(callback): callback(QThread.currentThread()) obj = StateSetter() f1 = executor.submit(func, methodinvoke(obj, "set_state", (object,))) f1.result() # So invoked method can be called QCoreApplication.processEvents() self.assertIs(state[1], QThread.currentThread(), "set_state was called from the wrong thread") self.assertIsNot(state[0], QThread.currentThread(), "set_state was invoked in the main thread") executor.shutdown(wait=True)
def mousePressEvent(self, event): anchor_item = self.scene.item_at(event.scenePos(), items.NodeAnchorItem, buttons=Qt.LeftButton) if anchor_item and event.button() == Qt.LeftButton: # Start a new link starting at item self.from_item = anchor_item.parentNodeItem() if isinstance(anchor_item, items.SourceAnchorItem): self.direction = NewLinkAction.FROM_SOURCE self.source_item = self.from_item else: self.direction = NewLinkAction.FROM_SINK self.sink_item = self.from_item event.accept() helpevent = QuickHelpTipEvent( self.tr("Create a new link"), self. tr('<h3>Create new link</h3>' '<p>Drag a link to an existing node or release on ' 'an empty spot to create a new node.</p>' '<p>Hold Shift when releasing the mouse button to ' 'edit connections.</p>' # '<a href="help://orange-canvas/create-new-links">' # 'More ...</a>' )) QCoreApplication.postEvent(self.document, helpevent) return True else: # Whoever put us in charge did not know what he was doing. self.cancel(self.ErrorReason) return False
def add_link(self, link): # type: (SchemeLink) -> None """ Add a `link` to the scheme. Parameters ---------- link : :class:`.SchemeLink` An initialized link instance to add to the scheme. """ assert isinstance(link, SchemeLink) self.check_connect(link) self.__links.append(link) ev = events.LinkEvent(events.LinkEvent.LinkAdded, link) QCoreApplication.sendEvent(self, ev) log.info("Added link %r (%r) -> %r (%r) to scheme %r." % \ (link.source_node.title, link.source_channel.name, link.sink_node.title, link.sink_channel.name, self.title) ) self.link_added.emit(link)
def __setitem__(self, key, value): """ Set the setting for key. """ if not isinstance(key, str): raise TypeError(key) fullkey = self.__key(key) value_type = None if fullkey in self.__defaults: value_type = self.__defaults[fullkey].value_type if not isinstance(value, value_type): if not isinstance(value, value_type): raise TypeError("Expected {0!r} got {1!r}".format( value_type.__name__, type(value).__name__) ) if key in self: oldValue = self.get(key) etype = SettingChangedEvent.SettingChanged else: oldValue = None etype = SettingChangedEvent.SettingAdded self.__setValue(fullkey, value, value_type) QCoreApplication.sendEvent( self, SettingChangedEvent(etype, key, value, oldValue) )
def _QTest_qWaitForWindowActive(widget, timeout=1000): # A Qt5 compatible (probably) QTest.qWaitForWindowActive(QWidget, int) # (mostly copied from qtestsystem.h in qt5/qtbase) from AnyQt.QtCore import \ Qt, QCoreApplication, QEventLoop, QElapsedTimer, QEvent window = widget.window() timer = QElapsedTimer() timer.start() while not window.isActiveWindow(): remaining = timeout - timer.elapsed() if remaining <= 0: break QCoreApplication.processEvents(QEventLoop.AllEvents, remaining) QCoreApplication.sendPostedEvents(None, QEvent.DeferredDelete) QTest.qSleep(10) # See the explanation in qtestsystem.h if window.isActiveWindow(): wait_no = 0 while window.pos().isNull(): if wait_no > timeout // 10: break wait_no += 1 QTest.qWait(10) return window.isActiveWindow()
def end(self): self.cleanup() # Remove the help tip set in mousePressEvent self.macro = None helpevent = QuickHelpTipEvent("", "") QCoreApplication.postEvent(self.document, helpevent) UserInteraction.end(self)
def test_methodinvoke(self): executor = ThreadExecutor() state = [None, None] class StateSetter(QObject): @Slot(object) def set_state(self, value): state[0] = value state[1] = QThread.currentThread() def func(callback): callback(QThread.currentThread()) obj = StateSetter() f1 = executor.submit(func, methodinvoke(obj, "set_state", (object, ))) f1.result() # So invoked method can be called QCoreApplication.processEvents() self.assertIs(state[1], QThread.currentThread(), "set_state was called from the wrong thread") self.assertIsNot(state[0], QThread.currentThread(), "set_state was invoked in the main thread") executor.shutdown(wait=True)
def add_link(self, link): """ Add a `link` to the scheme. Parameters ---------- link : :class:`.SchemeLink` An initialized link instance to add to the scheme. """ check_type(link, SchemeLink) self.check_connect(link) self.__links.append(link) ev = events.LinkEvent(events.LinkEvent.LinkAdded, link) QCoreApplication.sendEvent(self, ev) log.info("Added link %r (%r) -> %r (%r) to scheme %r." % \ (link.source_node.title, link.source_channel.name, link.sink_node.title, link.sink_channel.name, self.title) ) self.link_added.emit(link)
def __setitem__(self, key, value): """ Set the setting for key. """ if not isinstance(key, str): raise TypeError(key) fullkey = self.__key(key) if fullkey in self.__defaults: value_type = self.__defaults[fullkey].value_type if not isinstance(value, value_type): if not isinstance(value, value_type): raise TypeError("Expected {0!r} got {1!r}".format( value_type.__name__, type(value).__name__) ) if key in self: oldValue = self.get(key) etype = SettingChangedEvent.SettingChanged else: oldValue = None etype = SettingChangedEvent.SettingAdded self.__store.setValue(fullkey, value) QCoreApplication.sendEvent( self, SettingChangedEvent(etype, key, value, oldValue) )
def mousePressEvent(self, event): anchor_item = self.scene.item_at(event.scenePos(), items.NodeAnchorItem, buttons=Qt.LeftButton) if anchor_item and event.button() == Qt.LeftButton: # Start a new link starting at item self.from_item = anchor_item.parentNodeItem() if isinstance(anchor_item, items.SourceAnchorItem): self.direction = NewLinkAction.FROM_SOURCE self.source_item = self.from_item else: self.direction = NewLinkAction.FROM_SINK self.sink_item = self.from_item event.accept() helpevent = QuickHelpTipEvent( self.tr("Create a new link"), self.tr('<h3>Create new link</h3>' '<p>Drag a link to an existing node or release on ' 'an empty spot to create a new node.</p>' '<p>Hold Shift when releasing the mouse button to ' 'edit connections.</p>' # '<a href="help://orange-canvas/create-new-links">' # 'More ...</a>' ) ) QCoreApplication.postEvent(self.document, helpevent) return True else: # Whoever put us in charge did not know what he was doing. self.cancel(self.ErrorReason) return False
def viewportEvent(self, event: QEvent) -> bool: if event.type() == QEvent.Wheel: # delegate wheel events to parent StickyGraphicsView parent = self.parent().parent().parent() if isinstance(parent, StickyGraphicsView): QCoreApplication.sendEvent(parent.viewport(), event) if event.isAccepted(): return True return super().viewportEvent(event)
class CoreAppTestCase(unittest.TestCase): def setUp(self): self.app = QCoreApplication.instance() if self.app is None: self.app = QCoreApplication([]) def tearDown(self): self.app.processEvents() del self.app
class TestTask(unittest.TestCase): def setUp(self): self.app = QCoreApplication([]) def test_task(self): results = [] task = Task(function=QThread.currentThread) task.resultReady.connect(results.append) task.start() self.app.processEvents() self.assertSequenceEqual(results, [QThread.currentThread()]) results = [] thread = QThread() thread.start() task = Task(function=QThread.currentThread) task.moveToThread(thread) self.assertIsNot(task.thread(), QThread.currentThread()) self.assertIs(task.thread(), thread) task.resultReady.connect(results.append, Qt.DirectConnection) task.start() f = task.future() self.assertIsNot(f.result(3), QThread.currentThread()) self.assertIs(f.result(3), results[-1]) def test_executor(self): executor = ThreadExecutor() f = executor.submit(QThread.currentThread) self.assertIsNot(f.result(3), QThread.currentThread()) f = executor.submit(lambda: 1 / 0) with self.assertRaises(ZeroDivisionError): f.result() results = [] task = Task(function=QThread.currentThread) task.resultReady.connect(results.append, Qt.DirectConnection) f = executor.submit(task) self.assertIsNot(f.result(3), QThread.currentThread()) executor.shutdown()
class TestTask(unittest.TestCase): def setUp(self): self.app = QCoreApplication([]) def test_task(self): results = [] task = Task(function=QThread.currentThread) task.resultReady.connect(results.append) task.start() self.app.processEvents() self.assertSequenceEqual(results, [QThread.currentThread()]) results = [] thread = QThread() thread.start() task = Task(function=QThread.currentThread) task.moveToThread(thread) self.assertIsNot(task.thread(), QThread.currentThread()) self.assertIs(task.thread(), thread) task.resultReady.connect(results.append, Qt.DirectConnection) task.start() f = task.future() self.assertIsNot(f.result(3), QThread.currentThread()) self.assertIs(f.result(3), results[-1]) def test_executor(self): executor = ThreadExecutor() f = executor.submit(QThread.currentThread) self.assertIsNot(f.result(3), QThread.currentThread()) f = executor.submit(lambda: 1 / 0) with self.assertRaises(ZeroDivisionError): f.result() results = [] task = Task(function=QThread.currentThread) task.resultReady.connect(results.append, Qt.DirectConnection) f = executor.submit_task(task) self.assertIsNot(f.result(3), QThread.currentThread()) executor.shutdown()
def contextMenu(widget: QWidget, pos: QPoint, delay=-1) -> None: """ Simulates a contextMenuEvent on the widget. """ ev = QContextMenuEvent(QContextMenuEvent.Mouse, pos, widget.mapToGlobal(pos)) if delay > 0: QTest.qWait(delay) QCoreApplication.sendEvent(widget, ev)
def _stateChanged(self, future, state): """ The `future` state has changed (called by :class:`Future`). """ ev = StateChangedEvent(state) if self.thread() is QThread.currentThread(): QCoreApplication.sendEvent(self, ev) else: QCoreApplication.postEvent(self, ev)
def __add_widget_for_node(self, node): # type: (SchemeNode) -> None item = self.__item_for_node.get(node) if item is not None: return if node not in self.__workflow.nodes: return if node in self.__init_queue: self.__init_queue.remove(node) item = Item(node, None, -1) # Insert on the node -> item mapping. self.__item_for_node[node] = item log.debug("Creating widget for node %s", node) try: w = self.create_widget_for_node(node) except Exception: # pylint: disable=broad-except log.critical("", exc_info=True) lines = traceback.format_exception(*sys.exc_info()) text = "".join(lines) errorwidget = QLabel( textInteractionFlags=Qt.TextSelectableByMouse, wordWrap=True, objectName="widgetmanager-error-placeholder", text="<pre>" + escape(text) + "</pre>" ) item.errorwidget = errorwidget node.set_state_message(UserMessage(text, UserMessage.Error, 0)) return else: item.widget = w self.__item_for_widget[w] = item self.__set_float_on_top_flag(w) w.installEventFilter(self.__activation_monitor) # Up shortcut (activate/open parent) up_shortcut = QShortcut( QKeySequence(Qt.ControlModifier + Qt.Key_Up), w) up_shortcut.activated.connect(self.__on_activate_parent) # send all the post creation notification events workflow = self.__workflow assert workflow is not None inputs = workflow.find_links(sink_node=node) for link in inputs: ev = LinkEvent(LinkEvent.InputLinkAdded, link) QCoreApplication.sendEvent(w, ev) outputs = workflow.find_links(source_node=node) for link in outputs: ev = LinkEvent(LinkEvent.OutputLinkAdded, link) QCoreApplication.sendEvent(w, ev) self.widget_for_node_added.emit(node, w)
def set_runtime_env(self, key, value): # type: (str, Any) -> None """ Set a runtime environment variable `key` to `value` """ oldvalue = self.__env.get(key, None) if value != oldvalue: self.__env[key] = value QCoreApplication.sendEvent( self, WorkflowEnvChanged(key, value, oldvalue)) self.runtime_env_changed.emit(key, value, oldvalue)
def end(self): self.down_pos = None self.arrow_item = None self.annotation = None self.document.view().setCursor(Qt.ArrowCursor) # Clear the help tip helpevent = QuickHelpTipEvent("", "") QCoreApplication.postEvent(self.document, helpevent) UserInteraction.end(self)
def remove_annotation(self, annotation): # type: (BaseSchemeAnnotation) -> None """ Remove the `annotation` instance from the scheme. """ index = self.__annotations.index(annotation) self.__annotations.pop(index) ev = AnnotationEvent(AnnotationEvent.AnnotationRemoved, annotation, index) QCoreApplication.sendEvent(self, ev) self.annotation_removed.emit(annotation)
def test_threadsafe(self): output = OutputView() output.resize(500, 300) output.show() blue_formater = output.formated(color=Qt.blue) red_formater = output.formated(color=Qt.red) correct = [] def check_thread(*args): correct.append(QThread.currentThread() == self.app.thread()) blue = TextStream() blue.stream.connect(blue_formater.write) blue.stream.connect(check_thread) red = TextStream() red.stream.connect(red_formater.write) red.stream.connect(check_thread) def printer(i): if i % 12 == 0: fizzbuz = "fizzbuz" elif i % 4 == 0: fizzbuz = "buz" elif i % 3 == 0: fizzbuz = "fizz" else: fizzbuz = str(i) if i % 2: writer = blue else: writer = red writer.write("Greetings from thread {0}. " "This is {1}\n".format(current_thread().name, fizzbuz)) pool = multiprocessing.pool.ThreadPool(100) res = pool.map_async(printer, range(10000)) self.app.exec_() res.wait() # force all pending enqueued emits QCoreApplication.sendPostedEvents(blue, QEvent.MetaCall) QCoreApplication.sendPostedEvents(red, QEvent.MetaCall) self.app.processEvents() self.assertTrue(all(correct)) self.assertEqual(len(correct), 10000)
def remove_annotation(self, annotation): # type: (BaseSchemeAnnotation) -> None """ Remove the `annotation` instance from the scheme. """ self.__annotations.remove(annotation) ev = events.AnnotationEvent(events.AnnotationEvent.AnnotationRemoved, annotation) QCoreApplication.sendEvent(self, ev) self.annotation_removed.emit(annotation)
def __on_link_removed(self, link): # type: (SchemeLink) -> None assert link.source_node in self.__workflow.nodes assert link.sink_node in self.__workflow.nodes source = self.__item_for_widget.get(link.source_node) sink = self.__item_for_widget.get(link.sink_node) # notify the node gui of an removed link if source is not None: ev = LinkEvent(LinkEvent.OutputLinkRemoved, link) QCoreApplication.sendEvent(source.widget, ev) if sink is not None: ev = LinkEvent(LinkEvent.InputLinkRemoved, link) QCoreApplication.sendEvent(sink.widget, ev)
def test_threadsafe(self): output = OutputView() output.resize(500, 300) output.show() blue_formater = output.formatted(color=Qt.blue) red_formater = output.formatted(color=Qt.red) correct = [] def check_thread(*args): correct.append(QThread.currentThread() == self.app.thread()) blue = TextStream() blue.stream.connect(blue_formater.write) blue.stream.connect(check_thread) red = TextStream() red.stream.connect(red_formater.write) red.stream.connect(check_thread) def printer(i): if i % 12 == 0: fizzbuz = "fizzbuz" elif i % 4 == 0: fizzbuz = "buz" elif i % 3 == 0: fizzbuz = "fizz" else: fizzbuz = str(i) if i % 2: writer = blue else: writer = red writer.write("Greetings from thread {0}. " "This is {1}\n".format(current_thread().name, fizzbuz)) pool = multiprocessing.pool.ThreadPool(100) res = pool.map_async(printer, range(10000)) self.qWait() res.wait() # force all pending enqueued emits QCoreApplication.sendPostedEvents(blue, QEvent.MetaCall) QCoreApplication.sendPostedEvents(red, QEvent.MetaCall) self.app.processEvents() self.assertTrue(all(correct)) self.assertEqual(len(correct), 10000) pool.close()
def flush(self): """ Flush all pending signal emits currently enqueued. Must only ever be called from the thread this object lives in (:func:`QObject.thread()`). """ if QThread.currentThread() is not self.thread(): raise RuntimeError("`flush()` called from a wrong thread.") # NOTE: QEvent.MetaCall is the event implementing the # `Qt.QueuedConnection` method invocation. QCoreApplication.sendPostedEvents(self, QEvent.MetaCall)
def remove_annotation(self, annotation): """ Remove the `annotation` instance from the scheme. """ check_arg(annotation in self.__annotations, "Annotation is not in the scheme.") self.__annotations.remove(annotation) ev = events.AnnotationEvent(events.AnnotationEvent.AnnotationRemoved, annotation) QCoreApplication.sendEvent(self, ev) self.annotation_removed.emit(annotation)
def __on_link_removed(self, link): # type: (SchemeLink) -> None assert self.__workflow is not None assert link.source_node in self.__workflow.nodes assert link.sink_node in self.__workflow.nodes source = self.__item_for_node.get(link.source_node) sink = self.__item_for_node.get(link.sink_node) # notify the node gui of an removed link if source is not None and source.widget is not None: ev = LinkEvent(LinkEvent.OutputLinkRemoved, link) QCoreApplication.sendEvent(source.widget, ev) if sink is not None and sink.widget is not None: ev = LinkEvent(LinkEvent.InputLinkRemoved, link) QCoreApplication.sendEvent(sink.widget, ev)
def on_done(f): assert f is future selfref = selfweakref() if selfref is None: return try: QCoreApplication.postEvent( selfref, QEvent(FutureWatcher.__FutureDone)) except RuntimeError: # Ignore RuntimeErrors (when C++ side of QObject is deleted) # (? Use QObject.destroyed and remove the done callback ?) pass
def start(self): self.document.view().setCursor(Qt.CrossCursor) helpevent = QuickHelpTipEvent( self.tr("Click and drag to create a new arrow"), self.tr('<h3>New arrow annotation</h3>' '<p>Click and drag to create a new arrow annotation.</p>' # '<a href="help://orange-canvas/arrow-annotations>' # 'More ...</a>' ) ) QCoreApplication.postEvent(self.document, helpevent) UserInteraction.start(self)
def insert_annotation(self, index: int, annotation: Annotation) -> None: """ Insert `annotation` into `self.annotations` at the specified position `index`. """ assert isinstance(annotation, BaseSchemeAnnotation) if annotation in self.__annotations: raise ValueError("Cannot add the same annotation multiple times") self.__annotations.insert(index, annotation) ev = AnnotationEvent(AnnotationEvent.AnnotationAdded, annotation, index) QCoreApplication.sendEvent(self, ev) self.annotation_inserted.emit(index, annotation) self.annotation_added.emit(annotation)
def insert_node(self, index: int, node: Node): """ Insert `node` into self.nodes at the specified position `index` """ assert isinstance(node, SchemeNode) check_arg(node not in self.__nodes, "Node already in scheme.") self.__nodes.insert(index, node) ev = NodeEvent(NodeEvent.NodeAdded, node, index) QCoreApplication.sendEvent(self, ev) log.info("Added node %r to scheme %r." % (node.title, self.title)) self.node_added.emit(node) self.node_inserted.emit(index, node)
def on_done(f): assert f is future selfref = selfweakref() if selfref is None: return try: QCoreApplication.postEvent(selfref, QEvent(FutureWatcher.__FutureDone)) except RuntimeError: # Ignore RuntimeErrors (when C++ side of QObject is deleted) # (? Use QObject.destroyed and remove the done callback ?) pass
def add_annotation(self, annotation): # type: (BaseSchemeAnnotation) -> None """ Add an annotation (:class:`BaseSchemeAnnotation` subclass) instance to the scheme. """ assert isinstance(annotation, BaseSchemeAnnotation) if annotation in self.__annotations: raise ValueError("Cannot add the same annotation multiple times") self.__annotations.append(annotation) ev = events.AnnotationEvent(events.AnnotationEvent.AnnotationAdded, annotation) QCoreApplication.sendEvent(self, ev) self.annotation_added.emit(annotation)
def _QTest_qWait(timeout): from AnyQt.QtCore import Qt, QCoreApplication, QEvent, QEventLoop, QDeadlineTimer remaining = timeout deadline = QDeadlineTimer(remaining, Qt.PreciseTimer) while True: QCoreApplication.processEvents(QEventLoop.AllEvents, remaining) QCoreApplication.sendPostedEvents(None, QEvent.DeferredDelete) remaining = deadline.remainingTime() if remaining <= 0: break QTest.qSleep(min(10, remaining)) remaining = deadline.remainingTime() if remaining <= 0: break
def start(self): self.document.view().setCursor(Qt.CrossCursor) helpevent = QuickHelpTipEvent( self.tr("Click and drag to create a new arrow"), self. tr('<h3>New arrow annotation</h3>' '<p>Click and drag to create a new arrow annotation.</p>' # '<a href="help://orange-canvas/arrow-annotations>' # 'More ...</a>' )) QCoreApplication.postEvent(self.document, helpevent) UserInteraction.start(self)
def start(self): self.document.view().setCursor(Qt.CrossCursor) helpevent = QuickHelpTipEvent( self.tr("单击并拖动,创建新的箭头"), self. tr('<h3>新建箭头批注</h3>' '<p>单击并拖动,创建新的箭头批注。</p>' # '<a href="help://orange-canvas/arrow-annotations>' #'More ...</a>' )) QCoreApplication.postEvent(self.document, helpevent) UserInteraction.start(self)
def start(self): self.document.view().setCursor(Qt.CrossCursor) helpevent = QuickHelpTipEvent( self.tr("单击此处,创建新的文本批注"), self. tr('<h3>新建文本批注</h3>' '<p>在画布上单击(并拖动以调整大小),创建新的文本注释项。</p>' # '<a href="help://orange-canvas/text-annotations">' # 'More ...</a>' )) QCoreApplication.postEvent(self.document, helpevent) UserInteraction.start(self)
def end(self): if self.control is not None: self.scene.removeItem(self.control) self.control = None self.down_pos = None self.annotation_item = None self.annotation = None self.document.view().setCursor(Qt.ArrowCursor) # Clear the help tip helpevent = QuickHelpTipEvent("", "") QCoreApplication.postEvent(self.document, helpevent) UserInteraction.end(self)
def start(self): self.document.view().setCursor(Qt.CrossCursor) helpevent = QuickHelpTipEvent( self.tr("Click to create a new text annotation"), self. tr('<h3>New text annotation</h3>' '<p>Click (and drag to resize) on the canvas to create ' 'a new text annotation item.</p>' # '<a href="help://orange-canvas/text-annotations">' # 'More ...</a>' )) QCoreApplication.postEvent(self.document, helpevent) UserInteraction.start(self)
def add_annotation(self, annotation): """ Add an annotation (:class:`BaseSchemeAnnotation` subclass) instance to the scheme. """ check_arg(annotation not in self.__annotations, "Cannot add the same annotation multiple times.") check_type(annotation, BaseSchemeAnnotation) self.__annotations.append(annotation) ev = events.AnnotationEvent(events.AnnotationEvent.AnnotationAdded, annotation) QCoreApplication.sendEvent(self, ev) self.annotation_added.emit(annotation)
def start(self): self.document.view().setCursor(Qt.CrossCursor) helpevent = QuickHelpTipEvent( self.tr("Click to create a new text annotation"), self.tr('<h3>New text annotation</h3>' '<p>Click (and drag to resize) on the canvas to create ' 'a new text annotation item.</p>' # '<a href="help://orange-canvas/text-annotations">' # 'More ...</a>' ) ) QCoreApplication.postEvent(self.document, helpevent) UserInteraction.start(self)
def splash_screen(): """ """ pm = QPixmap( pkg_resources.resource_filename( __name__, "icons/orange-splash-screen.png") ) version = QCoreApplication.applicationVersion() size = 21 if len(version) < 5 else 16 font = QFont("Helvetica") font.setPixelSize(size) font.setBold(True) font.setItalic(True) font.setLetterSpacing(QFont.AbsoluteSpacing, 2) metrics = QFontMetrics(font) br = metrics.boundingRect(version).adjusted(-5, 0, 5, 0) br.moveCenter(QPoint(436, 224)) p = QPainter(pm) p.setRenderHint(QPainter.Antialiasing) p.setRenderHint(QPainter.TextAntialiasing) p.setFont(font) p.setPen(QColor("#231F20")) p.drawText(br, Qt.AlignCenter, version) p.end() return pm, QRect(88, 193, 200, 20)
def __on_help_request(self): """ Help shortcut was pressed. We send a `QWhatsThisClickedEvent` to the scheme and hope someone responds to it. """ # Sender is the QShortcut, and parent the OWBaseWidget widget = self.sender().parent() try: node = self.node_for_widget(widget) except KeyError: pass else: qualified_name = node.description.qualified_name help_url = "help://search?" + urlencode({"id": qualified_name}) event = QWhatsThisClickedEvent(help_url) QCoreApplication.sendEvent(self.scheme(), event)
def process_signals_for_widget(self, node, widget, signals): """ Process new signals for the OWBaseWidget. """ # This replaces the old OWBaseWidget.processSignals method if sip.isdeleted(widget): log.critical("Widget %r was deleted. Cannot process signals", widget) return app = QCoreApplication.instance() for signal in signals: link = signal.link value = signal.value # Check and update the dynamic link state if link.is_dynamic(): link.dynamic_enabled = can_enable_dynamic(link, value) if not link.dynamic_enabled: # Send None instead value = None handler = link.sink_channel.handler if handler.startswith("self."): handler = handler.split(".", 1)[1] handler = getattr(widget, handler) if link.sink_channel.single: args = (value,) else: args = (value, signal.id) log.debug("Process signals: calling %s.%s (from %s with id:%s)", type(widget).__name__, handler.__name__, link, signal.id) app.setOverrideCursor(Qt.WaitCursor) try: handler(*args) except Exception: sys.excepthook(*sys.exc_info()) log.exception("Error calling '%s' of '%s'", handler.__name__, node.title) finally: app.restoreOverrideCursor() app.setOverrideCursor(Qt.WaitCursor) try: widget.handleNewSignals() except Exception: sys.excepthook(*sys.exc_info()) log.exception("Error calling 'handleNewSignals()' of '%s'", node.title) finally: app.restoreOverrideCursor()
def __call__(self, exc_type, exc_value, tb): if self._stream: header = exc_type.__name__ + ' Exception' if QThread.currentThread() != QCoreApplication.instance().thread(): header += " (in non-GUI thread)" text = traceback.format_exception(exc_type, exc_value, tb) text.insert(0, '{:-^79}\n'.format(' ' + header + ' ')) text.append('-' * 79 + '\n') self._stream.writelines(text) self.handledException.emit((exc_type, exc_value, tb))
def cache_dir(): """ Return the application cache directory. If the directory path does not yet exists then create it. """ init() cachedir = QStandardPaths.writableLocation(QStandardPaths.CacheLocation) version = QCoreApplication.applicationVersion() cachedir = os.path.join(cachedir, version) if not os.path.exists(cachedir): os.makedirs(cachedir) return cachedir
def add_node(self, node): """ Add a node to the scheme. An error is raised if the node is already in the scheme. Parameters ---------- node : :class:`.SchemeNode` Node instance to add to the scheme. """ check_arg(node not in self.__nodes, "Node already in scheme.") check_type(node, SchemeNode) self.__nodes.append(node) ev = events.NodeEvent(events.NodeEvent.NodeAdded, node) QCoreApplication.sendEvent(self, ev) log.info("Added node %r to scheme %r." % (node.title, self.title)) self.node_added.emit(node)
def add_default_slot(self, default): """ Add a default slot to the settings This also replaces any previously set value for the key. """ value = default.default_value oldValue = None etype = SettingChangedEvent.SettingAdded key = default.key if key in self: oldValue = self.get(key) etype = SettingChangedEvent.SettingChanged if not self.isdefault(key): # Replacing a default value. self.__store.remove(self.__key(key)) self.__defaults[key] = default event = SettingChangedEvent(etype, key, value, oldValue) QCoreApplication.sendEvent(self, event)
def remove_node(self, node): """ Remove a `node` from the scheme. All links into and out of the `node` are also removed. If the node in not in the scheme an error is raised. Parameters ---------- node : :class:`.SchemeNode` Node instance to remove. """ check_arg(node in self.__nodes, "Node is not in the scheme.") self.__remove_node_links(node) self.__nodes.remove(node) ev = events.NodeEvent(events.NodeEvent.NodeRemoved, node) QCoreApplication.sendEvent(self, ev) log.info("Removed node %r from scheme %r." % (node.title, self.title)) self.node_removed.emit(node) return node
def remove_link(self, link): """ Remove a link from the scheme. Parameters ---------- link : :class:`.SchemeLink` Link instance to remove. """ check_arg(link in self.__links, "Link is not in the scheme.") self.__links.remove(link) ev = events.LinkEvent(events.LinkEvent.LinkRemoved, link) QCoreApplication.sendEvent(self, ev) log.info("Removed link %r (%r) -> %r (%r) from scheme %r." % \ (link.source_node.title, link.source_channel.name, link.sink_node.title, link.sink_channel.name, self.title) ) self.link_removed.emit(link)
def log_dir(): """ Return the application log directory. """ init() if sys.platform == "darwin": name = str(QCoreApplication.applicationName()) logdir = os.path.join(os.path.expanduser("~/Library/Logs"), name) else: logdir = data_dir() if not os.path.exists(logdir): os.makedirs(logdir) return logdir