class qSlicerMultiVolumeExplorerSimplifiedModuleWidget:
    def __init__(self, parent=None):
        logging.debug(
            "qSlicerMultiVolumeExplorerSimplifiedModuleWidget:init() called")
        if not parent or not hasattr(parent, "layout"):
            self.parent = slicer.qMRMLWidget()
            self.parent.setLayout(QVBoxLayout())
        else:
            self.parent = parent

        self.layout = self.parent.layout()

        self._bgMultiVolumeNode = None
        self._fgMultiVolumeNode = None

        self.styleObserverTags = []
        self.sliceWidgetsPerStyle = {}

        self.chartPopupWindow = None
        self.chartPopupSize = QSize(600, 300)
        self.chartPopupPosition = QPoint(0, 0)

    def hide(self):
        self.widget.hide()

    def show(self):
        self.widget.show()

    def setup(self):
        self.widget = QWidget()
        layout = QGridLayout()
        self.widget.setLayout(layout)
        self.layout.addWidget(self.widget)
        self.widget.show()
        self.layout = layout

        self.setupInputFrame()
        self.setupFrameControlFrame()
        self.setupAdditionalFrames()
        self.setupPlottingFrame()

        self.setFramesEnabled(False)

        self.timer = QTimer()
        self.timer.setInterval(50)

        self.setupConnections()

        # initialize slice observers (from DataProbe.py)
        # keep list of pairs: [observee,tag] so they can be removed easily
        self.styleObserverTags = []
        # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
        self.sliceWidgetsPerStyle = {}
        self.refreshObservers()

    def setupInputFrame(self, parent=None):
        if not parent:
            parent = self.layout
        self.bgMultiVolumeSelector = slicer.qMRMLNodeComboBox()
        self.bgMultiVolumeSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
        self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene)
        self.bgMultiVolumeSelector.addEnabled = 0
        self._bgMultiVolumeSelectorLabel = QLabel('Input multivolume')
        inputFrameWidget = QWidget()
        self.inputFrameLayout = QFormLayout()
        inputFrameWidget.setLayout(self.inputFrameLayout)
        self.inputFrameLayout.addRow(self._bgMultiVolumeSelectorLabel,
                                     self.bgMultiVolumeSelector)
        parent.addWidget(inputFrameWidget)

    def setupFrameControlFrame(self):
        # TODO: initialize the slider based on the contents of the labels array
        self.frameSlider = ctk.ctkSliderWidget()
        self.frameSlider.setSizePolicy(QSizePolicy.Ignored,
                                       QSizePolicy.Preferred)
        self.frameLabel = QLabel('Current frame number')
        self.playButton = QPushButton('Play')
        self.playButton.toolTip = 'Iterate over multivolume frames'
        self.playButton.checkable = True
        frameControlHBox = QHBoxLayout()
        frameControlHBox.addWidget(self.frameLabel)
        frameControlHBox.addWidget(self.frameSlider)
        frameControlHBox.addWidget(self.playButton)
        self.inputFrameLayout.addRow(frameControlHBox)

    def setupAdditionalFrames(self):
        pass

    def setupPlottingFrame(self, parent=None):
        if not parent:
            parent = self.layout
        self.plottingFrameWidget = QWidget()
        self.plottingFrameLayout = QGridLayout()
        self.plottingFrameWidget.setLayout(self.plottingFrameLayout)
        self._multiVolumeIntensityChart = MultiVolumeIntensityChartView()
        self.popupChartButton = QPushButton("Undock chart")
        self.popupChartButton.setCheckable(True)
        self.plottingFrameLayout.addWidget(
            self._multiVolumeIntensityChart.chartView)
        self.plottingFrameLayout.addWidget(self.popupChartButton)
        parent.addWidget(self.plottingFrameWidget)

    def setupConnections(self):
        self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)',
                            self.onVCMRMLSceneChanged)
        self.bgMultiVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                           self.onBackgroundInputChanged)
        self.playButton.connect('toggled(bool)', self.onPlayButtonToggled)
        self.frameSlider.connect('valueChanged(double)', self.onSliderChanged)
        self.timer.connect('timeout()', self.goToNext)
        self.popupChartButton.connect('toggled(bool)',
                                      self.onDockChartViewToggled)

    def onDockChartViewToggled(self, checked):
        if checked:
            self.chartPopupWindow = QDialog()
            self.chartPopupWindow.setWindowFlags(
                PythonQt.QtCore.Qt.WindowStaysOnTopHint)
            layout = QGridLayout()
            self.chartPopupWindow.setLayout(layout)
            layout.addWidget(self._multiVolumeIntensityChart.chartView)
            layout.addWidget(self.popupChartButton)
            self.chartPopupWindow.finished.connect(self.dockChartView)
            self.chartPopupWindow.resize(self.chartPopupSize)
            self.chartPopupWindow.move(self.chartPopupPosition)
            self.chartPopupWindow.show()
            self.popupChartButton.setText("Dock chart")
            self._multiVolumeIntensityChart.chartView.show()
        else:
            self.chartPopupWindow.close()

    def dockChartView(self):
        self.chartPopupSize = self.chartPopupWindow.size
        self.chartPopupPosition = self.chartPopupWindow.pos
        self.plottingFrameLayout.addWidget(
            self._multiVolumeIntensityChart.chartView)
        self.plottingFrameLayout.addWidget(self.popupChartButton)
        self.popupChartButton.setText("Undock chart")
        self.popupChartButton.disconnect('toggled(bool)',
                                         self.onDockChartViewToggled)
        self.popupChartButton.checked = False
        self.popupChartButton.connect('toggled(bool)',
                                      self.onDockChartViewToggled)

    def onSliderChanged(self, frameId):
        if self._bgMultiVolumeNode is None:
            return
        newValue = int(frameId)
        self.setCurrentFrameNumber(newValue)

    def onVCMRMLSceneChanged(self, mrmlScene):
        logging.debug(
            "qSlicerMultiVolumeExplorerSimplifiedModuleWidget:onVCMRMLSceneChanged"
        )
        self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene)
        self.onBackgroundInputChanged()

    def refreshGUIForNewBackgroundImage(self):
        self._multiVolumeIntensityChart.reset()
        self.setFramesEnabled(True)
        if self._fgMultiVolumeNode and self._bgMultiVolumeNode:
            Helper.SetBgFgVolumes(self._bgMultiVolumeNode.GetID(),
                                  self._fgMultiVolumeNode.GetID())
        else:
            Helper.SetBgVolume(self._bgMultiVolumeNode.GetID())
        self.refreshFrameSlider()
        self._multiVolumeIntensityChart.bgMultiVolumeNode = self._bgMultiVolumeNode
        self.refreshObservers()

    def getBackgroundMultiVolumeNode(self):
        return self.bgMultiVolumeSelector.currentNode()

    def onBackgroundInputChanged(self):
        self._bgMultiVolumeNode = self.getBackgroundMultiVolumeNode()

        if self._bgMultiVolumeNode is not None:
            self.refreshGUIForNewBackgroundImage()
        else:
            self.setFramesEnabled(False)

    def onPlayButtonToggled(self, checked):
        if self._bgMultiVolumeNode is None:
            return
        if checked:
            self.timer.start()
            self.playButton.text = 'Stop'
        else:
            self.timer.stop()
            self.playButton.text = 'Play'

    def processEvent(self, observee, event):
        # logging.debug("processing event %s" % event)
        if self._bgMultiVolumeNode is None:
            return

        # TODO: use a timer to delay calculation and compress events
        if event == 'LeaveEvent':
            # reset all the readouts
            # TODO: reset the label text
            return

        if not self.sliceWidgetsPerStyle.has_key(observee):
            return

        interactor = observee.GetInteractor()
        self.createChart(self.sliceWidgetsPerStyle[observee],
                         interactor.GetEventPosition())

    def createChart(self, sliceWidget, position):
        self._multiVolumeIntensityChart.createChart(sliceWidget, position)

    def setCurrentFrameNumber(self, frameNumber):
        mvDisplayNode = self._bgMultiVolumeNode.GetDisplayNode()
        mvDisplayNode.SetFrameComponent(frameNumber)

    def setFramesEnabled(self, enabled):
        pass

    def refreshObservers(self):
        """ When the layout changes, drop the observers from
    all the old widgets and create new observers for the
    newly created widgets"""
        self.removeObservers()
        # get new slice nodes
        layoutManager = slicer.app.layoutManager()
        sliceNodeCount = slicer.mrmlScene.GetNumberOfNodesByClass(
            'vtkMRMLSliceNode')
        for nodeIndex in xrange(sliceNodeCount):
            # find the widget for each node in scene
            sliceNode = slicer.mrmlScene.GetNthNodeByClass(
                nodeIndex, 'vtkMRMLSliceNode')
            sliceWidget = layoutManager.sliceWidget(sliceNode.GetLayoutName())
            if sliceWidget:
                # add observers and keep track of tags
                style = sliceWidget.sliceView().interactorStyle()
                self.sliceWidgetsPerStyle[style] = sliceWidget
                events = ("MouseMoveEvent", "EnterEvent", "LeaveEvent")
                for event in events:
                    tag = style.AddObserver(event, self.processEvent)
                    self.styleObserverTags.append([style, tag])

    def removeObservers(self):
        for observee, tag in self.styleObserverTags:
            observee.RemoveObserver(tag)
        self.styleObserverTags = []
        self.sliceWidgetsPerStyle = {}

    def refreshFrameSlider(self):
        self.frameSlider.minimum = 0
        if not self._bgMultiVolumeNode:
            self.frameSlider.maximum = 0
            return
        nFrames = self._bgMultiVolumeNode.GetNumberOfFrames()
        self.frameSlider.maximum = nFrames - 1

    def goToNext(self):
        currentElement = self.frameSlider.value
        currentElement += 1
        if currentElement > self.frameSlider.maximum:
            currentElement = 0
        self.frameSlider.value = currentElement
Пример #2
0
from ctk import *
from qt import QTimer

w = ctkMatrixWidget()
w.show()

if not _ctkPythonConsoleInstance.isInteractive:
  #QTimer().singleShot(0, app(), SLOT('quit()'))
  t = QTimer()
  t.setInterval(250)
  t.connect('timeout()', app(), 'quit()')
  t.start()
class qSlicerMultiVolumeExplorerSimplifiedModuleWidget:

  def __init__(self, parent=None):
    logging.debug("qSlicerMultiVolumeExplorerSimplifiedModuleWidget:init() called")
    if not parent or not hasattr(parent, "layout"):
      self.parent = slicer.qMRMLWidget()
      self.parent.setLayout(QVBoxLayout())
    else:
      self.parent = parent

    self.layout = self.parent.layout()

    self._bgMultiVolumeNode = None
    self._fgMultiVolumeNode = None

    self.styleObserverTags = []
    self.sliceWidgetsPerStyle = {}

    self.chartPopupWindow = None
    self.chartPopupSize = QSize(600, 300)
    self.chartPopupPosition = QPoint(0,0)

  def hide(self):
    self.widget.hide()

  def show(self):
    self.widget.show()

  def setup(self):
    self.widget = QWidget()
    layout = QGridLayout()
    self.widget.setLayout(layout)
    self.layout.addWidget(self.widget)
    self.widget.show()
    self.layout = layout

    self.setupInputFrame()
    self.setupFrameControlFrame()
    self.setupAdditionalFrames()
    self.setupPlottingFrame()

    self.setFramesEnabled(False)

    self.timer = QTimer()
    self.timer.setInterval(50)

    self.setupConnections()

    # initialize slice observers (from DataProbe.py)
    # keep list of pairs: [observee,tag] so they can be removed easily
    self.styleObserverTags = []
    # keep a map of interactor styles to sliceWidgets so we can easily get sliceLogic
    self.sliceWidgetsPerStyle = {}
    self.refreshObservers()

  def setupInputFrame(self, parent=None):
    if not parent:
      parent = self.layout
    self.bgMultiVolumeSelector = slicer.qMRMLNodeComboBox()
    self.bgMultiVolumeSelector.nodeTypes = ['vtkMRMLMultiVolumeNode']
    self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene)
    self.bgMultiVolumeSelector.addEnabled = 0
    self._bgMultiVolumeSelectorLabel = QLabel('Input multivolume')
    inputFrameWidget = QWidget()
    self.inputFrameLayout = QFormLayout()
    inputFrameWidget.setLayout(self.inputFrameLayout)
    self.inputFrameLayout.addRow(self._bgMultiVolumeSelectorLabel, self.bgMultiVolumeSelector)
    parent.addWidget(inputFrameWidget)

  def setupFrameControlFrame(self):
    # TODO: initialize the slider based on the contents of the labels array
    self.frameSlider = ctk.ctkSliderWidget()
    self.frameLabel = QLabel('Current frame number')
    self.playButton = QPushButton('Play')
    self.playButton.toolTip = 'Iterate over multivolume frames'
    self.playButton.checkable = True
    frameControlHBox = QHBoxLayout()
    frameControlHBox.addWidget(self.frameLabel)
    frameControlHBox.addWidget(self.frameSlider)
    frameControlHBox.addWidget(self.playButton)
    self.inputFrameLayout.addRow(frameControlHBox)

  def setupAdditionalFrames(self):
    pass

  def setupPlottingFrame(self, parent=None):
    if not parent:
      parent = self.layout
    self.plottingFrameWidget = QWidget()
    self.plottingFrameLayout = QGridLayout()
    self.plottingFrameWidget.setLayout(self.plottingFrameLayout)
    self._multiVolumeIntensityChart = MultiVolumeIntensityChartView()
    self.popupChartButton = QPushButton("Undock chart")
    self.popupChartButton.setCheckable(True)
    self.plottingFrameLayout.addWidget(self._multiVolumeIntensityChart.chartView)
    self.plottingFrameLayout.addWidget(self.popupChartButton)
    parent.addWidget(self.plottingFrameWidget)

  def setupConnections(self):
    self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onVCMRMLSceneChanged)
    self.bgMultiVolumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onBackgroundInputChanged)
    self.playButton.connect('toggled(bool)', self.onPlayButtonToggled)
    self.frameSlider.connect('valueChanged(double)', self.onSliderChanged)
    self.timer.connect('timeout()', self.goToNext)
    self.popupChartButton.connect('toggled(bool)', self.onDockChartViewToggled)

  def onDockChartViewToggled(self, checked):
    if checked:
      self.chartPopupWindow = QDialog()
      self.chartPopupWindow.setWindowFlags(PythonQt.QtCore.Qt.WindowStaysOnTopHint)
      layout = QGridLayout()
      self.chartPopupWindow.setLayout(layout)
      layout.addWidget(self._multiVolumeIntensityChart.chartView)
      layout.addWidget(self.popupChartButton)
      self.chartPopupWindow.finished.connect(self.dockChartView)
      self.chartPopupWindow.resize(self.chartPopupSize)
      self.chartPopupWindow.move(self.chartPopupPosition)
      self.chartPopupWindow.show()
      self.popupChartButton.setText("Dock chart")
      self._multiVolumeIntensityChart.chartView.show()
    else:
      self.chartPopupWindow.close()

  def dockChartView(self):
    self.chartPopupSize = self.chartPopupWindow.size
    self.chartPopupPosition = self.chartPopupWindow.pos
    self.plottingFrameLayout.addWidget(self._multiVolumeIntensityChart.chartView)
    self.plottingFrameLayout.addWidget(self.popupChartButton)
    self.popupChartButton.setText("Undock chart")
    self.popupChartButton.disconnect('toggled(bool)', self.onDockChartViewToggled)
    self.popupChartButton.checked = False
    self.popupChartButton.connect('toggled(bool)', self.onDockChartViewToggled)

  def onSliderChanged(self, frameId):
    if self._bgMultiVolumeNode is None:
      return
    newValue = int(frameId)
    self.setCurrentFrameNumber(newValue)

  def onVCMRMLSceneChanged(self, mrmlScene):
    logging.debug("qSlicerMultiVolumeExplorerSimplifiedModuleWidget:onVCMRMLSceneChanged")
    self.bgMultiVolumeSelector.setMRMLScene(slicer.mrmlScene)
    self.onBackgroundInputChanged()

  def refreshGUIForNewBackgroundImage(self):
    self._multiVolumeIntensityChart.reset()
    self.setFramesEnabled(True)
    if self._fgMultiVolumeNode and self._bgMultiVolumeNode:
      Helper.SetBgFgVolumes(self._bgMultiVolumeNode.GetID(), self._fgMultiVolumeNode.GetID())
    else:
      Helper.SetBgVolume(self._bgMultiVolumeNode.GetID())
    self.refreshFrameSlider()
    self._multiVolumeIntensityChart.bgMultiVolumeNode = self._bgMultiVolumeNode
    self.refreshObservers()

  def getBackgroundMultiVolumeNode(self):
    return self.bgMultiVolumeSelector.currentNode()

  def onBackgroundInputChanged(self):
    self._bgMultiVolumeNode = self.getBackgroundMultiVolumeNode()

    if self._bgMultiVolumeNode is not None:
      self.refreshGUIForNewBackgroundImage()
    else:
      self.setFramesEnabled(False)

  def onPlayButtonToggled(self, checked):
    if self._bgMultiVolumeNode is None:
      return
    if checked:
      self.timer.start()
      self.playButton.text = 'Stop'
    else:
      self.timer.stop()
      self.playButton.text = 'Play'

  def processEvent(self, observee, event):
    # logging.debug("processing event %s" % event)
    if self._bgMultiVolumeNode is None:
      return

    # TODO: use a timer to delay calculation and compress events
    if event == 'LeaveEvent':
      # reset all the readouts
      # TODO: reset the label text
      return

    if not self.sliceWidgetsPerStyle.has_key(observee):
      return

    interactor = observee.GetInteractor()
    self.createChart(self.sliceWidgetsPerStyle[observee], interactor.GetEventPosition())

  def createChart(self, sliceWidget, position):
    self._multiVolumeIntensityChart.createChart(sliceWidget, position)

  def setCurrentFrameNumber(self, frameNumber):
    mvDisplayNode = self._bgMultiVolumeNode.GetDisplayNode()
    mvDisplayNode.SetFrameComponent(frameNumber)

  def setFramesEnabled(self, enabled):
    pass

  def refreshObservers(self):
    """ When the layout changes, drop the observers from
    all the old widgets and create new observers for the
    newly created widgets"""
    self.removeObservers()
    # get new slice nodes
    layoutManager = slicer.app.layoutManager()
    sliceNodeCount = slicer.mrmlScene.GetNumberOfNodesByClass('vtkMRMLSliceNode')
    for nodeIndex in xrange(sliceNodeCount):
      # find the widget for each node in scene
      sliceNode = slicer.mrmlScene.GetNthNodeByClass(nodeIndex, 'vtkMRMLSliceNode')
      sliceWidget = layoutManager.sliceWidget(sliceNode.GetLayoutName())
      if sliceWidget:
        # add observers and keep track of tags
        style = sliceWidget.sliceView().interactorStyle()
        self.sliceWidgetsPerStyle[style] = sliceWidget
        events = ("MouseMoveEvent", "EnterEvent", "LeaveEvent")
        for event in events:
          tag = style.AddObserver(event, self.processEvent)
          self.styleObserverTags.append([style,tag])

  def removeObservers(self):
    for observee,tag in self.styleObserverTags:
      observee.RemoveObserver(tag)
    self.styleObserverTags = []
    self.sliceWidgetsPerStyle = {}

  def refreshFrameSlider(self):
    self.frameSlider.minimum = 0
    if not self._bgMultiVolumeNode:
      self.frameSlider.maximum = 0
      return
    nFrames = self._bgMultiVolumeNode.GetNumberOfFrames()
    self.frameSlider.maximum = nFrames - 1

  def goToNext(self):
    currentElement = self.frameSlider.value
    currentElement += 1
    if currentElement > self.frameSlider.maximum:
      currentElement = 0
    self.frameSlider.value = currentElement
Пример #4
0
class QtReactor(posixbase.PosixReactorBase):

    def __init__(self):
        self._reads = {}
        self._writes = {}
        self._notifiers = {}
        self._timer = QTimer()
        self._timer.setSingleShot(True)
        self._timer.timeout.connect(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 or 0, 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_()
Пример #5
0
from ctk import *
from qt import QTimer

# Test display of a CTK widget
w = ctkMatrixWidget()
w.show()

# Test command execution using Python manager
pythonManager = _ctkPythonManagerInstance
pythonManager.executeString("variableInPythonConsole=523")
try:
    print("variableInPythonConsole was successfully set to {0}".format(
        variableInPythonConsole))
except:
    print "PythonManager.executeString failed"
    qt.QApplication.exit(1)

if not _ctkPythonConsoleInstance.isInteractive:
    #QTimer().singleShot(0, app(), SLOT('quit()'))
    t = QTimer()
    t.setInterval(250)
    t.connect('timeout()', app(), 'quit()')
    t.start()
Пример #6
0
class QtReactor(posixbase.PosixReactorBase):
    def __init__(self):
        self._reads = {}
        self._writes = {}
        self._notifiers = {}
        self._timer = QTimer()
        self._timer.setSingleShot(True)
        self._timer.timeout.connect(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 or 0, 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_()