Ejemplo n.º 1
0
    def search(self):
        # first set/change the  font of the serach box
        font = self.dlg.search_lineEdit.font()
        font.setItalic(False)
        self.dlg.search_lineEdit.setFont(font)

        # clear description and quicklook
        self.dlg.textEdit.clear()
        
        # make a new emptey scene to show
        if not self.dlg.graphicsView is None:
            scene = QGraphicsScene()
            pic = QPixmap()
            scene.addItem(QGraphicsPixmapItem(pic))
            self.dlg.graphicsView.setScene(scene)        
            self.dlg.graphicsView.show()  
        
        # function the searches for a string in the datasets name, service type and otganization
        text = self.dlg.search_lineEdit.text()        
        # convert to lower case and remove greek accents in case of Greek
        text = text.lower()
        text = self.removeGreekAccents(text)  
        foundDatasets = []
        for dataset in self.datasets:
            # use lowercase characters and remove greek accents , to make the comparison
            name = self.removeGreekAccents(dataset.getName(self.language).lower())
            source = self.removeGreekAccents(dataset.getSource(self.language).lower())
            serviceType = self.removeGreekAccents(dataset.serviceType.lower())
            
            if text in name or text in source or text in serviceType:            
            #QMessageBox.information(None, "DEBUG:", str(type(dataset.getName(self.language))))                           
                foundDatasets.append(dataset)
        #fill the table with the found datasets
        self.fill_table(foundDatasets)     
Ejemplo n.º 2
0
    def test_editlinksnode(self):
        from ...registry.tests import small_testing_registry

        reg = small_testing_registry()
        file_desc = reg.widget("Orange.OrangeWidgets.Data.OWFile.OWFile")
        bayes_desc = reg.widget("Orange.OrangeWidgets.Classify.OWNaiveBayes."
                                "OWNaiveBayes")
        source_node = SchemeNode(file_desc, title="This is File")
        sink_node = SchemeNode(bayes_desc)

        scene = QGraphicsScene()
        view = QGraphicsView(scene)

        node = EditLinksNode(node=source_node)
        scene.addItem(node)

        node = EditLinksNode(direction=Qt.RightToLeft)
        node.setSchemeNode(sink_node)

        node.setPos(300, 0)
        scene.addItem(node)

        view.show()
        view.resize(800, 300)
        self.app.exec_()
Ejemplo n.º 3
0
class StartSelectView(QGraphicsView):

    def __init__(self, *args):
        QGraphicsView.__init__(self, *args)
        self.move(2, 250)
        self.btnSize = 28
        self.setMaximumHeight(self.btnSize * 2)
        self.setMaximumWidth(334)
        self.setMinimumHeight(self.btnSize * 2)
        self.setMinimumWidth(334)
        self.adjustSize()
        self.scene = QGraphicsScene(self)
        self.setStyleSheet('background-color:transparent; border-width: 0px; border: 0px;')
        self.psButtons = QPixmap(os.getcwd() + '/../icons/controller-sprite.png')
        self.select = self.psButtons.copy(696, 120, 45, 30)
        self.select = self.select.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.selectItem = QGraphicsPixmapItem(self.select)
        self.selectItem.setOffset(QPointF(0, 0))
        self.scene.addItem(self.selectItem)
        self.start = self.psButtons.copy(754, 120, 45, 30)
        self.start = self.start.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.startItem = QGraphicsPixmapItem(self.start)
        self.startItem.setOffset(QPointF(86, 0))
        self.scene.addItem(self.startItem)
        self.setScene(self.scene)
Ejemplo n.º 4
0
    def search(self):
        # first set/change the  font of the serach box
        font = self.dlg.search_lineEdit.font()
        font.setItalic(False)
        self.dlg.search_lineEdit.setFont(font)

        # clear description and quicklook
        self.dlg.textEdit.clear()

        # make a new emptey scene to show
        if not self.dlg.graphicsView is None:
            scene = QGraphicsScene()
            pic = QPixmap()
            scene.addItem(QGraphicsPixmapItem(pic))
            self.dlg.graphicsView.setScene(scene)
            self.dlg.graphicsView.show()

        # function the searches for a string in the datasets name, service type and otganization
        text = self.dlg.search_lineEdit.text()
        # convert to lower case and remove greek accents in case of Greek
        text = text.lower()
        text = self.removeGreekAccents(text)
        foundDatasets = []
        for dataset in self.datasets:
            # use lowercase characters and remove greek accents , to make the comparison
            name = self.removeGreekAccents(dataset.getName(self.language).lower())
            source = self.removeGreekAccents(dataset.getSource(self.language).lower())
            serviceType = self.removeGreekAccents(dataset.serviceType.lower())

            if text in name or text in source or text in serviceType:
            #QMessageBox.information(None, "DEBUG:", str(type(dataset.getName(self.language))))
                foundDatasets.append(dataset)
        #fill the table with the found datasets
        self.fill_table(foundDatasets)
Ejemplo n.º 5
0
class Ventana(Ui_MainWindow, QMainWindow):
    
    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)        
        self.actionOpenImgA.triggered.connect(self.cargarImgA)
        self.actionOpenImgB.triggered.connect(self.cargarImgB)
        self.actionOperate.triggered.connect(self.operar)
        
        self.escenaA = QGraphicsScene()
        self.imgA.setScene(self.escenaA)
        
        self.escenaB = QGraphicsScene()
        self.imgB.setScene(self.escenaB)
        
        self.escenaC = QGraphicsScene()
        self.imgC.setScene(self.escenaC)
        
        self.operacion.addItem("suma")
        self.operacion.addItem("multiplicacion")
        self.operacion.addItem("promedio")
    
    def cargarImgA(self):
        self.imagenA = self.cargarImg(self.escenaA)
        
    def cargarImgB(self):
        self.imagenB = self.cargarImg(self.escenaB)
    
    def cargarImg(self, escena):
        ruta =QFileDialog.getOpenFileName(parent=self, caption="Archivo")
        imagen = QImage()
        imagen.load(ruta)
        pixmap = QPixmap(imagen)
        escena.addItem(QGraphicsPixmapItem(pixmap))
        return imagen

    def operar(self):
        ancho = min(self.imagenA.width(), self.imagenB.width())
        alto  = min(self.imagenA.height(), self.imagenB.height())
        
        oper = getattr(self,str(self.operacion.currentText()))
        
        self.imagenC = QImage(ancho, alto, QImage.Format_RGB32 )
        
        for i in range(ancho):
            for j in range(alto):
                pix = oper(self.imagenA.pixel(i,j), self.imagenB.pixel(i,j))
                self.imagenC.setPixel(i, j, pix)
        
        pixmap = QPixmap(self.imagenC)
        self.escenaC.addItem(QGraphicsPixmapItem(pixmap))
        
    def suma(self, pixA, pixB):
        return pixA + pixB
    
    def multiplicacion(self, pixA, pixB):
        return pixA * pixB
    
    def promedio(self, pixA, pixB):
        return (pixA + pixB) / 2
Ejemplo n.º 6
0
    def test_editlinksnode(self):
        from ...registry.tests import small_testing_registry

        reg = small_testing_registry()
        file_desc = reg.widget("Orange.widgets.data.owfile.OWFile")
        bayes_desc = reg.widget("Orange.widgets.classify.ownaivebayes."
                                "OWNaiveBayes")
        source_node = SchemeNode(file_desc, title="This is File")
        sink_node = SchemeNode(bayes_desc)

        scene = QGraphicsScene()
        view = QGraphicsView(scene)

        node = EditLinksNode(node=source_node)
        scene.addItem(node)

        node = EditLinksNode(direction=Qt.RightToLeft)
        node.setSchemeNode(sink_node)

        node.setPos(300, 0)
        scene.addItem(node)

        view.show()
        view.resize(800, 300)
        self.app.exec_()
Ejemplo n.º 7
0
class LiteBoxView(QGraphicsView):

    ALPHA = QColor(0, 0, 0, 192)

    closed_signal = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(LiteBoxView, self).__init__(parent)
        self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
        #self.setAttribute(Qt.WA_DeleteOnClose)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        QtGui.QShortcut( Qt.Key_Escape, self, self.close )
        self.desktopshot = None

        # will propagate to children
        self.setRenderHint(QPainter.Antialiasing)
        self.setRenderHint(QPainter.TextAntialiasing)

        self.scene = QGraphicsScene()
        self.setScene(self.scene)

    def close(self):
        self.closed_signal.emit()
        super(LiteBoxView, self).close()

    def drawBackground(self, painter, rect):
        if self.desktopshot is None:
            self.desktopshot = get_desktop_pixmap()

        painter.drawPixmap(self.mapToScene(0, 0), self.desktopshot)
        painter.setBrush(LiteBoxView.ALPHA)
        painter.drawRect(rect)

    def show_fullscreen_svg(self, path):
        """:param path: path to an svg file"""
        from PyQt4 import QtSvg
        item = QtSvg.QGraphicsSvgItem(path)
        self.show_fullscreen_item(item)

    def show_fullscreen_pixmap(self, pixmap):
        """:param pixmap: a QPixmap"""
        item = QGraphicsPixmapItem(pixmap)
        self.show_fullscreen_item(item)
        
    def show_fullscreen_image(self, image):
        """:param image: a QImage"""
        pixmap = QPixmap.fromImage(image)
        self.show_fullscreen_pixmap( pixmap )

    def show_fullscreen_item(self, item):
        """:param item: a QGraphicsItem to be shown fullscreen"""
        item.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)
        self.scene.clear()
        self.scene.addItem(item)
        CloseMark(parent=item)
        self.showFullScreen()
        self.setFocus()
Ejemplo n.º 8
0
class LiteBoxView(QGraphicsView):

    ALPHA = QColor(0, 0, 0, 192)

    closed_signal = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(LiteBoxView, self).__init__(parent)
        self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
        #self.setAttribute(Qt.WA_DeleteOnClose)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        QtGui.QShortcut(Qt.Key_Escape, self, self.close)
        self.desktopshot = None

        # will propagate to children
        self.setRenderHint(QPainter.Antialiasing)
        self.setRenderHint(QPainter.TextAntialiasing)

        self.scene = QGraphicsScene()
        self.setScene(self.scene)

    def close(self):
        self.closed_signal.emit()
        super(LiteBoxView, self).close()

    def drawBackground(self, painter, rect):
        if self.desktopshot is None:
            self.desktopshot = get_desktop_pixmap()

        painter.drawPixmap(self.mapToScene(0, 0), self.desktopshot)
        painter.setBrush(LiteBoxView.ALPHA)
        painter.drawRect(rect)

    def show_fullscreen_svg(self, path):
        """:param path: path to an svg file"""
        from PyQt4 import QtSvg
        item = QtSvg.QGraphicsSvgItem(path)
        self.show_fullscreen_item(item)

    def show_fullscreen_pixmap(self, pixmap):
        """:param pixmap: a QPixmap"""
        item = QGraphicsPixmapItem(pixmap)
        self.show_fullscreen_item(item)

    def show_fullscreen_image(self, image):
        """:param image: a QImage"""
        pixmap = QPixmap.fromImage(image)
        self.show_fullscreen_pixmap(pixmap)

    def show_fullscreen_item(self, item):
        """:param item: a QGraphicsItem to be shown fullscreen"""
        item.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)
        self.scene.clear()
        self.scene.addItem(item)
        CloseMark(parent=item)
        self.showFullScreen()
        self.setFocus()
Ejemplo n.º 9
0
class MyWidget(QGraphicsView):
    def __init__(self):
        super(MyWidget, self).__init__()
        self.setFixedSize(300, 300)
        self.setSceneRect(0, 0, 250, 250)
        self.scene = QGraphicsScene()
        self.setScene(self.scene)
        self.scene.addItem(MyArrow())
Ejemplo n.º 10
0
    def addItem(self, QGraphicsItem):

        if self.__isNode(QGraphicsItem):
            QGraphicsItem.setZValue(0.0)
            QGraphicsItem.onPress.connect(self.__onNodePressed)

            self.__nodes[QGraphicsItem.Id] = QGraphicsItem

        QGraphicsScene.addItem(self, QGraphicsItem)
Ejemplo n.º 11
0
    def addItem(self, QGraphicsItem):

        if self.__isNode(QGraphicsItem):
            QGraphicsItem.setZValue(1.0)
            QGraphicsItem.onPress.connect(self.__onNodePressed)

            self.__nodes[QGraphicsItem.Id] = QGraphicsItem

        QGraphicsScene.addItem(self, QGraphicsItem)
Ejemplo n.º 12
0
    def test_graphicstextwidget(self):
        scene = QGraphicsScene()
        view = QGraphicsView(scene)

        text = GraphicsTextWidget()
        text.setHtml("<center><b>a text</b></center><p>paragraph</p>")
        scene.addItem(text)
        view.show()
        view.resize(400, 300)

        self.app.exec_()
Ejemplo n.º 13
0
    def test_graphicstextwidget(self):
        scene = QGraphicsScene()
        view = QGraphicsView(scene)

        text = GraphicsTextWidget()
        text.setHtml("<center><b>a text</b></center><p>paragraph</p>")
        scene.addItem(text)
        view.show()
        view.resize(400, 300)

        self.app.exec_()
Ejemplo n.º 14
0
class PendulumGraphics(Pendulum):
    """pendulum which renders itself in a QGraphicsView"""

    def initGraphics(self, gView):
        self.gView = gView
        self.gScene = QGraphicsScene(self.gView)
        self.gView.setScene(self.gScene)

        self.gText = QGraphicsTextItem("Pendulum")
        self.gText.moveBy(0, -120)
        self.gGrid = Graphics.Items.Grid(size=(-140, -140, 140, 140), xstep=20, ystep=20,
            toolTip='the main grid')
        self.gCross = Graphics.Items.CrossX(toolTip='this is the fix point of the pendulum')
        self.gAxes = Graphics.Items.Axes(toolTip='theese are x,y-axes')
        self.gPendulum = GPendulum()
        self.gPendulum.setProperties((self.mass, self.length, self.radius, self.gravity,
            self.omega, self.friction))
        self.gScene.addItem(self.gGrid)
        self.gScene.addItem(self.gText)
        self.gScene.addItem(self.gCross)
        self.gScene.addItem(self.gAxes)
        self.gScene.addItem(self.gPendulum)
        self.gView.setSceneRect(QRectF(-140, -140, 280, 280))
        self.gPendulum.rotate(self.phi.v)

    def reset(self):
        self.gPendulum.rotate(self.initValues['phi']-self.phi.v)
        Pendulum.reset(self)

    def update(self, timeStep):
        Pendulum.update(self, timeStep)
        self.gPendulum.rotate(self.phiStep)
Ejemplo n.º 15
0
 def axis_view(orientation):
     ax = pg.AxisItem(orientation=orientation, maxTickLength=7)
     scene = QGraphicsScene()
     scene.addItem(ax)
     view = QGraphicsView(
         scene,
         horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff,
         verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn,
         alignment=Qt.AlignLeft | Qt.AlignVCenter)
     view.setFixedHeight(ax.size().height())
     ax.line = SliderLine(orientation=Qt.Horizontal,
                          length=ax.size().height())
     scene.addItem(ax.line)
     return view, ax
Ejemplo n.º 16
0
 def axis_view(orientation):
     ax = pg.AxisItem(orientation=orientation, maxTickLength=7)
     scene = QGraphicsScene()
     scene.addItem(ax)
     view = QGraphicsView(
         scene,
         horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff,
         verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn,
         alignment=Qt.AlignLeft | Qt.AlignVCenter,
     )
     view.setFixedHeight(ax.size().height())
     ax.line = SliderLine(orientation=Qt.Horizontal, length=ax.size().height())
     scene.addItem(ax.line)
     return view, ax
Ejemplo n.º 17
0
class SingleJoystickView(QGraphicsView):

    def __init__(self, *args):
        QGraphicsView.__init__(self, *args)
        self.outerD = 125
        self.innerD = 25
        self.innerRange = 50
        self.inputRange = 256
        self.thresh = 3
        self.worker = JoystickThread()
        self.worker.valueUpdated.connect(self.moveJoystick)
        self.worker.start()
        self.move(30, 100)
        self.setContentsMargins(0, 0, 0, 0)
        self.setMaximumHeight(140)
        self.setMaximumWidth(140)
        self.adjustSize()
        self.scene = QGraphicsScene(self)
        self.outerCircle = QGraphicsEllipseItem(0, 0, self.outerD, self.outerD)
        self.outerCircle.setPen(QPen(QColor(Qt.darkGray), 1, Qt.SolidLine))
        self.outerCircle.setBrush(Qt.gray)
        self.innerCircle = QGraphicsEllipseItem(self.outerD / 2 - self.innerD / 2, self.outerD / 2 - self.innerD / 2, self.innerD, self.innerD)
        self.innerCircle.setPen(QPen(QColor(Qt.darkGray), 1, Qt.SolidLine))
        self.innerCircle.setBrush(Qt.lightGray)
        self.scene.addItem(self.outerCircle)
        self.scene.addItem(self.innerCircle)
        self.setScene(self.scene)
        self.setStyleSheet('background-color:transparent;color:red')
        self.currentX = 0
        self.currentY = 0

    def moveJoystick(self, x, y):
        x2 = x * self.innerRange / self.inputRange - self.innerRange / 2
        y2 = y * self.innerRange / self.inputRange - self.innerRange / 2
        if -self.thresh <= x2 <= self.thresh:
            x2 = 0
        if -self.thresh <= y2 <= self.thresh:
            y2 = 0
        self.tl = QTimeLine(10)
        self.tl.setFrameRange(0, 10)
        self.a = QGraphicsItemAnimation()
        self.a.setItem(self.innerCircle)
        self.a.setTimeLine(self.tl)
        self.a.setPosAt(0, QPointF(self.currentX, self.currentY))
        self.a.setTranslationAt(1, x2, y2)
        self.currentX = x2
        self.currentY = y2
        self.tl.start()
        print 'x:%d y:%d' % (x2, y2)
Ejemplo n.º 18
0
 def dropEvent(self, event):
     items = self.selectedItems()
     event.acceptProposedAction()
     data = event.mimeData().data('application/x-qabstractitemmodeldatalist')
     text = self.decode_data(data)[0][0].toString()
     newtable = meta.tables[str(text)]
     item = Table(newtable, Vector.random())
     if items:
         try:
             condition = items[0].table.join(newtable)
         except:
             condition = None
         spring = Relation(items[0], item, condition)
         QGraphicsScene.addItem(self, spring)
     self.addItem(item)
Ejemplo n.º 19
0
class FaceButtonsView(QGraphicsView):

    def __init__(self, *args):
        QGraphicsView.__init__(self, *args)
        self.move(170, 90)
        self.btnSize = 40
        self.padding = 5
        self.setMaximumHeight(self.btnSize * 4)
        self.setMaximumWidth(self.btnSize * 4)
        self.setMinimumHeight(self.btnSize * 4)
        self.setMinimumWidth(self.btnSize * 4)
        self.adjustSize()
        self.setStyleSheet('background-color:transparent; border-width: 0px; border: 0px;')
        self.scene = QGraphicsScene(self)
        self.psButtons = QPixmap(os.getcwd() + '/../icons/PS3_Buttons.png')
        self.triangle = self.psButtons.copy(0, 0, 220, 225)
        self.triangle = self.triangle.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.square = self.psButtons.copy(220, 0, 220, 225)
        self.square = self.square.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.circle = self.psButtons.copy(440, 0, 220, 225)
        self.circle = self.circle.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.cross = self.psButtons.copy(660, 0, 220, 225)
        self.cross = self.cross.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.triangleItem = QGraphicsPixmapItem(self.triangle)
        self.triangleItem.setOffset(QPointF(self.btnSize + self.padding, 0))
        self.scene.addItem(self.triangleItem)
        self.squareItem = QGraphicsPixmapItem(self.square)
        self.squareItem.setOffset(QPointF(0, self.btnSize + self.padding))
        self.scene.addItem(self.squareItem)
        self.circleItem = QGraphicsPixmapItem(self.circle)
        self.circleItem.setOffset(QPointF(self.btnSize * 2 + self.padding * 2, self.btnSize + self.padding))
        self.scene.addItem(self.circleItem)
        self.crossItem = QGraphicsPixmapItem(self.cross)
        self.crossItem.setOffset(QPointF(self.btnSize + self.padding, self.btnSize * 2 + self.padding * 2))
        self.scene.addItem(self.crossItem)
        self.effect = QGraphicsDropShadowEffect()
        self.effect.setOffset(0, 0)
        self.effect.setBlurRadius(20)
        self.effect.setColor(Qt.green)
        self.triangleItem.setGraphicsEffect(self.effect)
        self.setScene(self.scene)
        self.tl2 = QTimeLine(10000)
        self.tl2.setFrameRange(0, 10000)
        self.t = QGraphicsItemAnimation()
        self.t.setItem(self.triangleItem)
        self.t.setTimeLine(self.tl2)
        self.tl2.connect(self.tl2, SIGNAL('frameChanged(int)'), self.updateEffect)
        self.effectd = 3
        self.tl2.start()

    def updateEffect(self):
        if self.effect.blurRadius() > 50:
            self.effectd = -3
        elif self.effect.blurRadius() < 5:
            self.effectd = 3
        self.effect.setBlurRadius(self.effect.blurRadius() + self.effectd)
Ejemplo n.º 20
0
Archivo: 6.py Proyecto: wsonv/Wonjun
def main():

    app = QApplication(sys.argv)

    grview = QGraphicsView()
    scene = QGraphicsScene()
    scene.setSceneRect(0, 0, 680, 459)

    scene.addPixmap(QPixmap('01.png'))
    grview.setScene(scene)

    item = GraphicsRectItem(0, 0, 300, 150)
    scene.addItem(item)

    grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
    grview.show()
    sys.exit(app.exec_())
Ejemplo n.º 21
0
    def __init__(self, master, *args):
        QGraphicsView.__init__(self, *args)
        self.master = master

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        self.setRenderHints(QPainter.Antialiasing)
        scene = QGraphicsScene(self)
        self.pixmapGraphicsItem = QGraphicsPixmapItem(None)
        scene.addItem(self.pixmapGraphicsItem)
        self.setScene(scene)

        self.setMouseTracking(True)
        self.viewport().setMouseTracking(True)

        self.setFocusPolicy(Qt.WheelFocus)
Ejemplo n.º 22
0
    def __init__(self, master, *args):
        QGraphicsView.__init__(self, *args)
        self.master = master

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        self.setRenderHints(QPainter.Antialiasing)
        scene = QGraphicsScene(self)
        self.pixmapGraphicsItem = QGraphicsPixmapItem(None)
        scene.addItem(self.pixmapGraphicsItem)
        self.setScene(scene)

        self.setMouseTracking(True)
        self.viewport().setMouseTracking(True)

        self.setFocusPolicy(Qt.WheelFocus)
Ejemplo n.º 23
0
 def close(self):
     #clear everything
     self.init_table()
     # clear description and quicklook
     self.dlg.textEdit.clear()
     # clear search box
     #text = self.dlg.search_lineEdit.setText("")
     self.init_searchBox()
     # make a new emptey scene to show
     if not self.dlg.graphicsView is None:
         scene = QGraphicsScene()
         pic = QPixmap()
         scene.addItem(QGraphicsPixmapItem(pic))
         self.dlg.graphicsView.setScene(scene)        
         self.dlg.graphicsView.show()
     """close the dialog"""
     self.dlg.close()
Ejemplo n.º 24
0
    def __init__(self, app):
        super(QDialog, self).__init__()
        
        #Set up window
        self.ui = Ui_keySavedDialog()
        self.ui.setupUi(self)
        
        # Set up connections
        self.ui.okayButton.clicked.connect(self.okayClicked)

        # Set checkmark image
        scene = QGraphicsScene()
        item = QGraphicsPixmapItem(QPixmap("checkmark.png"))
        scene.addItem(item)
        self.ui.checkMarkGraphicsView.setScene(scene)
        
        self.show()
Ejemplo n.º 25
0
 def close(self):
     #clear everything
     self.init_table()
     # clear description and quicklook
     self.dlg.textEdit.clear()
     # clear search box
     #text = self.dlg.search_lineEdit.setText("")
     self.init_searchBox()
     # make a new emptey scene to show
     if not self.dlg.graphicsView is None:
         scene = QGraphicsScene()
         pic = QPixmap()
         scene.addItem(QGraphicsPixmapItem(pic))
         self.dlg.graphicsView.setScene(scene)
         self.dlg.graphicsView.show()
     """close the dialog"""
     self.dlg.close()
Ejemplo n.º 26
0
class DpadView(QGraphicsView):

    def __init__(self, *args):
        QGraphicsView.__init__(self, *args)
        self.move(2, 90)
        self.btnSize = 75
        self.padding = -35
        self.setMaximumHeight(self.btnSize * 2 + 20)
        self.setMaximumWidth(self.btnSize * 2 + 20)
        self.setMinimumHeight(self.btnSize * 2 + 20)
        self.setMinimumWidth(self.btnSize * 2 + 20)
        self.adjustSize()
        self.setStyleSheet('background-color:transparent; border-width: 0px; border: 0px;')
        self.scene = QGraphicsScene(self)
        self.left = QPixmap(os.getcwd() + '/../icons/left.png')
        self.left = self.left.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.right = QPixmap(os.getcwd() + '/../icons/right.png')
        self.right = self.right.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.up = QPixmap(os.getcwd() + '/../icons/up.png')
        self.up = self.up.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.down = QPixmap(os.getcwd() + '/../icons/down.png')
        self.down = self.down.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.leftItem = QGraphicsPixmapItem(self.left)
        self.leftItem.setOffset(QPointF(0, self.btnSize + self.padding))
        self.scene.addItem(self.leftItem)
        self.rightItem = QGraphicsPixmapItem(self.right)
        self.rightItem.setOffset(QPointF(self.btnSize * 2 + self.padding * 2, self.btnSize + self.padding))
        self.scene.addItem(self.rightItem)
        self.upItem = QGraphicsPixmapItem(self.up)
        self.upItem.setOffset(QPointF(self.btnSize + self.padding, 0))
        self.scene.addItem(self.upItem)
        self.downItem = QGraphicsPixmapItem(self.down)
        self.downItem.setOffset(QPointF(self.btnSize + self.padding, self.btnSize * 2 + self.padding * 2))
        self.scene.addItem(self.downItem)
        self.effect = QGraphicsDropShadowEffect()
        self.effect.setOffset(0, 0)
        self.effect.setBlurRadius(20)
        self.effect.setColor(Qt.green)
        self.downItem.setGraphicsEffect(self.effect)
        self.setScene(self.scene)
        self.tl2 = QTimeLine(10000)
        self.tl2.setFrameRange(0, 10000)
        self.t = QGraphicsItemAnimation()
        self.t.setItem(self.downItem)
        self.t.setTimeLine(self.tl2)
        self.tl2.connect(self.tl2, SIGNAL('frameChanged(int)'), self.updateEffect)
        self.effectd = 3
        self.tl2.start()

    def updateEffect(self):
        if self.effect.blurRadius() > 50:
            self.effectd = -3
        elif self.effect.blurRadius() < 5:
            self.effectd = 3
        self.effect.setBlurRadius(self.effect.blurRadius() + self.effectd)
Ejemplo n.º 27
0
    def test(self):
        raw = numpy.load(os.path.join(volumina._testing.__path__[0], 'lena.npy')).astype( numpy.uint32 )
        ars = _ArraySource2d(raw)
        ims = DummyItemSource(ars)
        req = ims.request( QRect( 0, 0, 256, 256 ) )
        item = req.wait()
        assert isinstance(item, QGraphicsItem)

        DEBUG = False
        if DEBUG:        
            from PyQt4.QtGui import QApplication, QGraphicsView, QGraphicsScene
            app = QApplication([])
            scene = QGraphicsScene()
            scene.addItem(item)
            view = QGraphicsView(scene)
            view.show()
            view.raise_()         
            app.exec_()
Ejemplo n.º 28
0
    def updateDescAndQL(self):
        # get the name of the selected dataset
        dataset_name, dataset_serviceType = self.getSelectedNameAndType()

        #custom web service object
        dataset = self.selectdataSets(dataset_name, dataset_serviceType)

        quicklook = os.path.join(self.quicklooks_dir, dataset.QLname + ".jpg")
        desc = dataset.getDescription(self.language)
        name = dataset.getName(self.language)

        #update decription
        self.dlg.textEdit.clear()
        #creation and last update
        if self.language == "EN":
            crDate = "Creation date : " + dataset.creationDate
            update = "Last update : " + dataset.lastUpdate
        elif self.language == "GR":
            crDate = unicode(
                "Ημερομηνια δημιουργιας : " + dataset.creationDate, 'utf-8')
            update = unicode("Τελευταία ενημέρωση : " + dataset.lastUpdate,
                             'utf-8')

        cursor = QTextCursor(self.dlg.textEdit.document())
        cursor.insertHtml("<h3> " + name + " <br><br></h3>")
        cursor.insertHtml("<p> " + desc + " <br><br><br></p>")
        cursor.insertHtml("<p><i> " + crDate + " <br></i></p>")
        #cursor.insertHtml("<p><i> "+update+" <br></i></p>")

        self.dlg.textEdit.setReadOnly(True)
        #update quicklook

        #GET DIMENSIONS OF THE IMAGE
        img = Image.open(quicklook)
        w, h = img.size

        scene = QGraphicsScene()
        pic = QPixmap(quicklook)
        scene.addItem(QGraphicsPixmapItem(pic))

        self.dlg.graphicsView.setScene(scene)
        self.dlg.graphicsView.fitInView(QRectF(0, 0, w, h), Qt.KeepAspectRatio)
        self.dlg.graphicsView.show()
Ejemplo n.º 29
0
    def test(self):
        raw = numpy.load(
            os.path.join(volumina._testing.__path__[0],
                         'lena.npy')).astype(numpy.uint32)
        ars = _ArraySource2d(raw)
        ims = DummyItemSource(ars)
        req = ims.request(QRect(0, 0, 256, 256))
        item = req.wait()
        assert isinstance(item, QGraphicsItem)

        DEBUG = False
        if DEBUG:
            from PyQt4.QtGui import QApplication, QGraphicsView, QGraphicsScene
            app = QApplication([])
            scene = QGraphicsScene()
            scene.addItem(item)
            view = QGraphicsView(scene)
            view.show()
            view.raise_()
            app.exec_()
Ejemplo n.º 30
0
def render_drop_shadow_frame(pixmap, shadow_rect, shadow_color,
                             offset, radius, rect_fill_color):
    pixmap.fill(QColor(0, 0, 0, 0))
    scene = QGraphicsScene()
    rect = QGraphicsRectItem(shadow_rect)
    rect.setBrush(QColor(rect_fill_color))
    rect.setPen(QPen(Qt.NoPen))
    scene.addItem(rect)
    effect = QGraphicsDropShadowEffect(color=shadow_color,
                                       blurRadius=radius,
                                       offset=offset)

    rect.setGraphicsEffect(effect)
    scene.setSceneRect(QRectF(QPointF(0, 0), QSizeF(pixmap.size())))
    painter = QPainter(pixmap)
    scene.render(painter)
    painter.end()
    scene.clear()
    scene.deleteLater()
    return pixmap
Ejemplo n.º 31
0
    def updateDescAndQL(self):
        # get the name of the selected dataset
        dataset_name, dataset_serviceType = self.getSelectedNameAndType()

        #custom web service object
        dataset = self.selectdataSets(dataset_name,dataset_serviceType)

        quicklook = os.path.join(self.quicklooks_dir, dataset.QLname+".jpg")
        desc = dataset.getDescription(self.language)
        name = dataset.getName(self.language)

        #update decription
        self.dlg.textEdit.clear()
        #creation and last update
        if self.language =="EN":
            crDate = "Creation date : "+dataset.creationDate
            update = "Last update : "+dataset.lastUpdate
        elif self.language =="GR":
            crDate = unicode("Ημερομηνια δημιουργιας : "+dataset.creationDate,'utf-8')
            update = unicode("Τελευταία ενημέρωση : "+dataset.lastUpdate,'utf-8')

        cursor = QTextCursor(self.dlg.textEdit.document())
        cursor.insertHtml("<h3> "+name+" <br><br></h3>")
        cursor.insertHtml("<p> "+desc+" <br><br><br></p>")
        cursor.insertHtml("<p><i> "+crDate+" <br></i></p>")
        #cursor.insertHtml("<p><i> "+update+" <br></i></p>")

        self.dlg.textEdit.setReadOnly(True)
        #update quicklook

        #GET DIMENSIONS OF THE IMAGE
        img = Image.open(quicklook)
        w, h = img.size

        scene = QGraphicsScene()
        pic = QPixmap(quicklook)
        scene.addItem(QGraphicsPixmapItem(pic))

        self.dlg.graphicsView.setScene(scene)
        self.dlg.graphicsView.fitInView(QRectF(0, 0, w, h), Qt.KeepAspectRatio)
        self.dlg.graphicsView.show()
Ejemplo n.º 32
0
    def test(self):
        if not self.winManager:
            return
        from PyQt4.QtGui import QGraphicsScene, QGraphicsItem, QGraphicsLineItem
        from PyQt4.QtCore import QRectF, QLineF
        w = self.winManager.newWindow()
        scene = QGraphicsScene(w.graphicsView)
        scene.addItem(Items.Grid())
        scene.addItem(Items.Axes())

        line = scene.addLine(QLineF(0, 0, 0, 0))

        cross = Items.NodeCross(movable=True)
        cross.addEdge(line, 1)
        scene.addItem(cross)

        help = scene.addText(QCoreApplication.translate('Graphics', 'Press "h" for help!'))
        help.moveBy(-50, 80)

        text = Items.NodeText(QCoreApplication.translate('Graphics', 'Drag Me!'))
        text.setFlag(QGraphicsItem.ItemIsMovable, True)
        text.setFlag(QGraphicsItem.ItemIsSelectable, True)
        text.addEdge(line, 2)
        scene.addItem(text)
        w.graphicsView.setScene(scene)
Ejemplo n.º 33
0
    def test_editlinksnode(self):
        reg = small_testing_registry()
        one_desc = reg.widget("one")
        negate_desc = reg.widget("negate")
        source_node = SchemeNode(one_desc, title="This is 1")
        sink_node = SchemeNode(negate_desc)

        scene = QGraphicsScene()
        view = QGraphicsView(scene)

        node = EditLinksNode(node=source_node)
        scene.addItem(node)

        node = EditLinksNode(direction=Qt.RightToLeft)
        node.setSchemeNode(sink_node)

        node.setPos(300, 0)
        scene.addItem(node)

        view.show()
        view.resize(800, 300)
        self.app.exec_()
Ejemplo n.º 34
0
    def __init__(self, parent=None):
        super(Lectern, self).__init__(parent)
        self.anchor = None
        
        self.initMainMenu()
        self.initToolbar()

        splitter = QSplitter()
        self.tocView = QTreeView()
        self.tocView.clicked.connect(self.navTo)
        self.tocModel = TableOfContents()
        self.tocModel.isEmpty.connect(self.handleTOCLoad)
        self.tocView.setModel(self.tocModel)
        self.tocView.expandAll()
        self.tocView.hide()
        splitter.addWidget(self.tocView)

        self.webView = QGraphicsWebView()
        frame = self.webView.page().mainFrame()
        scene = QGraphicsScene()
        scene.addItem(self.webView)
        self.graphicsView = GraphicsView(scene)
        self.graphicsView.setFrameShape(QFrame.NoFrame)
        glWidget = QGLWidget(self)
        self.graphicsView.setViewport(glWidget)

        self.webView.loadFinished.connect(self.handleLoad)

        splitter.addWidget(self.graphicsView)
        self.setCentralWidget(splitter)

        self.ebook_info = {}
        self.setWindowTitle('Lectern')

        try:
            self.ebook_info = self.openBook(QApplication.arguments()[1])
        except IndexError:
            pass
Ejemplo n.º 35
0
    def updateLanguage(self):
        # get the new language
        language = str(self.dlg.language_comboBox.currentText())
        # Change the self.language propertie and change the labe;s
        if language == "English":
            self.language = "EN"
            self.dlg.desc_lbl.setText("Description")
            self.dlg.preview_lbl.setText("Preview")
            self.dlg.load_btn.setText("Load")
            self.dlg.close_btn.setText("Close")
            self.dlg.search_lbl.setText("Search")
            self.dlg.info_btn.setText("Info")
        elif language == "Greek":
            self.language = "GR"
            self.dlg.desc_lbl.setText(unicode("Περιγραφή", 'utf-8'))
            self.dlg.preview_lbl.setText(unicode("Προεπισκόπηση",'utf-8'))
            self.dlg.load_btn.setText(unicode("Φόρτωση",'utf-8'))
            self.dlg.close_btn.setText(unicode("Κλείσιμο",'utf-8'))
            self.dlg.search_lbl.setText(unicode("Αναζήτηση",'utf-8'))
            self.dlg.info_btn.setText(unicode("Πληροφορίες", 'utf-8'))

        self.dlg.preview_lbl.setAlignment(Qt.AlignRight)
        #refill the table
        self.init_table()
        # clear description and quicklook
        self.dlg.textEdit.clear()
        # clear search box
        #text = self.dlg.search_lineEdit.setText("")
        self.init_searchBox()
        # make a new emptey scene to show
        if not self.dlg.graphicsView is None:
            scene = QGraphicsScene()
            pic = QPixmap()
            scene.addItem(QGraphicsPixmapItem(pic))
            self.dlg.graphicsView.setScene(scene)
            self.dlg.graphicsView.show()
Ejemplo n.º 36
0
    def updateLanguage(self):
        # get the new language
        language = str(self.dlg.language_comboBox.currentText())        
        # Change the self.language propertie and change the labe;s
        if language == "English":
            self.language = "EN"
            self.dlg.desc_lbl.setText("Description")
            self.dlg.preview_lbl.setText("Preview")
            self.dlg.load_btn.setText("Load")
            self.dlg.close_btn.setText("Close")
            self.dlg.search_lbl.setText("Search")
            self.dlg.info_btn.setText("Info")
        elif language == "Greek":
            self.language = "GR"
            self.dlg.desc_lbl.setText(unicode("Περιγραφή", 'utf-8'))
            self.dlg.preview_lbl.setText(unicode("Προεπισκόπηση",'utf-8'))
            self.dlg.load_btn.setText(unicode("Φόρτωση",'utf-8'))
            self.dlg.close_btn.setText(unicode("Κλείσιμο",'utf-8'))
            self.dlg.search_lbl.setText(unicode("Αναζήτηση",'utf-8'))
            self.dlg.info_btn.setText(unicode("Πληροφορίες", 'utf-8'))

        self.dlg.preview_lbl.setAlignment(Qt.AlignRight)
        #refill the table
        self.init_table()
        # clear description and quicklook
        self.dlg.textEdit.clear()
        # clear search box
        #text = self.dlg.search_lineEdit.setText("")
        self.init_searchBox()
        # make a new emptey scene to show
        if not self.dlg.graphicsView is None:
            scene = QGraphicsScene()
            pic = QPixmap()
            scene.addItem(QGraphicsPixmapItem(pic))
            self.dlg.graphicsView.setScene(scene)        
            self.dlg.graphicsView.show()          
Ejemplo n.º 37
0
class BumpersView(QGraphicsView):

    def __init__(self, *args):
        QGraphicsView.__init__(self, *args)
        self.move(2, 22)
        self.btnSize = 60
        self.setMaximumHeight(60)
        self.setMaximumWidth(332)
        self.setMinimumHeight(60)
        self.setMinimumWidth(332)
        self.adjustSize()
        self.scene = QGraphicsScene(self)
        self.setStyleSheet('background-color:transparent; border-width: 0px; border: 0px;')
        self.l1 = QPixmap(os.getcwd() + '/../icons/l1.png')
        self.l1 = self.l1.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.l1Item = QGraphicsPixmapItem(self.l1)
        self.l1Item.setOffset(QPointF(30, 0))
        self.scene.addItem(self.l1Item)
        self.r1 = QPixmap(os.getcwd() + '/../icons/r1.png')
        self.r1 = self.l1.scaled(self.btnSize, self.btnSize, Qt.KeepAspectRatio)
        self.r1Item = QGraphicsPixmapItem(self.r1)
        self.r1Item.setOffset(QPointF(200, 0))
        self.scene.addItem(self.r1Item)
        self.setScene(self.scene)
Ejemplo n.º 38
0
 def scene(self):
     scene = QGraphicsScene()
     scene.addItem(self.background_pixmap_item)
     scene.addItem(self.head_pixmap_item)
     return scene
Ejemplo n.º 39
0
class ClassDiagram(QWidget, itab_item.ITabItem):
    def __init__(self, actions, parent=None):
        QWidget.__init__(self, parent)
        itab_item.ITabItem.__init__(self)
        self.actions = actions
        self.graphicView = QGraphicsView(self)
        self.scene = QGraphicsScene()
        self.graphicView.setScene(self.scene)
        self.graphicView.setViewportUpdateMode(
            QGraphicsView.BoundingRectViewportUpdate)

        vLayout = QVBoxLayout(self)
        self.setLayout(vLayout)
        vLayout.addWidget(self.graphicView)
        self.scene.setItemIndexMethod(QGraphicsScene.NoIndex)
        self.scene.setSceneRect(-200, -200, 400, 400)
        self.graphicView.setMinimumSize(400, 400)
        actualProject = self.actions.ide.explorer.get_actual_project()
        arrClasses = self.actions._locator.get_classes_from_project(
            actualProject)
        #FIXME:dirty need to fix
        self.mX = -400
        self.mY = -320
        self.hightestY = self.mY
        filesList = []
        for elem in arrClasses:
            #loking for paths
            filesList.append(elem[2])
        for path in set(filesList):
            self.create_class(path)

    def create_class(self, path):
        content = file_manager.read_file_content(path)
        items = introspection.obtain_symbols(content)
        mYPadding = 10
        mXPadding = 10
        for classname, classdetail in list(items["classes"].items()):
            cl = ClassModel(self.graphicView, self.scene)
            cl.set_class_name(classname)
            self.fill_clases(cl, classdetail[1])
            self.scene.addItem(cl)
            cl.setPos(self.mX, self.mY)
            self.mX += cl._get_width() + mXPadding
            if self.hightestY < self.mY + cl.get_height():
                self.hightestY = self.mY + cl.get_height()
            if self.mX > 2000:
                self.mX = -400
                self.mY += self.hightestY + mYPadding

    def fill_clases(self, classComponent, classContent):
        funct = classContent['functions']
        classComponent.set_functions_list(funct)
        attr = classContent['attributes']
        classComponent.set_attributes_list(attr)

    def scale_view(self, scaleFactor):
        factor = self.graphicView.transform().scale(
            scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width()

        if factor > 0.05 and factor < 15:
            self.graphicView.scale(scaleFactor, scaleFactor)

    def keyPressEvent(self, event):

        taskList = {
            Qt.Key_Plus: lambda: self.scaleView(1.2),
            Qt.Key_Minus: lambda: self.scaleView(1 / 1.2)
        }
        if (event.key() in taskList):
            taskList[event.key()]()
        else:
            QWidget.keyPressEvent(self, event)
Ejemplo n.º 40
0
                    y = mappedParentRect.top(
                    ) + NodeGraphicsItem.LEAFSIZE[1] / 2
                elif y > mappedParentRect.bottom(
                ) - NodeGraphicsItem.LEAFSIZE[1] / 2:
                    y = mappedParentRect.bottom(
                    ) - NodeGraphicsItem.LEAFSIZE[1] / 2
                value = QPointF(x, y)

        elif change == QGraphicsItem.ItemPositionHasChanged:
            self.model.pos = value if isinstance(
                value, QPointF) else value.toPointF()

        return super(NodeGraphicsItem, self).itemChange(change, value)


if __name__ == '__main__':
    from PyQt4.QtGui import QApplication, QGraphicsView, QGraphicsScene
    from treenode import TreeNode
    import sys
    app = QApplication(sys.argv)
    myview = QGraphicsView()
    myscene = QGraphicsScene(QRectF(-400, -300, 800, 600))
    myview.setScene(myscene)
    rootnode = TreeNode(0, 'root')
    parentnode = TreeNode(1, 'grass land', parent=rootnode)
    leafnode = TreeNode(2, 'grass 1', parent=parentnode)
    # leafnode2 = TreeNode(3,'earth',parent=parentnode)
    myscene.addItem(NodeGraphicsItem(parentnode))
    myview.show()
    app.exec_()
Ejemplo n.º 41
0
class OWSieveDiagram(OWWidget):
    name = "Sieve Diagram"
    description = "Visualize the observed and expected frequencies " \
                  "for a combination of values."
    icon = "icons/SieveDiagram.svg"
    priority = 200

    inputs = [("Data", Table, "set_data", Default),
              ("Features", AttributeList, "set_input_features")]
    outputs = [("Selection", Table)]

    graph_name = "canvas"

    want_control_area = False

    settingsHandler = DomainContextHandler()
    attrX = ContextSetting("", exclude_metas=False)
    attrY = ContextSetting("", exclude_metas=False)
    selection = ContextSetting(set())

    def __init__(self):
        # pylint: disable=missing-docstring
        super().__init__()

        self.data = self.discrete_data = None
        self.attrs = []
        self.input_features = None
        self.areas = []
        self.selection = set()

        self.attr_box = gui.hBox(self.mainArea)
        model = VariableListModel()
        model.wrap(self.attrs)
        combo_args = dict(widget=self.attr_box,
                          master=self,
                          contentsLength=12,
                          callback=self.update_attr,
                          sendSelectedValue=True,
                          valueType=str,
                          model=model)
        fixed_size = (QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.attrXCombo = gui.comboBox(value="attrX", **combo_args)
        gui.widgetLabel(self.attr_box, "\u2715", sizePolicy=fixed_size)
        self.attrYCombo = gui.comboBox(value="attrY", **combo_args)
        self.vizrank, self.vizrank_button = SieveRank.add_vizrank(
            self.attr_box, self, "Score Combinations", self.set_attr)
        self.vizrank_button.setSizePolicy(*fixed_size)

        self.canvas = QGraphicsScene()
        self.canvasView = ViewWithPress(self.canvas,
                                        self.mainArea,
                                        handler=self.reset_selection)
        self.mainArea.layout().addWidget(self.canvasView)
        self.canvasView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvasView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        box = gui.hBox(self.mainArea)
        box.layout().addWidget(self.graphButton)
        box.layout().addWidget(self.report_button)

    def sizeHint(self):
        return QSize(450, 550)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.update_graph()

    def showEvent(self, event):
        super().showEvent(event)
        self.update_graph()

    def set_data(self, data):
        """
        Discretize continuous attributes, and put all attributes and discrete
        metas into self.attrs, which is used as a model for combos.

        Select the first two attributes unless context overrides this.
        Method `resolve_shown_attributes` is called to use the attributes from
        the input, if it exists and matches the attributes in the data.

        Remove selection; again let the context override this.
        Initialize the vizrank dialog, but don't show it.

        Args:
            data (Table): input data
        """
        if isinstance(data, SqlTable) and data.approx_len() > LARGE_TABLE:
            data = data.sample_time(DEFAULT_SAMPLE_TIME)

        self.closeContext()
        self.data = data
        self.areas = []
        self.selection = set()
        if self.data is None:
            self.attrs[:] = []
        else:
            if any(attr.is_continuous for attr in data.domain):
                discretizer = Discretize(method=EqualFreq(n=4),
                                         discretize_classes=True,
                                         discretize_metas=True)
                self.discrete_data = discretizer(data)
            else:
                self.discrete_data = self.data
            self.attrs[:] = [
                var for var in chain(self.discrete_data.domain, (
                    var for var in self.data.domain.metas if var.is_discrete))
            ]
        if self.attrs:
            self.attrX = self.attrs[0].name
            self.attrY = self.attrs[len(self.attrs) > 1].name
        else:
            self.attrX = self.attrY = None
            self.areas = []
            self.selection = set()
        self.openContext(self.data)
        self.resolve_shown_attributes()
        self.update_graph()
        self.update_selection()

        self.vizrank.initialize()
        self.vizrank_button.setEnabled(
            self.data is not None and len(self.data) > 1
            and len(self.data.domain.attributes) > 1)

    def set_attr(self, attr_x, attr_y):
        self.attrX, self.attrY = attr_x.name, attr_y.name
        self.update_attr()

    def update_attr(self):
        """Update the graph and selection."""
        self.selection = set()
        self.update_graph()
        self.update_selection()

    def set_input_features(self, attr_list):
        """
        Handler for the Features signal.

        The method stores the attributes and calls `resolve_shown_attributes`

        Args:
            attr_list (AttributeList): data from the signal
        """
        self.input_features = attr_list
        self.resolve_shown_attributes()
        self.update_selection()

    def resolve_shown_attributes(self):
        """
        Use the attributes from the input signal if the signal is present
        and at least two attributes appear in the domain. If there are
        multiple, use the first two. Combos are disabled if inputs are used.
        """
        self.warning()
        self.attr_box.setEnabled(True)
        if not self.input_features:  # None or empty
            return
        features = [f for f in self.input_features if f in self.attrs]
        if not features:
            self.warning(
                "Features from the input signal are not present in the data")
            return
        old_attrs = self.attrX, self.attrY
        self.attrX, self.attrY = [f.name for f in (features * 2)[:2]]
        self.attr_box.setEnabled(False)
        if (self.attrX, self.attrY) != old_attrs:
            self.selection = set()
            self.update_graph()

    def reset_selection(self):
        self.selection = set()
        self.update_selection()

    def select_area(self, area, event):
        """
        Add or remove the clicked area from the selection

        Args:
            area (QRect): the area that is clicked
            event (QEvent): event description
        """
        if event.button() != Qt.LeftButton:
            return
        index = self.areas.index(area)
        if event.modifiers() & Qt.ControlModifier:
            self.selection ^= {index}
        else:
            self.selection = {index}
        self.update_selection()

    def update_selection(self):
        """
        Update the graph (pen width) to show the current selection.
        Filter and output the data.
        """
        if self.areas is None or not self.selection:
            self.send("Selection", None)
            return

        filts = []
        for i, area in enumerate(self.areas):
            if i in self.selection:
                width = 4
                val_x, val_y = area.value_pair
                filts.append(
                    filter.Values([
                        filter.FilterDiscrete(self.attrX, [val_x]),
                        filter.FilterDiscrete(self.attrY, [val_y])
                    ]))
            else:
                width = 1
            pen = area.pen()
            pen.setWidth(width)
            area.setPen(pen)
        if len(filts) == 1:
            filts = filts[0]
        else:
            filts = filter.Values(filts, conjunction=False)
        selection = filts(self.discrete_data)
        if self.discrete_data is not self.data:
            idset = set(selection.ids)
            sel_idx = [i for i, id in enumerate(self.data.ids) if id in idset]
            selection = self.data[sel_idx]
        self.send("Selection", selection)

    def update_graph(self):
        # Function uses weird names like r, g, b, but it does it with utmost
        # caution, hence
        # pylint: disable=invalid-name
        """Update the graph."""
        def text(txt, *args, **kwargs):
            return CanvasText(self.canvas,
                              "",
                              html_text=to_html(txt),
                              *args,
                              **kwargs)

        def width(txt):
            return text(txt, 0, 0, show=False).boundingRect().width()

        def fmt(val):
            return str(int(val)) if val % 1 == 0 else "{:.2f}".format(val)

        def show_pearson(rect, pearson, pen_width):
            """
            Color the given rectangle according to its corresponding
            standardized Pearson residual.

            Args:
                rect (QRect): the rectangle being drawn
                pearson (float): signed standardized pearson residual
                pen_width (int): pen width (bolder pen is used for selection)
            """
            r = rect.rect()
            x, y, w, h = r.x(), r.y(), r.width(), r.height()
            if w == 0 or h == 0:
                return

            r = b = 255
            if pearson > 0:
                r = g = max(255 - 20 * pearson, 55)
            elif pearson < 0:
                b = g = max(255 + 20 * pearson, 55)
            else:
                r = g = b = 224
            rect.setBrush(QBrush(QColor(r, g, b)))
            pen_color = QColor(255 * (r == 255), 255 * (g == 255),
                               255 * (b == 255))
            pen = QPen(pen_color, pen_width)
            rect.setPen(pen)
            if pearson > 0:
                pearson = min(pearson, 10)
                dist = 20 - 1.6 * pearson
            else:
                pearson = max(pearson, -10)
                dist = 20 - 8 * pearson
            pen.setWidth(1)

            def _offseted_line(ax, ay):
                r = QGraphicsLineItem(x + ax, y + ay, x + (ax or w),
                                      y + (ay or h))
                self.canvas.addItem(r)
                r.setPen(pen)

            ax = dist
            while ax < w:
                _offseted_line(ax, 0)
                ax += dist

            ay = dist
            while ay < h:
                _offseted_line(0, ay)
                ay += dist

        def make_tooltip():
            """Create the tooltip. The function uses local variables from
            the enclosing scope."""

            # pylint: disable=undefined-loop-variable
            def _oper(attr_name, txt):
                if self.data.domain[attr_name] is ddomain[attr_name]:
                    return "="
                return " " if txt[0] in "<≥" else " in "

            return ("<b>{attrX}{xeq}{xval_name}</b>: {obs_x}/{n} ({p_x:.0f} %)"
                    .format(attrX=to_html(attr_x),
                            xeq=_oper(attr_x, xval_name),
                            xval_name=to_html(xval_name),
                            obs_x=fmt(chi.probs_x[x] * n),
                            n=int(n),
                            p_x=100 * chi.probs_x[x]) + "<br/>" +
                    "<b>{attrY}{yeq}{yval_name}</b>: {obs_y}/{n} ({p_y:.0f} %)"
                    .format(attrY=to_html(attr_y),
                            yeq=_oper(attr_y, yval_name),
                            yval_name=to_html(yval_name),
                            obs_y=fmt(chi.probs_y[y] * n),
                            n=int(n),
                            p_y=100 * chi.probs_y[y]) + "<hr/>" +
                    """<b>combination of values: </b><br/>
                   &nbsp;&nbsp;&nbsp;expected {exp} ({p_exp:.0f} %)<br/>
                   &nbsp;&nbsp;&nbsp;observed {obs} ({p_obs:.0f} %)""".format(
                        exp=fmt(chi.expected[y, x]),
                        p_exp=100 * chi.expected[y, x] / n,
                        obs=fmt(chi.observed[y, x]),
                        p_obs=100 * chi.observed[y, x] / n))

        for item in self.canvas.items():
            self.canvas.removeItem(item)
        if self.data is None or len(self.data) == 0 or \
                self.attrX is None or self.attrY is None:
            return

        ddomain = self.discrete_data.domain
        attr_x, attr_y = self.attrX, self.attrY
        disc_x, disc_y = ddomain[attr_x], ddomain[attr_y]
        view = self.canvasView

        chi = ChiSqStats(self.discrete_data, attr_x, attr_y)
        n = chi.n
        max_ylabel_w = max((width(val) for val in disc_y.values), default=0)
        max_ylabel_w = min(max_ylabel_w, 200)
        x_off = width(attr_x) + max_ylabel_w
        y_off = 15
        square_size = min(view.width() - x_off - 35,
                          view.height() - y_off - 50)
        square_size = max(square_size, 10)
        self.canvasView.setSceneRect(0, 0, view.width(), view.height())

        curr_x = x_off
        max_xlabel_h = 0
        self.areas = []
        for x, (px, xval_name) in enumerate(zip(chi.probs_x, disc_x.values)):
            if px == 0:
                continue
            width = square_size * px

            curr_y = y_off
            for y in range(len(chi.probs_y) - 1, -1, -1):  # bottom-up order
                py = chi.probs_y[y]
                yval_name = disc_y.values[y]
                if py == 0:
                    continue
                height = square_size * py

                selected = len(self.areas) in self.selection
                rect = CanvasRectangle(self.canvas,
                                       curr_x + 2,
                                       curr_y + 2,
                                       width - 4,
                                       height - 4,
                                       z=-10,
                                       onclick=self.select_area)
                rect.value_pair = x, y
                self.areas.append(rect)
                show_pearson(rect, chi.residuals[y, x], 3 * selected)
                rect.setToolTip(make_tooltip())

                if x == 0:
                    text(yval_name, x_off, curr_y + height / 2,
                         Qt.AlignRight | Qt.AlignVCenter)
                curr_y += height

            xl = text(xval_name, curr_x + width / 2, y_off + square_size,
                      Qt.AlignHCenter | Qt.AlignTop)
            max_xlabel_h = max(int(xl.boundingRect().height()), max_xlabel_h)
            curr_x += width

        bottom = y_off + square_size + max_xlabel_h
        text(attr_y,
             0,
             y_off + square_size / 2,
             Qt.AlignLeft | Qt.AlignVCenter,
             bold=True,
             vertical=True)
        text(attr_x,
             x_off + square_size / 2,
             bottom,
             Qt.AlignHCenter | Qt.AlignTop,
             bold=True)
        xl = text("χ²={:.2f}, p={:.3f}".format(chi.chisq, chi.p), 0, bottom)
        # Assume similar height for both lines
        text("N = " + fmt(chi.n), 0, bottom - xl.boundingRect().height())

    def get_widget_name_extension(self):
        if self.data is not None:
            return "{} vs {}".format(self.attrX, self.attrY)

    def send_report(self):
        self.report_plot()
Ejemplo n.º 42
0
class Ui_MRMainWindow(Ui_MainWindow):
    def __init__(self, moviemodel, worker):
        self._moviemodel = moviemodel
        self.worker = worker
        self.job_canceled = False

    def setupUi(self, MainWindow):
        super(Ui_MRMainWindow, self).setupUi(MainWindow)
        self._main_window = MainWindow
        self.listView.set_model(self._moviemodel)
        self._graphic_scene = QGraphicsScene()
        self.movieCoverView.setScene(self._graphic_scene)

        self.draw_toolbar()

        QtCore.QObject.connect(self.actionQuit,
                               QtCore.SIGNAL("triggered()"),
                               QtCore.QCoreApplication.instance().quit)

        QtCore.QObject.connect(self.listView,
                                QtCore.SIGNAL("itemClicked(QListWidgetItem *)"),
                                self.candidates_proposition_menu)

        QtCore.QObject.connect(self.listView,
                               QtCore.SIGNAL("currentItemChanged(\
                               QListWidgetItem *,QListWidgetItem *)"),
                               self.load_movie_infos_in_view)

        QtCore.QObject.connect(self.actionAddFiles,
                               QtCore.SIGNAL("triggered()"),
                               self.add_files)

        QtCore.QObject.connect(self.actionAddDirectory,
                               QtCore.SIGNAL("triggered()"),
                                self.add_directory)

        QtCore.QObject.connect(self.actionLaunchRenameAssistant,
                               QtCore.SIGNAL("triggered()"),
                               self.do_compute)

        QtCore.QObject.connect(self.actionLaunchFromSelection,
                               QtCore.SIGNAL("triggered()"),
                               self.do_compute_from_selection)

        QtCore.QObject.connect(self.actionSave,
                               QtCore.SIGNAL("triggered()"),
                               self.do_batch_save)

        QtCore.QObject.connect(self.cancelJobButton,
                               QtCore.SIGNAL("clicked()"),
                               self.canceljob)

        self.listView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        self.listView.connect(self.listView,
                        QtCore.SIGNAL("customContextMenuRequested(QPoint)"),
                        self.onContext)

        QtCore.QObject.connect(self._main_window,
                                QtCore.SIGNAL("progress(int)"),
                                self.update_progress_bar)

        QtCore.QObject.connect(self._main_window,
                                QtCore.SIGNAL("statusmessage(QString)"),
                                self.update_status_bar)

        QtCore.QObject.connect(self.listView,
                               QtCore.SIGNAL("dropped"),
                               self.file_dropped)
    def draw_toolbar(self):
        actions = [self.actionAddFiles,
                   self.actionAddDirectory,
                   self.actionLaunchRenameAssistant,
                   self.actionLaunchFromSelection,
                   self.actionSave,
                   self.actionQuit]
        for action in actions:
            button = QtGui.QToolButton()
            button.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
            button.addAction(action)
            button.setDefaultAction(action)
            self.toolBar.addWidget(button)
        self.toolBar.show()

    def file_dropped(self, links):
            self.build_model_from_files(links)

    def load_movie_infos_in_view(self, item, previous):
        if len(self._moviemodel.data()) == 0:
            print 'modele vide'
            self.filenamEdit.setText("")
            self.titleEdit.setText("")
            self.imdbLinkEdit.setText("")
            self.descriptionEdit.setText("")
            self._graphic_scene.clear()
            return

        if item == None:
            return

        movie = self.listView.item_to_movie[item]
        self.filenamEdit.setText(movie.get_filename())
        self.titleEdit.setText(movie.get_title())
        self.imdbLinkEdit.setText(movie.get_imdb_link())
        self.descriptionEdit.setText(movie.get_desc())

        self._graphic_scene.clear()
        if movie.get_cover() != "":
            pixmap = QtGui.QPixmap(movie.get_cover())
            pixmap = pixmap.scaled(self.movieCoverView.size())
            qitem = QDraggableGraphicsPixmapItem(movie.get_cover(), pixmap)
            self._graphic_scene.addItem(qitem)

    def add_files(self):
        file_extensions = " ".join(map((lambda x: "*." + x),
                                       EXTENSIONS))
        files = QFileDialog.getOpenFileNames(
            None,
            "Select one or more files to open",
            "/home",
            "Video Files (" + file_extensions + ")")
        self.build_model_from_files([unicode(x) for x in files])

    def add_directory(self):
        direct = QFileDialog.getExistingDirectory(None,
                        "Open Directory", "/home",
                         QFileDialog.ShowDirsOnly)
        self.build_model_from_files([unicode(direct)])

    def build_model_from_files(self, files=[]):
        files = FileTools.recurse_files(files)
        for movie in xrange(len(files)):
            m = Movie(files[movie])
            self._moviemodel.add_movie(m)

    def onContext(self, point):
        if (len(self._moviemodel.data()) == 0) or (self.worker.job != None):
            return
        menu = QtGui.QMenu("Context Menu", self._main_window)
        assist = QtGui.QAction("Rename assistant", None)
        ignore = QtGui.QAction("Ignore", None)
        remove = QtGui.QAction("Remove", None)
        reset = QtGui.QAction("Undo modifications", None)
        save = QtGui.QAction("Save", None)
        rmall = QtGui.QAction("Remove all", None)

        menu.addAction(assist)
        menu.addAction(reset)
        menu.addAction(save)
        #menu.addAction(ignore)
        menu.addAction(remove)
        menu.addAction(rmall)

        res = menu.exec_(self.listView.mapToGlobal(point))
        item = self.listView.currentItem()
        movie = self.listView.item_to_movie[item]

        if res == save:
            self._moviemodel.save_movie(movie)

        if res == remove:
            self._moviemodel.remove_movie(movie)

        if res == reset:
            self._moviemodel.reset_movie_informations(movie)
            self.load_movie_infos_in_view(item, None)

        if res == assist:
            self.worker.do(self.do_compute_sub, movie)

        if res == ignore:
            pass

        if res == rmall:
            movies = list(self._moviemodel.data())
            for movie in movies:
                self._moviemodel.remove_movie(movie)

    def candidates_proposition_menu(self, item):
        movie = self.listView.item_to_movie[item]
        menu = QtGui.QMenu("Propositions", self._main_window)

        candidates = self._moviemodel.get_candidates(movie)
        if(len(candidates) == 0):
            return
        tmp = {}
        if candidates != []:
            for j in candidates:
                i = unicode(j)
                proposition = i[0:min(len(i), 100)]
                a = QtGui.QAction(proposition, None)
                tmp[a] = j
                menu.addAction(a)
        else:
            pass

        res = menu.exec_(QtGui.QCursor.pos())
        if res != None:
            self._moviemodel.affect_candidate(movie, tmp[res])
            self.load_movie_infos_in_view(item, None)

    def do_compute(self):
        self.worker.do(self.do_compute_sub)

    def do_compute_from_selection(self):
        self.worker.do(self.do_compute_sub, selection=True)

    def update_progress_bar(self, val):
        self.progressBar.setProperty("value", val)

    def update_status_bar(self, val):
        self.statusbar.showMessage(val)

    def do_compute_sub(self, movie=(), selection=False):
        self.job_canceled = False
        self._set_enable_toolbar(False)
        self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                               "Querying Google. This may take some time ....")
        self._main_window.emit(QtCore.SIGNAL("progress(int)"), 0)
        #allocine_engine = GoogleQuery()
        allocine_engine = AllocineQuery()
        google_engine = GoogleQuery()
        movies = self._moviemodel.data()

        if movie != ():
            movies = [movie[0]]

        if selection:
            indexes = self.listView.selectedIndexes()
            if len(indexes) > 0:
                firstindex = indexes[0]
                movies = movies[firstindex.row():]

        for i in xrange(len(movies)):
            if self.job_canceled:
                self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                                       "Job cancelled.")
                break
            current_movie = movies[i]
            self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                                   "Processing: %s"%(current_movie.get_title()))

            query = FileTools.preprocess_query(current_movie.get_title())
            propositions = allocine_engine.extract_results(allocine_engine.query(query))
            if len(propositions) == 0:
                propositions = google_engine.extract_results(google_engine.query(query))
            def sorter(x,y):
                if "title" in x.get_imdb_link():
                    if "title" in y.get_imdb_link():
                        return 0
                    return -1
                return 1
            propositions.sort(sorter)
            self._moviemodel.set_candidates(current_movie, propositions)
            if(len(propositions) > 0):
                self._moviemodel.affect_candidate(current_movie,
                                                  propositions[0])
            self._main_window.emit(QtCore.SIGNAL("progress(int)"),
                                   (i + 1) * 100 / len(movies))
            time.sleep(SLEEP)
        self._main_window.emit(QtCore.SIGNAL("progress(int)"), 0)
        self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                               "Finished.")
        self._set_enable_toolbar(True)

    def do_batch_save(self):
        self.worker.do(self.do_batch_save_sub)

    def do_batch_save_sub(self, args, kwargs):
        data = self._moviemodel.data()
        for movie in data:
            if movie.has_changed():
                self._moviemodel.save_movie(movie)

    def canceljob(self):
        self.job_canceled = True
        self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                               "Abording current job. Please wait...")

    def _set_enable_toolbar(self, enabled):
        for action in self.toolBar.actions():
            action.setEnabled(enabled)
Ejemplo n.º 43
0
class MainForm(QDialog):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)
        self.Running = False
        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, SCENESIZEX, SCENESIZEY)
        self.view = QGraphicsView()
        self.view.setRenderHint(QPainter.Antialiasing)
        self.view.setScene(self.scene)
        self.view.setFocusPolicy(Qt.NoFocus)
        #self.zoomSlider = QSlider(Qt.Horizontal)
        #self.zoomSlider.setRange(5, 200)
        #self.zoomSlider.setValue(100)
        self.pauseButton = QPushButton("Pa&use")
        self.quitButton = QPushButton("&Quit")

        layout = QVBoxLayout()
        layout.addWidget(self.view)
        #layout.addWidget(self.zoomSlider)
        layout.addWidget(self.pauseButton)
        layout.addWidget(self.quitButton)
        self.setLayout(layout)

        #self.connect(self.zoomSlider, SIGNAL("valueChanged(int))"),
        #             self.zoom)
        self.connect(self.pauseButton, SIGNAL("clicked()"), self.pauseOrResume)
        self.connect(self.quitButton, SIGNAL("clicked()"), self.accept)

        self.readNodes()
        self.zoom(1.0)
        self.populate()
        #self.startTimer(INTERVAL)
        self.setWindowTitle("TdPaleo")

    def pauseOrResume(self):
        self.Running = not self.Running
        self.pauseButton.setText("Pa&use" if self.Running else "Res&ume")
        items = self.scene.items()
        for item in items:
            item.setRunning()

    def zoom(self, value):
        factor = 1 / 1.5
        matrix = self.view.matrix()
        matrix.reset()
        matrix.scale(factor, factor)
        self.view.setMatrix(matrix)

    def readNodes(self):
        file = open("tdp_geometry.dat")
        file.readline()
        while True:
            line = file.readline()
            if not line:
                break
            param = line.split(" ")
            if (line != "\n"):
                n = node()
                n.x = float(param[0])
                n.y = 956 - float(param[1])
                n.angle = float(param[2])
                n.d = int(param[3])
                n.type = int(param[4])
                nodes.append(n)

    def populate(self):
        color = QColor(0, 150, 0)
        head = TdPCavallo(color, nodes[0].angle,
                          QPointF(nodes[0].x, nodes[0].y))
        #FIXME AGGIUNGERE POI IL FANTINO AL CAVALLO
        #segment = Segment(color, offset, head)
        self.scene.addItem(head)
        #Running = False

    def timerEvent(self, event):
        if not self.Running:
            return
    start = time.time()
    path_items = generate_path_items_for_labels(pen_table, labels_img, None)
    print "generate took {}".format(time.time() - start)  # 52 ms

    edges_item = SegmentationEdgesItem(path_items, pen_table)

    def assign_random_color(id_pair, buttons):
        print "handling click: {}".format(id_pair)
        pen = pen_table[id_pair]
        if pen:
            pen = QPen(pen)
        else:
            pen = QPen()
        random_color = QColor(*list(np.random.randint(0, 255, (3, ))))
        pen.setColor(random_color)
        pen_table[id_pair] = pen

    edges_item.edgeClicked.connect(assign_random_color)

    scene = QGraphicsScene()
    scene.addItem(edges_item)

    transform = QTransform()
    transform.scale(5.0, 5.0)

    view = QGraphicsView(scene)
    view.setTransform(transform)
    view.show()
    view.raise_()
    app.exec_()
Ejemplo n.º 45
0
class OWVennDiagram(widget.OWWidget):
    name = "Venn Diagram"
    description = "A graphical visualization of an overlap of data instances " \
                  "from a collection of input data sets."
    icon = "icons/VennDiagram.svg"

    inputs = [("Data", Orange.data.Table, "setData", widget.Multiple)]
    outputs = [("Selected Data", Orange.data.Table)]

    # Selected disjoint subset indices
    selection = settings.Setting([])
    #: Stored input set hints
    #: {(index, inputname, attributes): (selectedattrname, itemsettitle)}
    #: The 'selectedattrname' can be None
    inputhints = settings.Setting({})
    #: Use identifier columns for instance matching
    useidentifiers = settings.Setting(True)
    autocommit = settings.Setting(True)

    want_graph = True

    def __init__(self):
        super().__init__()

        # Diagram update is in progress
        self._updating = False
        # Input update is in progress
        self._inputUpdate = False
        # All input tables have the same domain.
        self.samedomain = True
        # Input datasets in the order they were 'connected'.
        self.data = OrderedDict()
        # Extracted input item sets in the order they were 'connected'
        self.itemsets = OrderedDict()

        # GUI
        box = gui.widgetBox(self.controlArea, "Info")
        self.info = gui.widgetLabel(box, "No data on input\n")

        self.identifiersBox = gui.radioButtonsInBox(
            self.controlArea, self, "useidentifiers", [],
            box="Data Instance Identifiers",
            callback=self._on_useidentifiersChanged
        )
        self.useequalityButton = gui.appendRadioButton(
            self.identifiersBox, "Use instance equality"
        )
        rb = gui.appendRadioButton(
            self.identifiersBox, "Use identifiers"
        )
        self.inputsBox = gui.indentedBox(
            self.identifiersBox, sep=gui.checkButtonOffsetHint(rb)
        )
        self.inputsBox.setEnabled(bool(self.useidentifiers))

        for i in range(5):
            box = gui.widgetBox(self.inputsBox, "Data set #%i" % (i + 1),
                                addSpace=False)
            box.setFlat(True)
            model = itemmodels.VariableListModel(parent=self)
            cb = QComboBox(
                minimumContentsLength=12,
                sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon)
            cb.setModel(model)
            cb.activated[int].connect(self._on_inputAttrActivated)
            box.setEnabled(False)
            # Store the combo in the box for later use.
            box.combo_box = cb
            box.layout().addWidget(cb)

        gui.rubber(self.controlArea)

        gui.auto_commit(self.controlArea, self, "autocommit",
                        "Commit", "Auto commit")

        # Main area view
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.setRenderHint(QPainter.Antialiasing)
        self.view.setBackgroundRole(QPalette.Window)
        self.view.setFrameStyle(QGraphicsView.StyledPanel)

        self.mainArea.layout().addWidget(self.view)
        self.vennwidget = VennDiagram()
        self.vennwidget.resize(400, 400)
        self.vennwidget.itemTextEdited.connect(self._on_itemTextEdited)
        self.scene.selectionChanged.connect(self._on_selectionChanged)

        self.scene.addItem(self.vennwidget)

        self.resize(self.controlArea.sizeHint().width() + 550,
                    max(self.controlArea.sizeHint().height(), 550))

        self._queue = []
        self.graphButton.clicked.connect(self.save_graph)

    @check_sql_input
    def setData(self, data, key=None):
        self.error(0)
        if not self._inputUpdate:
            # Store hints only on the first setData call.
            self._storeHints()
            self._inputUpdate = True

        if key in self.data:
            if data is None:
                # Remove the input
                self._remove(key)
            else:
                # Update existing item
                self._update(key, data)
        elif data is not None:
            # TODO: Allow setting more them 5 inputs and let the user
            # select the 5 to display.
            if len(self.data) == 5:
                self.error(0, "Can only take 5 inputs.")
                return
            # Add a new input
            self._add(key, data)

    def handleNewSignals(self):
        self._inputUpdate = False

        # Check if all inputs are from the same domain.
        domains = [input.table.domain for input in self.data.values()]
        samedomain = all(domain_eq(d1, d2) for d1, d2 in pairwise(domains))

        self.useequalityButton.setEnabled(samedomain)
        self.samedomain = samedomain

        has_identifiers = all(source_attributes(input.table.domain)
                              for input in self.data.values())

        if not samedomain and not self.useidentifiers:
            self.useidentifiers = 1
        elif samedomain and not has_identifiers:
            self.useidentifiers = 0

        incremental = all(inc for _, inc in self._queue)

        if incremental:
            # Only received updated data on existing link.
            self._updateItemsets()
        else:
            # Links were removed and/or added.
            self._createItemsets()
            self._restoreHints()
            self._updateItemsets()

        del self._queue[:]

        self._createDiagram()
        if self.data:
            self.info.setText(
                "{} data sets on input.\n".format(len(self.data)))
        else:
            self.info.setText("No data on input\n")

        self._updateInfo()
        super().handleNewSignals()

    def _invalidate(self, keys=None, incremental=True):
        """
        Invalidate input for a list of input keys.
        """
        if keys is None:
            keys = list(self.data.keys())

        self._queue.extend((key, incremental) for key in keys)

    def itemsetAttr(self, key):
        index = list(self.data.keys()).index(key)
        _, combo = self._controlAtIndex(index)
        model = combo.model()
        attr_index = combo.currentIndex()
        if attr_index >= 0:
            return model[attr_index]
        else:
            return None

    def _controlAtIndex(self, index):
        group_box = self.inputsBox.layout().itemAt(index).widget()
        combo = group_box.combo_box
        return group_box, combo

    def _setAttributes(self, index, attrs):
        box, combo = self._controlAtIndex(index)
        model = combo.model()

        if attrs is None:
            model[:] = []
            box.setEnabled(False)
        else:
            if model[:] != attrs:
                model[:] = attrs

            box.setEnabled(True)

    def _add(self, key, table):
        name = table.name
        index = len(self.data)
        attrs = source_attributes(table.domain)

        self.data[key] = _InputData(key, name, table)

        self._setAttributes(index, attrs)

        self._invalidate([key], incremental=False)

        item = self.inputsBox.layout().itemAt(index)
        box = item.widget()
        box.setTitle("Data set: {}".format(name))

    def _remove(self, key):
        index = list(self.data.keys()).index(key)

        # Clear possible warnings.
        self.warning(index)

        self._setAttributes(index, None)

        del self.data[key]

        layout = self.inputsBox.layout()
        item = layout.takeAt(index)
        layout.addItem(item)
        inputs = list(self.data.values())

        for i in range(5):
            box, _ = self._controlAtIndex(i)
            if i < len(inputs):
                title = "Data set: {}".format(inputs[i].name)
            else:
                title = "Data set #{}".format(i + 1)
            box.setTitle(title)

        self._invalidate([key], incremental=False)

    def _update(self, key, table):
        name = table.name
        index = list(self.data.keys()).index(key)
        attrs = source_attributes(table.domain)

        self.data[key] = self.data[key]._replace(name=name, table=table)

        self._setAttributes(index, attrs)
        self._invalidate([key])

        item = self.inputsBox.layout().itemAt(index)
        box = item.widget()
        box.setTitle("Data set: {}".format(name))

    def _itemsForInput(self, key):
        useidentifiers = self.useidentifiers or not self.samedomain

        def items_by_key(key, input):
            attr = self.itemsetAttr(key)
            if attr is not None:
                return [str(inst[attr]) for inst in input.table
                        if not numpy.isnan(inst[attr])]
            else:
                return []

        def items_by_eq(key, input):
            return list(map(ComparableInstance, input.table))

        input = self.data[key]
        if useidentifiers:
            items = items_by_key(key, input)
        else:
            items = items_by_eq(key, input)
        return items

    def _updateItemsets(self):
        assert list(self.data.keys()) == list(self.itemsets.keys())
        for key, input in list(self.data.items()):
            items = self._itemsForInput(key)
            item = self.itemsets[key]
            item = item._replace(items=items)
            name = input.name
            if item.name != name:
                item = item._replace(name=name, title=name)
            self.itemsets[key] = item

    def _createItemsets(self):
        olditemsets = dict(self.itemsets)
        self.itemsets.clear()

        for key, input in self.data.items():
            items = self._itemsForInput(key)
            name = input.name
            if key in olditemsets and olditemsets[key].name == name:
                # Reuse the title (which might have been changed by the user)
                title = olditemsets[key].title
            else:
                title = name

            itemset = _ItemSet(key=key, name=name, title=title, items=items)
            self.itemsets[key] = itemset

    def _storeHints(self):
        if self.data:
            self.inputhints.clear()
            for i, (key, input) in enumerate(self.data.items()):
                attrs = source_attributes(input.table.domain)
                attrs = tuple(attr.name for attr in attrs)
                selected = self.itemsetAttr(key)
                if selected is not None:
                    attr_name = selected.name
                else:
                    attr_name = None
                itemset = self.itemsets[key]
                self.inputhints[(i, input.name, attrs)] = \
                    (attr_name, itemset.title)

    def _restoreHints(self):
        settings = []
        for i, (key, input) in enumerate(self.data.items()):
            attrs = source_attributes(input.table.domain)
            attrs = tuple(attr.name for attr in attrs)
            hint = self.inputhints.get((i, input.name, attrs), None)
            if hint is not None:
                attr, name = hint
                attr_ind = attrs.index(attr) if attr is not None else -1
                settings.append((attr_ind, name))
            else:
                return

        # all inputs match the stored hints
        for i, key in enumerate(self.itemsets):
            attr, itemtitle = settings[i]
            self.itemsets[key] = self.itemsets[key]._replace(title=itemtitle)
            _, cb = self._controlAtIndex(i)
            cb.setCurrentIndex(attr)

    def _createDiagram(self):
        self._updating = True

        oldselection = list(self.selection)

        self.vennwidget.clear()
        n = len(self.itemsets)
        self.disjoint = disjoint(set(s.items) for s in self.itemsets.values())

        vennitems = []
        colors = colorpalette.ColorPaletteHSV(n)

        for i, (key, item) in enumerate(self.itemsets.items()):
            gr = VennSetItem(text=item.title, count=len(item.items))
            color = colors[i]
            color.setAlpha(100)
            gr.setBrush(QBrush(color))
            gr.setPen(QPen(Qt.NoPen))
            vennitems.append(gr)

        self.vennwidget.setItems(vennitems)

        for i, area in enumerate(self.vennwidget.vennareas()):
            area_items = list(map(str, list(self.disjoint[i])))
            if i:
                area.setText("{0}".format(len(area_items)))

            label = disjoint_set_label(i, n, simplify=False)
            head = "<h4>|{}| = {}</h4>".format(label, len(area_items))
            if len(area_items) > 32:
                items_str = ", ".join(map(escape, area_items[:32]))
                hidden = len(area_items) - 32
                tooltip = ("{}<span>{}, ...</br>({} items not shown)<span>"
                           .format(head, items_str, hidden))
            elif area_items:
                tooltip = "{}<span>{}</span>".format(
                    head,
                    ", ".join(map(escape, area_items))
                )
            else:
                tooltip = head

            area.setToolTip(tooltip)

            area.setPen(QPen(QColor(10, 10, 10, 200), 1.5))
            area.setFlag(QGraphicsPathItem.ItemIsSelectable, True)
            area.setSelected(i in oldselection)

        self._updating = False
        self._on_selectionChanged()

    def _updateInfo(self):
        # Clear all warnings
        self.warning(list(range(5)))

        if not len(self.data):
            self.info.setText("No data on input\n")
        else:
            self.info.setText(
                "{0} data sets on input\n".format(len(self.data)))

        if self.useidentifiers:
            for i, key in enumerate(self.data):
                if not source_attributes(self.data[key].table.domain):
                    self.warning(i, "Data set #{} has no suitable identifiers."
                                 .format(i + 1))

    def _on_selectionChanged(self):
        if self._updating:
            return

        areas = self.vennwidget.vennareas()
        indices = [i for i, area in enumerate(areas)
                   if area.isSelected()]

        self.selection = indices

        self.invalidateOutput()

    def _on_useidentifiersChanged(self):
        self.inputsBox.setEnabled(self.useidentifiers == 1)
        # Invalidate all itemsets
        self._invalidate()
        self._updateItemsets()
        self._createDiagram()

        self._updateInfo()

    def _on_inputAttrActivated(self, attr_index):
        combo = self.sender()
        # Find the input index to which the combo box belongs
        # (they are reordered when removing inputs).
        index = None
        inputs = list(self.data.items())
        for i in range(len(inputs)):
            _, c = self._controlAtIndex(i)
            if c is combo:
                index = i
                break

        assert (index is not None)

        key, _ = inputs[index]

        self._invalidate([key])
        self._updateItemsets()
        self._createDiagram()

    def _on_itemTextEdited(self, index, text):
        text = str(text)
        key = list(self.itemsets.keys())[index]
        self.itemsets[key] = self.itemsets[key]._replace(title=text)

    def invalidateOutput(self):
        self.commit()

    def commit(self):
        selected_subsets = []

        selected_items = reduce(
            set.union, [self.disjoint[index] for index in self.selection],
            set()
        )
        def match(val):
            if numpy.isnan(val):
                return False
            else:
                return str(val) in selected_items

        source_var = Orange.data.StringVariable("source")
        item_id_var = Orange.data.StringVariable("item_id")

        names = [itemset.title.strip() for itemset in self.itemsets.values()]
        names = uniquify(names)

        for i, (key, input) in enumerate(self.data.items()):
            if self.useidentifiers:
                attr = self.itemsetAttr(key)
                if attr is not None:
                    mask = list(map(match, (inst[attr] for inst in input.table)))
                else:
                    mask = [False] * len(input.table)

                def instance_key(inst):
                    return str(inst[attr])
            else:
                mask = [ComparableInstance(inst) in selected_items
                        for inst in input.table]
                _map = {item: str(i) for i, item in enumerate(selected_items)}

                def instance_key(inst):
                    return _map[ComparableInstance(inst)]

            mask = numpy.array(mask, dtype=bool)
            subset = Orange.data.Table(input.table.domain,
                                       input.table[mask])
            subset.ids = input.table.ids[mask]
            if len(subset) == 0:
                continue

            # add columns with source table id and set id

            id_column = numpy.array([[instance_key(inst)] for inst in subset],
                                    dtype=object)
            source_names = numpy.array([[names[i]]] * len(subset),
                                       dtype=object)

            subset = append_column(subset, "M", source_var, source_names)
            subset = append_column(subset, "M", item_id_var, id_column)

            selected_subsets.append(subset)

        if selected_subsets:
            data = table_concat(selected_subsets)
            # Get all variables which are not constant between the same
            # item set
            varying = varying_between(data, [item_id_var])

            if source_var in varying:
                varying.remove(source_var)

            data = reshape_wide(data, varying, [item_id_var], [source_var])
            # remove the temporary item set id column
            data = drop_columns(data, [item_id_var])
        else:
            data = None

        self.send("Selected Data", data)

    def getSettings(self, *args, **kwargs):
        self._storeHints()
        return super().getSettings(self, *args, **kwargs)

    def save_graph(self):
        from Orange.widgets.data.owsave import OWSave

        save_img = OWSave(data=self.scene,
                          file_formats=FileFormat.img_writers)
        save_img.exec_()
Ejemplo n.º 46
0
class DualImageView(QGraphicsView):
    VERTICAL = 0
    HORIZONTAL = 1
    IMAGE_A = 0
    IMAGE_B = 1

    # no argument signal
    images_changed = pyqtSignal()
    annotations_changed = pyqtSignal()
    annotation_selected = pyqtSignal(int)
    no_selection = pyqtSignal()

    # click/point signals
    image_a_click = pyqtSignal(int,int)
    image_b_click = pyqtSignal(int,int)    

    # keyboard
    key_event = pyqtSignal(int)

    def __init__(self, main_win):
        super(QGraphicsView,self).__init__(main_win)
        self.parent_ = main_win
        self.main_win_ = main_win
        self.setInteractive(True)

        self.setStyleSheet("QGraphicsView { border: none; }")
        
        self.scene_ = QGraphicsScene(0,0,0,0,self.parent_)
        self.image_item_ = self.scene_.addPixmap(QPixmap())
        self.image_item_.setPos(0,0)
        #self.ann_group_ = QGraphicsItemGroup()
        #self.ann_group_.setPos(0,0)
        #self.scene_.addItem(self.ann_group_)
        self.setScene(self.scene_)
        self.scene_.selectionChanged.connect(self.on_selection_changed)
        
        # TODO: handle orientation
        self.orientation_ = DualImageView.VERTICAL
        self.images_ = [None, None]
        self.composite_ = None
        self.annotations_ = []
        self.dim_ = 0
        self.offset_ = np.array([0,0])
        self.cancel_click_ = False
        
        self.images_changed.connect(self.on_images_changed)
        self.annotations_changed.connect(self.on_annotations_changed)

    def on_selection_changed(self):
        log.debug("on_selection_changed")
        selected = self.scene_.selectedItems()
        if len(selected) > 0:
            self.cancel_click_ = True
            selected = self.scene_.selectedItems()[0]
            idx = -1
            for a in self.annotations_:
                idx += 1
                if a.item == selected:
                    log.debug(" emitting selection {0}".format(idx))
                    self.annotation_selected.emit(idx)
        else:
            self.no_selection.emit()

    @property
    def image_b_offset(self):
        return np.array([0,self.dim_],dtype=np.int32)

    def point_in_image(self, p):
        if p[1] < self.dim_:
            return 0
        else:
            return 1

    def point_to_image(self, which, p):
        if which == DualImageView.IMAGE_B:
            return p - self.image_b_offset
        return p

    def image_to_view(self, which, p):
        if which == DualImageView.IMAGE_B:
            return p + self.image_b_offset
        return p

    def on_images_changed(self):
        imga = self.images_[0]
        imgb = self.images_[1]
        width = max(imga.shape[1],imgb.shape[1])
        heighta = imga.shape[0]
        heightb = imgb.shape[0]
        height = heighta + heightb
        self.dim_ = heighta
        self.offset_ = np.array([0,heighta])
        # this assumes rgb images :-(
        comp = np.empty((height,width,imga.shape[2]),dtype=imga.dtype)
        comp[0:heighta,:imga.shape[1],:] = imga
        comp[heighta:(heighta+heightb),:imgb.shape[1],:] = imgb
        self.composite_ = comp
        qimg = qn.array2qimage(self.composite_)
        pix = QPixmap.fromImage(qimg)
        self.image_item_.setPixmap(pix)
        self.scene_.setSceneRect(0,0, width, height)
        self.repaint()
        
    def on_annotations_changed(self):
        #log.debug("on_annotations_changed")
        # self.scene_.removeItem(self.ann_group_)
        # self.ann_group_ = QGraphicsItemGroup()
        # self.ann_group_.setHandlesChildEvents(False)
        # self.ann_group_.setPos(0,0)
        # for a in self.annotations_:
        #     log.debug(" adding item")
        #     self.ann_group_.addToGroup(a.get_item())
        # self.scene_.addItem(self.ann_group_)
        self.repaint()

    def transform_raw_pt(self, ev):
        pt = self.mapToScene(ev.x(), ev.y())
        return np.array([int(pt.x()), int(pt.y())], dtype=np.int32)

    def clear(self):
        self.images_ = [None,None]
        self.composite_ = None
        self.annotations_ = None
        self.images_changed.emit()
        self.annotations_changed.emit()
        
    def set_images(self, img_pair):
        self.images_ = img_pair
        self.images_changed.emit()

    # @property
    # def annotations(self):
    #     return self.annotations_
    
    # @annotations.setter
    # def annotations(self, anns):
    #     self.annotations_ = anns
    #     self.annotations_changed.emit()

    # def set_annotations(self, anns):
    #     self.annotations_ = anns
    #     self.annotations_changed.emit()

    def paintEvent(self, ev):
        painter = QPainter(self.viewport())
        painter.fillRect(0,0,self.viewport().width(),self.viewport().height(), QColor(0,0,0))
        painter.end()
        QGraphicsView.paintEvent(self, ev)

    def annotation(self, idx):
        return self.annotations_[idx]

    def clear_annotations(self):
        for a in self.annotations_:
            self.scene_.removeItem(a.item)
        self.annotations_ = []
        self.annotations_changed.emit()

    def add_annotation(self, ann):
        ann.changed.connect(self.on_annotations_changed)
        self.annotations_.append(ann)
        self.scene_.addItem(ann.item)
        self.annotations_changed.emit()
        return len(self.annotations_) - 1
        
    def remove_last_annotation(self):
        self.scene_.removeItem(self.annotations_[-1].item)
        del self.annotations_[-1]
        self.annotations_changed.emit()

    def remove_annotation(self, idx):
        self.scene_.removeItem(self.annotations_[idx].item)
        del self.annotations_[idx]
        self.annotations_changed.emit()

    def mousePressEvent(self, ev):
        super(DualImageView,self).mousePressEvent(ev)
        if self.cancel_click_:
            return
        log.debug("mouse pressed: " + str(ev))
        self.img_local_pt = self.transform_raw_pt(ev)

    def mouseReleaseEvent(self, ev):
        super(DualImageView,self).mouseReleaseEvent(ev)
        if self.cancel_click_:
            self.cancel_click_ = False
            return
        log.debug("mouse released: " + str(ev))
        rel_pt = self.transform_raw_pt(ev)
        delta = rel_pt - self.img_local_pt
        if abs(delta[0]) < 3 and abs(delta[1] < 3):
            # it was a successful click
            self.mouseClicked(self.img_local_pt)
        else: 
            # recognize this as a rectangle drag
            self.mouseDragged(self.img_local_pt, delta)

    def mouseDragged(self, pt, delta):
        log.debug("mouse dragged: {0}, {1}".format(pt,delta))

    def mouseClicked(self, pt):
        log.debug("mouse clicked: {0}".format(pt))
        if pt[1] < self.dim_:
            self.image_a_click.emit(pt[0],pt[1])
        else:
            self.image_b_click.emit(pt[0],pt[1] - self.dim_)

    # handle the keyboard events here!
    def keyPressEvent(self, ev):
        pass

    def keyReleaseEvent(self, ev):
        k = ev.key()
        self.key_event.emit(k)
Ejemplo n.º 47
0
class OWHierarchicalClustering(widget.OWWidget):
    name = "Hierarchical Clustering"
    description = ("Hierarchical clustering based on distance matrix, and "
                   "a dendrogram viewer.")
    icon = "icons/HierarchicalClustering.svg"
    priority = 2100

    inputs = [("Distances", Orange.misc.DistMatrix, "set_distances")]

    outputs = [("Selected Data", Orange.data.Table),
               ("Other Data", Orange.data.Table)]

    #: Selected linkage
    linkage = settings.Setting(1)
    #: Index of the selected annotation item (variable, ...)
    annotation_idx = settings.Setting(0)
    #: Selected tree pruning (none/max depth)
    pruning = settings.Setting(0)
    #: Maximum depth when max depth pruning is selected
    max_depth = settings.Setting(10)

    #: Selected cluster selection method (none, cut distance, top n)
    selection_method = settings.Setting(0)
    #: Cut height ratio wrt root height
    cut_ratio = settings.Setting(75.0)
    #: Number of top clusters to select
    top_n = settings.Setting(3)

    append_clusters = settings.Setting(True)
    cluster_role = settings.Setting(2)
    cluster_name = settings.Setting("Cluster")
    autocommit = settings.Setting(False)

    #: Cluster variable domain role
    AttributeRole, ClassRole, MetaRole = 0, 1, 2

    def __init__(self, parent=None):
        super().__init__(parent)

        self.matrix = None
        self.items = None
        self.linkmatrix = None
        self.root = None
        self._displayed_root = None
        self.cutoff_height = 0.0
        self._invalidated = False

        gui.comboBox(gui.widgetBox(self.controlArea, "Linkage"),
                     self,
                     "linkage",
                     items=LINKAGE,
                     callback=self._invalidate_clustering)

        box = gui.widgetBox(self.controlArea, "Annotation")
        self.label_cb = gui.comboBox(box,
                                     self,
                                     "annotation_idx",
                                     callback=self._update_labels)

        self.label_cb.setModel(itemmodels.VariableListModel())
        self.label_cb.model()[:] = ["None", "Enumeration"]

        box = gui.radioButtons(self.controlArea,
                               self,
                               "pruning",
                               box="Pruning",
                               callback=self._invalidate_pruning)
        grid = QGridLayout()
        box.layout().addLayout(grid)
        grid.addWidget(gui.appendRadioButton(box, "None", addToLayout=False),
                       0, 0)
        self.max_depth_spin = gui.spin(box,
                                       self,
                                       "max_depth",
                                       minv=1,
                                       maxv=100,
                                       callback=self._invalidate_pruning,
                                       keyboardTracking=False)

        grid.addWidget(
            gui.appendRadioButton(box, "Max depth", addToLayout=False), 1, 0)
        grid.addWidget(self.max_depth_spin, 1, 1)

        box = gui.radioButtons(self.controlArea,
                               self,
                               "selection_method",
                               box="Selection",
                               callback=self._selection_method_changed)

        grid = QGridLayout()
        box.layout().addLayout(grid)
        grid.addWidget(gui.appendRadioButton(box, "Manual", addToLayout=False),
                       0, 0)
        grid.addWidget(
            gui.appendRadioButton(box, "Height ratio", addToLayout=False), 1,
            0)
        self.cut_ratio_spin = gui.spin(box,
                                       self,
                                       "cut_ratio",
                                       0,
                                       100,
                                       step=1e-1,
                                       spinType=float,
                                       callback=self._selection_method_changed)
        self.cut_ratio_spin.setSuffix("%")

        grid.addWidget(self.cut_ratio_spin, 1, 1)

        grid.addWidget(gui.appendRadioButton(box, "Top N", addToLayout=False),
                       2, 0)
        self.top_n_spin = gui.spin(box,
                                   self,
                                   "top_n",
                                   1,
                                   20,
                                   callback=self._selection_method_changed)
        grid.addWidget(self.top_n_spin, 2, 1)
        box.layout().addLayout(grid)

        self.controlArea.layout().addStretch()

        box = gui.widgetBox(self.controlArea, "Output")
        gui.checkBox(box,
                     self,
                     "append_clusters",
                     "Append cluster IDs",
                     callback=self._invalidate_output)

        ibox = gui.indentedBox(box)
        name_edit = gui.lineEdit(ibox, self, "cluster_name")
        name_edit.editingFinished.connect(self._invalidate_output)

        cb = gui.comboBox(
            ibox,
            self,
            "cluster_role",
            callback=self._invalidate_output,
            items=["Attribute", "Class variable", "Meta variable"])
        form = QFormLayout(fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow,
                           labelAlignment=Qt.AlignLeft,
                           spacing=8)
        form.addRow("Name", name_edit)
        form.addRow("Place", cb)

        ibox.layout().addSpacing(5)
        ibox.layout().addLayout(form)
        ibox.layout().addSpacing(5)

        cb = gui.checkBox(box, self, "autocommit", "Commit automatically")
        b = gui.button(box, self, "Commit", callback=self.commit, default=True)
        gui.setStopper(self, b, cb, "_invalidated", callback=self.commit)

        self.scene = QGraphicsScene()
        self.view = QGraphicsView(
            self.scene,
            horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff,
            verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn,
            alignment=Qt.AlignLeft | Qt.AlignVCenter)

        def axis_view(orientation):
            ax = pg.AxisItem(orientation=orientation, maxTickLength=7)
            scene = QGraphicsScene()
            scene.addItem(ax)
            view = QGraphicsView(
                scene,
                horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff,
                verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn,
                alignment=Qt.AlignLeft | Qt.AlignVCenter)
            view.setFixedHeight(ax.size().height())
            ax.line = SliderLine(orientation=Qt.Horizontal,
                                 length=ax.size().height())
            scene.addItem(ax.line)
            return view, ax

        self.top_axis_view, self.top_axis = axis_view("top")
        self.mainArea.layout().setSpacing(1)
        self.mainArea.layout().addWidget(self.top_axis_view)
        self.mainArea.layout().addWidget(self.view)
        self.bottom_axis_view, self.bottom_axis = axis_view("bottom")
        self.mainArea.layout().addWidget(self.bottom_axis_view)

        self._main_graphics = QGraphicsWidget()
        self._main_layout = QGraphicsLinearLayout(Qt.Horizontal)
        self._main_layout.setSpacing(1)

        self._main_graphics.setLayout(self._main_layout)
        self.scene.addItem(self._main_graphics)

        self.dendrogram = DendrogramWidget()
        self.dendrogram.setSizePolicy(QSizePolicy.MinimumExpanding,
                                      QSizePolicy.MinimumExpanding)
        self.dendrogram.selectionChanged.connect(self._invalidate_output)
        self.dendrogram.selectionEdited.connect(self._selection_edited)

        fm = self.fontMetrics()
        self.dendrogram.setContentsMargins(5,
                                           fm.lineSpacing() / 2, 5,
                                           fm.lineSpacing() / 2)
        self.labels = GraphicsSimpleTextList()
        self.labels.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.labels.setAlignment(Qt.AlignLeft)
        self.labels.setMaximumWidth(200)
        self.labels.layout().setSpacing(0)

        self._main_layout.addItem(self.dendrogram)
        self._main_layout.addItem(self.labels)

        self._main_layout.setAlignment(self.dendrogram,
                                       Qt.AlignLeft | Qt.AlignVCenter)
        self._main_layout.setAlignment(self.labels,
                                       Qt.AlignLeft | Qt.AlignVCenter)

        self.view.viewport().installEventFilter(self)
        self.top_axis_view.viewport().installEventFilter(self)
        self.bottom_axis_view.viewport().installEventFilter(self)
        self._main_graphics.installEventFilter(self)

        self.cut_line = SliderLine(self.dendrogram, orientation=Qt.Horizontal)
        self.cut_line.valueChanged.connect(self._dendrogram_slider_changed)
        self.cut_line.hide()

        self.bottom_axis.line.valueChanged.connect(self._axis_slider_changed)
        self.top_axis.line.valueChanged.connect(self._axis_slider_changed)
        self.dendrogram.geometryChanged.connect(self._dendrogram_geom_changed)
        self._set_cut_line_visible(self.selection_method == 1)

    def set_distances(self, matrix):
        self.matrix = matrix
        self._invalidate_clustering()
        self._set_items(matrix.row_items if matrix is not None else None)

    def _set_items(self, items):
        self.items = items
        if items is None:
            self.label_cb.model()[:] = ["None", "Enumeration"]
        elif isinstance(items, Orange.data.Table):
            vars = list(items.domain)
            self.label_cb.model()[:] = ["None", "Enumeration"] + vars
        elif isinstance(items, list) and \
                all(isinstance(var, Orange.data.Variable) for var in items):
            self.label_cb.model()[:] = ["None", "Enumeration", "Name"]
        else:
            self.label_cb.model()[:] = ["None", "Enumeration"]
        self.annotation_idx = min(self.annotation_idx,
                                  len(self.label_cb.model()) - 1)

    def handleNewSignals(self):
        self._update_labels()

    def _clear_plot(self):
        self.labels.set_labels([])
        self.dendrogram.set_root(None)

    def _set_displayed_root(self, root):
        self._clear_plot()
        self._displayed_root = root
        self.dendrogram.set_root(root)

        self._update_labels()

        self._main_graphics.resize(
            self._main_graphics.size().width(),
            self._main_graphics.sizeHint(Qt.PreferredSize).height())
        self._main_graphics.layout().activate()

    def _update(self):
        self._clear_plot()

        distances = self.matrix

        if distances is not None:
            # Convert to flat upper triangular distances
            i, j = numpy.triu_indices(distances.X.shape[0], k=1)
            distances = distances.X[i, j]

            method = LINKAGE[self.linkage].lower()
            Z = scipy.cluster.hierarchy.linkage(distances, method=method)
            tree = tree_from_linkage(Z)
            self.linkmatrix = Z
            self.root = tree

            self.top_axis.setRange(tree.value.height, 0.0)
            self.bottom_axis.setRange(tree.value.height, 0.0)

            if self.pruning:
                self._set_displayed_root(prune(tree, level=self.max_depth))
            else:
                self._set_displayed_root(tree)
        else:
            self.linkmatrix = None
            self.root = None
            self._set_displayed_root(None)

        self._apply_selection()

    def _update_labels(self):
        labels = []
        if self.root and self._displayed_root:
            indices = [leaf.value.index for leaf in leaves(self.root)]

            if self.annotation_idx == 0:
                labels = []
            elif self.annotation_idx == 1:
                labels = [str(i) for i in indices]
            elif isinstance(self.items, Orange.data.Table):
                var = self.label_cb.model()[self.annotation_idx]
                col = self.items[:, var]
                labels = [var.repr_val(next(iter(row))) for row in col]
                labels = [labels[idx] for idx in indices]
            else:
                labels = []

            if labels and self._displayed_root is not self.root:
                joined = leaves(self._displayed_root)
                labels = [
                    ", ".join(labels[leaf.value.first:leaf.value.last])
                    for leaf in joined
                ]

        self.labels.set_labels(labels)
        self.labels.setMinimumWidth(1 if labels else -1)

    def _invalidate_clustering(self):
        self._update()
        self._update_labels()

    def _invalidate_output(self):
        self._invalidated = True
        if self.autocommit:
            self.commit()

    def _invalidate_pruning(self):
        if self.root:
            selection = self.dendrogram.selected_nodes()
            ranges = [node.value.range for node in selection]
            if self.pruning:
                self._set_displayed_root(prune(self.root,
                                               level=self.max_depth))
            else:
                self._set_displayed_root(self.root)
            selected = [
                node for node in preorder(self._displayed_root)
                if node.value.range in ranges
            ]

            self.dendrogram.set_selected_clusters(selected)

        self._apply_selection()

    def commit(self):
        self._invalidated = False

        items = getattr(self.matrix, "items", self.items)
        if not items:
            # nothing to commit
            return

        selection = self.dendrogram.selected_nodes()
        selection = sorted(selection, key=lambda c: c.value.first)

        indices = [leaf.value.index for leaf in leaves(self.root)]

        maps = [
            indices[node.value.first:node.value.last] for node in selection
        ]

        selected_indices = list(chain(*maps))
        unselected_indices = sorted(
            set(range(self.root.value.last)) - set(selected_indices))

        selected = [items[k] for k in selected_indices]
        unselected = [items[k] for k in unselected_indices]

        if not selected:
            self.send("Selected Data", None)
            self.send("Other Data", None)
            return
        selected_data = unselected_data = None

        if isinstance(items, Orange.data.Table):
            c = numpy.zeros(len(items))

            for i, indices in enumerate(maps):
                c[indices] = i
            c[unselected_indices] = len(maps)

            mask = c != len(maps)

            if self.append_clusters:
                clust_var = Orange.data.DiscreteVariable(
                    str(self.cluster_name),
                    values=[
                        "Cluster {}".format(i + 1) for i in range(len(maps))
                    ] + ["Other"])
                data, domain = items, items.domain

                attrs = domain.attributes
                class_ = domain.class_vars
                metas = domain.metas

                X, Y, M = data.X, data.Y, data.metas
                if self.cluster_role == self.AttributeRole:
                    attrs = attrs + (clust_var, )
                    X = numpy.c_[X, c]
                elif self.cluster_role == self.ClassRole:
                    class_ = class_ + (clust_var, )
                    Y = numpy.c_[Y, c]
                elif self.cluster_role == self.MetaRole:
                    metas = metas + (clust_var, )
                    M = numpy.c_[M, c]

                domain = Orange.data.Domain(attrs, class_, metas)
                data = Orange.data.Table(domain, X, Y, M)
            else:
                data = items

            if selected:
                selected_data = data[mask]
            if unselected:
                unselected_data = data[~mask]

        self.send("Selected Data", selected_data)
        self.send("Other Data", unselected_data)

    def sizeHint(self):
        return QSize(800, 500)

    def eventFilter(self, obj, event):
        if obj is self.view.viewport() and event.type() == QEvent.Resize:
            width = self.view.viewport().width() - 2
            self._main_graphics.setMaximumWidth(width)
            self._main_graphics.setMinimumWidth(width)
            self._main_graphics.layout().activate()
        elif event.type() == QEvent.MouseButtonPress and \
                (obj is self.top_axis_view.viewport() or
                 obj is self.bottom_axis_view.viewport()):
            self.selection_method = 1
            # Map click point to cut line local coordinates
            pos = self.top_axis_view.mapToScene(event.pos())
            cut = self.top_axis.line.mapFromScene(pos)
            self.top_axis.line.setValue(cut.x())
            # update the line visibility, output, ...
            self._selection_method_changed()

        return super().eventFilter(obj, event)

    def _dendrogram_geom_changed(self):
        pos = self.dendrogram.pos_at_height(self.cutoff_height)
        geom = self.dendrogram.geometry()
        crect = self.dendrogram.contentsRect()

        self._set_slider_value(pos.x(), geom.width())
        self.cut_line.setLength(geom.height())

        self.top_axis.resize(crect.width(), self.top_axis.height())
        self.top_axis.setPos(geom.left() + crect.left(), 0)
        self.top_axis.line.setPos(self.cut_line.scenePos().x(), 0)

        self.bottom_axis.resize(crect.width(), self.bottom_axis.height())
        self.bottom_axis.setPos(geom.left() + crect.left(), 0)
        self.bottom_axis.line.setPos(self.cut_line.scenePos().x(), 0)

        geom = self._main_graphics.geometry()
        assert geom.topLeft() == QPointF(0, 0)
        self.scene.setSceneRect(geom)

        geom.setHeight(self.top_axis.size().height())

        self.top_axis.scene().setSceneRect(geom)
        self.bottom_axis.scene().setSceneRect(geom)

    def _axis_slider_changed(self, value):
        self.cut_line.setValue(value)

    def _dendrogram_slider_changed(self, value):
        p = QPointF(value, 0)
        cl_height = self.dendrogram.height_at(p)

        self.set_cutoff_height(cl_height)

        # Sync the cut positions between the dendrogram and the axis.
        self._set_slider_value(value, self.dendrogram.size().width())

    def _set_slider_value(self, value, span):
        with blocked(self.cut_line):
            self.cut_line.setValue(value)
            self.cut_line.setRange(0, span)

        with blocked(self.top_axis.line):
            self.top_axis.line.setValue(value)
            self.top_axis.line.setRange(0, span)

        with blocked(self.bottom_axis.line):
            self.bottom_axis.line.setValue(value)
            self.bottom_axis.line.setRange(0, span)

    def set_cutoff_height(self, height):
        self.cutoff_height = height
        if self.root:
            self.cut_ratio = 100 * height / self.root.value.height
        self.select_max_height(height)

    def _set_cut_line_visible(self, visible):
        self.cut_line.setVisible(visible)
        self.top_axis.line.setVisible(visible)
        self.bottom_axis.line.setVisible(visible)

    def select_top_n(self, n):
        root = self._displayed_root
        if root:
            clusters = top_clusters(root, n)
            self.dendrogram.set_selected_clusters(clusters)

    def select_max_height(self, height):
        root = self._displayed_root
        if root:
            clusters = clusters_at_height(root, height)
            self.dendrogram.set_selected_clusters(clusters)

    def _selection_method_changed(self):
        self._set_cut_line_visible(self.selection_method == 1)
        if self.root:
            self._apply_selection()

    def _apply_selection(self):
        if not self.root:
            return

        if self.selection_method == 0:
            pass
        elif self.selection_method == 1:
            height = self.cut_ratio * self.root.value.height / 100
            self.set_cutoff_height(height)
            pos = self.dendrogram.pos_at_height(height)
            self._set_slider_value(pos.x(), self.dendrogram.size().width())
        elif self.selection_method == 2:
            self.select_top_n(self.top_n)

    def _selection_edited(self):
        # Selection was edited by clicking on a cluster in the
        # dendrogram view.
        self.selection_method = 0
        self._selection_method_changed()
Ejemplo n.º 48
0
        self._resizeState = True
        self._location = self.pos()
        event.accept()

    def mouseReleaseEvent(self, event):
        self._resizeState = False
        event.accept()

    def mouseMoveEvent(self, event):
        if self._resizeState:
            change = event.pos() - event.lastPos()
            if self._parent.resizeRect(self._position,
                                       self._location + change):
                self._location += change
                self.prepareGeometryChange()
                self.setPos(self._location)
        event.accept()


if __name__ == '__main__':
    from PyQt4.QtGui import QApplication, QGraphicsView, QGraphicsScene
    import sys
    app = QApplication(sys.argv)
    myview = QGraphicsView()
    myscene = QGraphicsScene(QRectF(-400, -300, 800, 600))
    myscene.addItem(ResizeHandle())
    myview.setScene(myscene)
    myview.show()

    app.exec_()
Ejemplo n.º 49
0
class OWSieveDiagram(OWWidget):
    """
    A two-way contingency table providing information on the relation
    between the observed and expected frequencies of a combination of values
    """
    name = "Sieve Diagram"
    icon = "icons/SieveDiagram.svg"
    priority = 310

    inputs = [("Data", Table, "set_data", Default),
              ("Features", AttributeList, "set_input_features")]
    outputs = [("Selection", Table)]

    graph_name = "canvas"

    want_control_area = False

    settingsHandler = DomainContextHandler()
    attrX = ContextSetting("")
    attrY = ContextSetting("")
    selection = ContextSetting(set())

    def __init__(self):
        # pylint: disable=missing-docstring
        super().__init__()

        self.data = self.discrete_data = None
        self.attrs = []
        self.input_features = None
        self.areas = []
        self.selection = set()

        self.attr_box = gui.hBox(self.mainArea)
        model = VariableListModel()
        model.wrap(self.attrs)
        combo_args = dict(
            widget=self.attr_box, master=self, contentsLength=12,
            callback=self.update_attr, sendSelectedValue=True, valueType=str,
            model=model)
        fixed_size = (QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.attrXCombo = gui.comboBox(value="attrX", **combo_args)
        gui.widgetLabel(self.attr_box, "\u2715", sizePolicy=fixed_size)
        self.attrYCombo = gui.comboBox(value="attrY", **combo_args)
        self.vizrank = SieveRank(self)
        self.vizrank_button = gui.button(
            self.attr_box, self, "Score Combinations", sizePolicy=fixed_size,
            callback=self.vizrank.reshow, enabled=False)
        self.vizrank.pairSelected.connect(self.set_attr)

        self.canvas = QGraphicsScene()
        self.canvasView = ViewWithPress(
            self.canvas, self.mainArea, handler=self.reset_selection)
        self.mainArea.layout().addWidget(self.canvasView)
        self.canvasView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvasView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        box = gui.hBox(self.mainArea)
        box.layout().addWidget(self.graphButton)
        box.layout().addWidget(self.report_button)

    def sizeHint(self):
        return QSize(450, 550)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.update_graph()

    def showEvent(self, event):
        super().showEvent(event)
        self.update_graph()

    def closeEvent(self, event):
        self.vizrank.close()
        super().closeEvent(event)

    def hideEvent(self, event):
        self.vizrank.hide()
        super().hideEvent(event)

    def set_data(self, data):
        """
        Discretize continuous attributes, and put all attributes and discrete
        metas into self.attrs, which is used as a model for combos.

        Select the first two attributes unless context overrides this.
        Method `resolve_shown_attributes` is called to use the attributes from
        the input, if it exists and matches the attributes in the data.

        Remove selection; again let the context override this.
        Initialize the vizrank dialog, but don't show it.

        Args:
            data (Table): input data
        """
        if isinstance(data, SqlTable) and data.approx_len() > LARGE_TABLE:
            data = data.sample_time(DEFAULT_SAMPLE_TIME)

        self.closeContext()
        self.data = data
        self.areas = []
        self.selection = set()
        if self.data is None:
            self.attrs[:] = []
        else:
            if any(attr.is_continuous for attr in data.domain):
                discretizer = Discretize(
                    method=EqualFreq(n=4),
                    discretize_classes=True, discretize_metas=True)
                self.discrete_data = discretizer(data)
            else:
                self.discrete_data = self.data
            self.attrs[:] = [
                var for var in chain(
                    self.discrete_data.domain,
                    (var for var in self.data.domain.metas if var.is_discrete))
            ]
        if self.attrs:
            self.attrX = self.attrs[0].name
            self.attrY = self.attrs[len(self.attrs) > 1].name
        else:
            self.attrX = self.attrY = None
            self.areas = []
            self.selection = set()
        self.openContext(self.data)
        self.resolve_shown_attributes()
        self.update_graph()
        self.update_selection()

        self.vizrank.initialize()
        self.vizrank_button.setEnabled(
            self.data is not None and len(self.data) > 1 and
            len(self.data.domain.attributes) > 1)

    def set_attr(self, attr_x, attr_y):
        self.attrX, self.attrY = attr_x.name, attr_y.name
        self.update_attr()

    def update_attr(self):
        """Update the graph and selection."""
        self.selection = set()
        self.update_graph()
        self.update_selection()

    def set_input_features(self, attr_list):
        """
        Handler for the Features signal.

        The method stores the attributes and calls `resolve_shown_attributes`

        Args:
            attr_list (AttributeList): data from the signal
        """
        self.input_features = attr_list
        self.resolve_shown_attributes()
        self.update_selection()

    def resolve_shown_attributes(self):
        """
        Use the attributes from the input signal if the signal is present
        and at least two attributes appear in the domain. If there are
        multiple, use the first two. Combos are disabled if inputs are used.
        """
        self.warning()
        self.attr_box.setEnabled(True)
        if not self.input_features:  # None or empty
            return
        features = [f for f in self.input_features if f in self.attrs]
        if not features:
            self.warning(
                "Features from the input signal are not present in the data")
            return
        old_attrs = self.attrX, self.attrY
        self.attrX, self.attrY = [f.name for f in (features * 2)[:2]]
        self.attr_box.setEnabled(False)
        if (self.attrX, self.attrY) != old_attrs:
            self.selection = set()
            self.update_graph()

    def reset_selection(self):
        self.selection = set()
        self.update_selection()

    def select_area(self, area, event):
        """
        Add or remove the clicked area from the selection

        Args:
            area (QRect): the area that is clicked
            event (QEvent): event description
        """
        if event.button() != Qt.LeftButton:
            return
        index = self.areas.index(area)
        if event.modifiers() & Qt.ControlModifier:
            self.selection ^= {index}
        else:
            self.selection = {index}
        self.update_selection()

    def update_selection(self):
        """
        Update the graph (pen width) to show the current selection.
        Filter and output the data.
        """
        if self.areas is None or not self.selection:
            self.send("Selection", None)
            return

        filts = []
        for i, area in enumerate(self.areas):
            if i in self.selection:
                width = 4
                val_x, val_y = area.value_pair
                filts.append(
                    filter.Values([
                        filter.FilterDiscrete(self.attrX, [val_x]),
                        filter.FilterDiscrete(self.attrY, [val_y])
                    ]))
            else:
                width = 1
            pen = area.pen()
            pen.setWidth(width)
            area.setPen(pen)
        if len(filts) == 1:
            filts = filts[0]
        else:
            filts = filter.Values(filts, conjunction=False)
        selection = filts(self.discrete_data)
        if self.discrete_data is not self.data:
            idset = set(selection.ids)
            sel_idx = [i for i, id in enumerate(self.data.ids) if id in idset]
            selection = self.data[sel_idx]
        self.send("Selection", selection)

    def update_graph(self):
        # Function uses weird names like r, g, b, but it does it with utmost
        # caution, hence
        # pylint: disable=invalid-name
        """Update the graph."""

        def text(txt, *args, **kwargs):
            return CanvasText(self.canvas, "", html_text=to_html(txt),
                              *args, **kwargs)

        def width(txt):
            return text(txt, 0, 0, show=False).boundingRect().width()

        def fmt(val):
            return str(int(val)) if val % 1 == 0 else "{:.2f}".format(val)

        def show_pearson(rect, pearson, pen_width):
            """
            Color the given rectangle according to its corresponding
            standardized Pearson residual.

            Args:
                rect (QRect): the rectangle being drawn
                pearson (float): signed standardized pearson residual
                pen_width (int): pen width (bolder pen is used for selection)
            """
            r = rect.rect()
            x, y, w, h = r.x(), r.y(), r.width(), r.height()
            if w == 0 or h == 0:
                return

            r = b = 255
            if pearson > 0:
                r = g = max(255 - 20 * pearson, 55)
            elif pearson < 0:
                b = g = max(255 + 20 * pearson, 55)
            else:
                r = g = b = 224
            rect.setBrush(QBrush(QColor(r, g, b)))
            pen_color = QColor(255 * (r == 255), 255 * (g == 255),
                               255 * (b == 255))
            pen = QPen(pen_color, pen_width)
            rect.setPen(pen)
            if pearson > 0:
                pearson = min(pearson, 10)
                dist = 20 - 1.6 * pearson
            else:
                pearson = max(pearson, -10)
                dist = 20 - 8 * pearson
            pen.setWidth(1)

            def _offseted_line(ax, ay):
                r = QGraphicsLineItem(x + ax, y + ay, x + (ax or w),
                                      y + (ay or h))
                self.canvas.addItem(r)
                r.setPen(pen)

            ax = dist
            while ax < w:
                _offseted_line(ax, 0)
                ax += dist

            ay = dist
            while ay < h:
                _offseted_line(0, ay)
                ay += dist

        def make_tooltip():
            """Create the tooltip. The function uses local variables from
            the enclosing scope."""
            # pylint: disable=undefined-loop-variable
            def _oper(attr_name, txt):
                if self.data.domain[attr_name] is ddomain[attr_name]:
                    return "="
                return " " if txt[0] in "<≥" else " in "

            return (
                "<b>{attrX}{xeq}{xval_name}</b>: {obs_x}/{n} ({p_x:.0f} %)".
                format(attrX=to_html(attr_x),
                       xeq=_oper(attr_x, xval_name),
                       xval_name=to_html(xval_name),
                       obs_x=fmt(chi.probs_x[x] * n),
                       n=int(n),
                       p_x=100 * chi.probs_x[x]) +
                "<br/>" +
                "<b>{attrY}{yeq}{yval_name}</b>: {obs_y}/{n} ({p_y:.0f} %)".
                format(attrY=to_html(attr_y),
                       yeq=_oper(attr_y, yval_name),
                       yval_name=to_html(yval_name),
                       obs_y=fmt(chi.probs_y[y] * n),
                       n=int(n),
                       p_y=100 * chi.probs_y[y]) +
                "<hr/>" +
                """<b>combination of values: </b><br/>
                   &nbsp;&nbsp;&nbsp;expected {exp} ({p_exp:.0f} %)<br/>
                   &nbsp;&nbsp;&nbsp;observed {obs} ({p_obs:.0f} %)""".
                format(exp=fmt(chi.expected[y, x]),
                       p_exp=100 * chi.expected[y, x] / n,
                       obs=fmt(chi.observed[y, x]),
                       p_obs=100 * chi.observed[y, x] / n))

        for item in self.canvas.items():
            self.canvas.removeItem(item)
        if self.data is None or len(self.data) == 0 or \
                self.attrX is None or self.attrY is None:
            return

        ddomain = self.discrete_data.domain
        attr_x, attr_y = self.attrX, self.attrY
        disc_x, disc_y = ddomain[attr_x], ddomain[attr_y]
        view = self.canvasView

        chi = ChiSqStats(self.discrete_data, attr_x, attr_y)
        n = chi.n
        max_ylabel_w = max((width(val) for val in disc_y.values), default=0)
        max_ylabel_w = min(max_ylabel_w, 200)
        x_off = width(attr_x) + max_ylabel_w
        y_off = 15
        square_size = min(view.width() - x_off - 35, view.height() - y_off - 50)
        square_size = max(square_size, 10)
        self.canvasView.setSceneRect(0, 0, view.width(), view.height())

        curr_x = x_off
        max_xlabel_h = 0
        self.areas = []
        for x, (px, xval_name) in enumerate(zip(chi.probs_x, disc_x.values)):
            if px == 0:
                continue
            width = square_size * px

            curr_y = y_off
            for y in range(len(chi.probs_y) - 1, -1, -1):  # bottom-up order
                py = chi.probs_y[y]
                yval_name = disc_y.values[y]
                if py == 0:
                    continue
                height = square_size * py

                selected = len(self.areas) in self.selection
                rect = CanvasRectangle(
                    self.canvas, curr_x + 2, curr_y + 2, width - 4, height - 4,
                    z=-10, onclick=self.select_area)
                rect.value_pair = x, y
                self.areas.append(rect)
                show_pearson(rect, chi.residuals[y, x], 3 * selected)
                rect.setToolTip(make_tooltip())

                if x == 0:
                    text(yval_name, x_off, curr_y + height / 2,
                         Qt.AlignRight | Qt.AlignVCenter)
                curr_y += height

            xl = text(xval_name, curr_x + width / 2, y_off + square_size,
                      Qt.AlignHCenter | Qt.AlignTop)
            max_xlabel_h = max(int(xl.boundingRect().height()), max_xlabel_h)
            curr_x += width

        bottom = y_off + square_size + max_xlabel_h
        text(attr_y, 0, y_off + square_size / 2,
             Qt.AlignLeft | Qt.AlignVCenter, bold=True, vertical=True)
        text(attr_x, x_off + square_size / 2, bottom,
             Qt.AlignHCenter | Qt.AlignTop, bold=True)
        xl = text("χ²={:.2f}, p={:.3f}".format(chi.chisq, chi.p),
                  0, bottom)
        # Assume similar height for both lines
        text("N = " + fmt(chi.n), 0, bottom - xl.boundingRect().height())

    def get_widget_name_extension(self):
        if self.data is not None:
            return "{} vs {}".format(self.attrX, self.attrY)

    def send_report(self):
        self.report_plot()
Ejemplo n.º 50
0
class OWMosaicDisplay(OWWidget):
    name = "Mosaic Display"
    description = "Display data in a mosaic plot."
    icon = "icons/MosaicDisplay.svg"

    inputs = [("Data", Table, "set_data", Default),
              ("Data Subset", Table, "set_subset_data")]
    outputs = [("Selected Data", Table)]

    settingsHandler = DomainContextHandler()
    use_boxes = Setting(True)
    variable1 = ContextSetting("")
    variable2 = ContextSetting("")
    variable3 = ContextSetting("")
    variable4 = ContextSetting("")
    selection = ContextSetting({})
    # interior_coloring is context setting to properly reset it
    # if the widget switches to regression and back (set setData)
    interior_coloring = ContextSetting(1)

    PEARSON, CLASS_DISTRIBUTION = 0, 1
    interior_coloring_opts = ["Pearson residuals", "Class distribution"]
    BAR_WIDTH = 5
    SPACING = 4
    ATTR_NAME_OFFSET = 20
    ATTR_VAL_OFFSET = 3
    BLUE_COLORS = [
        QColor(255, 255, 255),
        QColor(210, 210, 255),
        QColor(110, 110, 255),
        QColor(0, 0, 255)
    ]
    RED_COLORS = [
        QColor(255, 255, 255),
        QColor(255, 200, 200),
        QColor(255, 100, 100),
        QColor(255, 0, 0)
    ]

    graph_name = "canvas"

    def __init__(self):
        super().__init__()

        self.data = None
        self.discrete_data = None
        self.unprocessed_subset_data = None
        self.subset_data = None

        self.areas = []

        self.canvas = QGraphicsScene()
        self.canvas_view = ViewWithPress(self.canvas,
                                         handler=self.clear_selection)
        self.mainArea.layout().addWidget(self.canvas_view)
        self.canvas_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvas_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvas_view.setRenderHint(QPainter.Antialiasing)

        box = gui.vBox(self.controlArea, box=True)
        self.attr_combos = [
            gui.comboBox(box,
                         self,
                         value="variable{}".format(i),
                         orientation=Qt.Horizontal,
                         contentsLength=12,
                         callback=self.reset_graph,
                         sendSelectedValue=True,
                         valueType=str) for i in range(1, 5)
        ]
        self.rb_colors = gui.radioButtonsInBox(self.controlArea,
                                               self,
                                               "interior_coloring",
                                               self.interior_coloring_opts,
                                               box="Interior Coloring",
                                               callback=self.update_graph)
        self.bar_button = gui.checkBox(gui.indentedBox(self.rb_colors),
                                       self,
                                       'use_boxes',
                                       label='Compare with total',
                                       callback=self._compare_with_total)
        gui.rubber(self.controlArea)

    def sizeHint(self):
        return QSize(530, 720)

    def _compare_with_total(self):
        if self.data and self.data.domain.has_discrete_class:
            self.interior_coloring = 1
            self.update_graph()

    def init_combos(self, data):
        for combo in self.attr_combos:
            combo.clear()
        if data is None:
            return
        for combo in self.attr_combos[1:]:
            combo.addItem("(None)")

        icons = gui.attributeIconDict
        for attr in chain(data.domain, data.domain.metas):
            if attr.is_discrete or attr.is_continuous:
                for combo in self.attr_combos:
                    combo.addItem(icons[attr], attr.name)

        if self.attr_combos[0].count() > 0:
            self.variable1 = self.attr_combos[0].itemText(0)
            self.variable2 = self.attr_combos[1].itemText(
                2 * (self.attr_combos[1].count() > 2))
        self.variable3 = self.attr_combos[2].itemText(0)
        self.variable4 = self.attr_combos[3].itemText(0)

    def get_attr_list(self):
        return [
            a for a in
            [self.variable1, self.variable2, self.variable3, self.variable4]
            if a and a != "(None)"
        ]

    def resizeEvent(self, e):
        OWWidget.resizeEvent(self, e)
        self.update_graph()

    def showEvent(self, ev):
        OWWidget.showEvent(self, ev)
        self.update_graph()

    def set_data(self, data):
        if type(data) == SqlTable and data.approx_len() > LARGE_TABLE:
            data = data.sample_time(DEFAULT_SAMPLE_TIME)

        self.closeContext()
        self.data = data
        self.init_combos(self.data)
        self.information([0, 1, 2])
        if not self.data:
            self.discrete_data = None
            return
        """ TODO: check
        if data.has_missing_class():
            self.information(1, "Examples with missing classes were removed.")
        """
        if any(attr.is_continuous for attr in data.domain):
            self.discrete_data = Discretize(method=EqualFreq(n=4))(data)
        else:
            self.discrete_data = self.data

        if self.data.domain.class_var is None:
            self.rb_colors.setDisabled(True)
            disc_class = False
        else:
            self.rb_colors.setDisabled(False)
            disc_class = self.data.domain.has_discrete_class
            self.rb_colors.group.button(2).setDisabled(not disc_class)
            self.bar_button.setDisabled(not disc_class)
        self.interior_coloring = bool(disc_class)
        self.openContext(self.data)

        # if we first received subset we now call setSubsetData to process it
        if self.unprocessed_subset_data:
            self.set_subset_data(self.unprocessed_subset_data)
            self.unprocessed_subset_data = None

    def set_subset_data(self, data):
        if self.data is None:
            self.unprocessed_subset_data = data
            self.warning(10)
            return
        try:
            self.subset_data = data.from_table(self.data.domain, data)
            self.warning(10)
        except:
            self.subset_data = None
            self.warning(
                10, "'Data' and 'Data Subset' are incompatible"
                if data is not None else "")

    # this is called by widget after setData and setSubsetData are called.
    # this way the graph is updated only once
    def handleNewSignals(self):
        self.reset_graph()

    def clear_selection(self):
        self.selection = {}
        self.update_selection_rects()
        self.send_selection()

    def reset_graph(self):
        self.clear_selection()
        self.update_graph()

    def update_selection_rects(self):
        for i, (attr, vals, area) in enumerate(self.areas):
            if i in self.selection:
                area.setPen(QPen(Qt.black, 3, Qt.DotLine))
            else:
                area.setPen(QPen())

    def select_area(self, index, ev):
        if ev.button() != Qt.LeftButton:
            return
        if ev.modifiers() & Qt.ControlModifier:
            self.selection ^= {index}
        else:
            self.selection = {index}
        self.update_selection_rects()
        self.send_selection()

    def send_selection(self):
        if not self.selection or self.data is None:
            self.send("Selected Data", None)
            return
        filters = []
        self.warning(6)
        if self.discrete_data is not self.data:
            if isinstance(self.data, SqlTable):
                self.warning(
                    6,
                    "Selection of continuous variables on SQL is not supported"
                )
        for i in self.selection:
            cols, vals, area = self.areas[i]
            filters.append(
                filter.Values(
                    filter.FilterDiscrete(col, [val])
                    for col, val in zip(cols, vals)))
        if len(filters) > 1:
            filters = filter.Values(filters, conjunction=False)
        else:
            filters = filters[0]
        selection = filters(self.discrete_data)
        if self.discrete_data is not self.data:
            idset = set(selection.ids)
            sel_idx = [i for i, id in enumerate(self.data.ids) if id in idset]
            selection = self.discrete_data[sel_idx]
        self.send("Selected Data", selection)

    def send_report(self):
        self.report_plot(self.canvas)

    def update_graph(self):
        spacing = self.SPACING
        bar_width = self.BAR_WIDTH

        def draw_data(attr_list,
                      x0_x1,
                      y0_y1,
                      side,
                      condition,
                      total_attrs,
                      used_attrs=[],
                      used_vals=[],
                      attr_vals=""):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if conditionaldict[attr_vals] == 0:
                add_rect(x0,
                         x1,
                         y0,
                         y1,
                         "",
                         used_attrs,
                         used_vals,
                         attr_vals=attr_vals)
                # store coordinates for later drawing of labels
                draw_text(side, attr_list[0], (x0, x1), (y0, y1), total_attrs,
                          used_attrs, used_vals, attr_vals)
                return

            attr = attr_list[0]
            # how much smaller rectangles do we draw
            edge = len(attr_list) * spacing
            values = get_variable_values_sorted(data.domain[attr])
            if side % 2:
                values = values[::-1]  # reverse names if necessary

            if side % 2 == 0:  # we are drawing on the x axis
                # remove the space needed for separating different attr. values
                whole = max(0, (x1 - x0) - edge * (len(values) - 1))
                if whole == 0:
                    edge = (x1 - x0) / float(len(values) - 1)
            else:  # we are drawing on the y axis
                whole = max(0, (y1 - y0) - edge * (len(values) - 1))
                if whole == 0:
                    edge = (y1 - y0) / float(len(values) - 1)

            if attr_vals == "":
                counts = [conditionaldict[val] for val in values]
            else:
                counts = [
                    conditionaldict[attr_vals + "-" + val] for val in values
                ]
            total = sum(counts)

            # if we are visualizing the third attribute and the first attribute
            # has the last value, we have to reverse the order in which the
            # boxes will be drawn otherwise, if the last cell, nearest to the
            # labels of the fourth attribute, is empty, we wouldn't be able to
            # position the labels
            valrange = list(range(len(values)))
            if len(attr_list + used_attrs) == 4 and len(used_attrs) == 2:
                attr1values = get_variable_values_sorted(
                    data.domain[used_attrs[0]])
                if used_vals[0] == attr1values[-1]:
                    valrange = valrange[::-1]

            for i in valrange:
                start = i * edge + whole * float(sum(counts[:i]) / total)
                end = i * edge + whole * float(sum(counts[:i + 1]) / total)
                val = values[i]
                htmlval = getHtmlCompatibleString(val)
                if attr_vals != "":
                    newattrvals = attr_vals + "-" + val
                else:
                    newattrvals = val

                tooltip = condition + 4 * "&nbsp;" + attr + \
                    ": <b>" + htmlval + "</b><br>"
                attrs = used_attrs + [attr]
                vals = used_vals + [val]
                common_args = attrs, vals, newattrvals
                if side % 2 == 0:  # if we are moving horizontally
                    if len(attr_list) == 1:
                        add_rect(x0 + start, x0 + end, y0, y1, tooltip,
                                 *common_args)
                    else:
                        draw_data(attr_list[1:], (x0 + start, x0 + end),
                                  (y0, y1), side + 1, tooltip, total_attrs,
                                  *common_args)
                else:
                    if len(attr_list) == 1:
                        add_rect(x0, x1, y0 + start, y0 + end, tooltip,
                                 *common_args)
                    else:
                        draw_data(attr_list[1:], (x0, x1),
                                  (y0 + start, y0 + end), side + 1, tooltip,
                                  total_attrs, *common_args)

            draw_text(side, attr_list[0], (x0, x1), (y0, y1), total_attrs,
                      used_attrs, used_vals, attr_vals)

        def draw_text(side, attr, x0_x1, y0_y1, total_attrs, used_attrs,
                      used_vals, attr_vals):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if side in drawn_sides:
                return

            # the text on the right will be drawn when we are processing
            # visualization of the last value of the first attribute
            if side == 3:
                attr1values = \
                    get_variable_values_sorted(data.domain[used_attrs[0]])
                if used_vals[0] != attr1values[-1]:
                    return

            if not conditionaldict[attr_vals]:
                if side not in draw_positions:
                    draw_positions[side] = (x0, x1, y0, y1)
                return
            else:
                if side in draw_positions:
                    # restore the positions of attribute values and name
                    (x0, x1, y0, y1) = draw_positions[side]

            drawn_sides.add(side)

            values = get_variable_values_sorted(data.domain[attr])
            if side % 2:
                values = values[::-1]

            spaces = spacing * (total_attrs - side) * (len(values) - 1)
            width = x1 - x0 - spaces * (side % 2 == 0)
            height = y1 - y0 - spaces * (side % 2 == 1)

            # calculate position of first attribute
            currpos = 0

            if attr_vals == "":
                counts = [conditionaldict.get(val, 1) for val in values]
            else:
                counts = [
                    conditionaldict.get(attr_vals + "-" + val, 1)
                    for val in values
                ]
            total = sum(counts)
            if total == 0:
                counts = [1] * len(values)
                total = sum(counts)

            aligns = [
                Qt.AlignTop | Qt.AlignHCenter, Qt.AlignRight | Qt.AlignVCenter,
                Qt.AlignBottom | Qt.AlignHCenter,
                Qt.AlignLeft | Qt.AlignVCenter
            ]
            align = aligns[side]
            for i in range(len(values)):
                val = values[i]
                perc = counts[i] / float(total)
                if distributiondict[val] != 0:
                    if side == 0:
                        CanvasText(self.canvas, str(val),
                                   x0 + currpos + width * 0.5 * perc,
                                   y1 + self.ATTR_VAL_OFFSET, align)
                    elif side == 1:
                        CanvasText(self.canvas, str(val),
                                   x0 - self.ATTR_VAL_OFFSET,
                                   y0 + currpos + height * 0.5 * perc, align)
                    elif side == 2:
                        CanvasText(self.canvas, str(val),
                                   x0 + currpos + width * perc * 0.5,
                                   y0 - self.ATTR_VAL_OFFSET, align)
                    else:
                        CanvasText(self.canvas, str(val),
                                   x1 + self.ATTR_VAL_OFFSET,
                                   y0 + currpos + height * 0.5 * perc, align)

                if side % 2 == 0:
                    currpos += perc * width + spacing * (total_attrs - side)
                else:
                    currpos += perc * height + spacing * (total_attrs - side)

            if side == 0:
                CanvasText(self.canvas,
                           attr,
                           x0 + (x1 - x0) / 2,
                           y1 + self.ATTR_VAL_OFFSET + self.ATTR_NAME_OFFSET,
                           align,
                           bold=1)
            elif side == 1:
                CanvasText(self.canvas,
                           attr,
                           x0 - max_ylabel_w1 - self.ATTR_VAL_OFFSET,
                           y0 + (y1 - y0) / 2,
                           align,
                           bold=1,
                           vertical=True)
            elif side == 2:
                CanvasText(self.canvas,
                           attr,
                           x0 + (x1 - x0) / 2,
                           y0 - self.ATTR_VAL_OFFSET - self.ATTR_NAME_OFFSET,
                           align,
                           bold=1)
            else:
                CanvasText(self.canvas,
                           attr,
                           x1 + max_ylabel_w2 + self.ATTR_VAL_OFFSET,
                           y0 + (y1 - y0) / 2,
                           align,
                           bold=1,
                           vertical=True)

        def add_rect(x0,
                     x1,
                     y0,
                     y1,
                     condition="",
                     used_attrs=[],
                     used_vals=[],
                     attr_vals=""):
            area_index = len(self.areas)
            if x0 == x1:
                x1 += 1
            if y0 == y1:
                y1 += 1

            # rectangles of width and height 1 are not shown - increase
            if x1 - x0 + y1 - y0 == 2:
                y1 += 1

            if class_var and class_var.is_discrete:
                colors = [QColor(*col) for col in class_var.colors]
            else:
                colors = None

            def select_area(_, ev):
                self.select_area(area_index, ev)

            def rect(x, y, w, h, z, pen_color=None, brush_color=None, **args):
                if pen_color is None:
                    return CanvasRectangle(self.canvas,
                                           x,
                                           y,
                                           w,
                                           h,
                                           z=z,
                                           onclick=select_area,
                                           **args)
                if brush_color is None:
                    brush_color = pen_color
                return CanvasRectangle(self.canvas,
                                       x,
                                       y,
                                       w,
                                       h,
                                       pen_color,
                                       brush_color,
                                       z=z,
                                       onclick=select_area,
                                       **args)

            def line(x1, y1, x2, y2):
                r = QGraphicsLineItem(x1, y1, x2, y2, None)
                self.canvas.addItem(r)
                r.setPen(QPen(Qt.white, 2))
                r.setZValue(30)

            outer_rect = rect(x0, y0, x1 - x0, y1 - y0, 30)
            self.areas.append((used_attrs, used_vals, outer_rect))
            if not conditionaldict[attr_vals]:
                return

            if self.interior_coloring == self.PEARSON:
                s = sum(apriori_dists[0])
                expected = s * reduce(
                    mul, (apriori_dists[i][used_vals[i]] / float(s)
                          for i in range(len(used_vals))))
                actual = conditionaldict[attr_vals]
                pearson = (actual - expected) / sqrt(expected)
                if pearson == 0:
                    ind = 0
                else:
                    ind = max(0, min(int(log(abs(pearson), 2)), 3))
                color = [self.RED_COLORS, self.BLUE_COLORS][pearson > 0][ind]
                rect(x0, y0, x1 - x0, y1 - y0, -20, color)
                outer_rect.setToolTip(
                    condition + "<hr/>" + "Expected instances: %.1f<br>"
                    "Actual instances: %d<br>"
                    "Standardized (Pearson) residual: %.1f" %
                    (expected, conditionaldict[attr_vals], pearson))
            else:
                cls_values = get_variable_values_sorted(class_var)
                prior = get_distribution(data, class_var.name)
                total = 0
                for i, value in enumerate(cls_values):
                    val = conditionaldict[attr_vals + "-" + value]
                    if val == 0:
                        continue
                    if i == len(cls_values) - 1:
                        v = y1 - y0 - total
                    else:
                        v = ((y1 - y0) * val) / conditionaldict[attr_vals]
                    rect(x0, y0 + total, x1 - x0, v, -20, colors[i])
                    total += v

                if self.use_boxes and \
                        abs(x1 - x0) > bar_width and \
                        abs(y1 - y0) > bar_width:
                    total = 0
                    line(x0 + bar_width, y0, x0 + bar_width, y1)
                    n = sum(prior)
                    for i, (val, color) in enumerate(zip(prior, colors)):
                        if i == len(prior) - 1:
                            h = y1 - y0 - total
                        else:
                            h = (y1 - y0) * val / n
                        rect(x0, y0 + total, bar_width, h, 20, color)
                        total += h

                if conditionalsubsetdict:
                    if conditionalsubsetdict[attr_vals]:
                        counts = [
                            conditionalsubsetdict[attr_vals + "-" + val]
                            for val in cls_values
                        ]
                        if sum(counts) == 1:
                            rect(x0 - 2,
                                 y0 - 2,
                                 x1 - x0 + 5,
                                 y1 - y0 + 5,
                                 -550,
                                 colors[counts.index(1)],
                                 Qt.white,
                                 penWidth=2,
                                 penStyle=Qt.DashLine)
                        if self.subset_data is not None:
                            line(x1 - bar_width, y0, x1 - bar_width, y1)
                            total = 0
                            n = conditionalsubsetdict[attr_vals]
                            if n:
                                for i, (cls, color) in \
                                        enumerate(zip(cls_values, colors)):
                                    val = conditionalsubsetdict[attr_vals +
                                                                "-" + cls]
                                    if val == 0:
                                        continue
                                    if i == len(prior) - 1:
                                        v = y1 - y0 - total
                                    else:
                                        v = ((y1 - y0) * val) / n
                                    rect(x1 - bar_width, y0 + total, bar_width,
                                         v, 15, color)
                                    total += v

                actual = [
                    conditionaldict[attr_vals + "-" + cls_values[i]]
                    for i in range(len(prior))
                ]
                n_actual = sum(actual)
                if n_actual > 0:
                    apriori = [prior[key] for key in cls_values]
                    n_apriori = sum(apriori)
                    text = "<br/>".join(
                        "<b>%s</b>: %d / %.1f%% (Expected %.1f / %.1f%%)" %
                        (cls, act, 100.0 * act / n_actual,
                         apr / n_apriori * n_actual, 100.0 * apr / n_apriori)
                        for cls, act, apr in zip(cls_values, actual, apriori))
                else:
                    text = ""
                outer_rect.setToolTip("{}<hr>Instances: {}<br><br>{}".format(
                    condition, n_actual, text[:-4]))

        def draw_legend(x0_x1, y0_y1):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if self.interior_coloring == self.PEARSON:
                names = [
                    "<-8", "-8:-4", "-4:-2", "-2:2", "2:4", "4:8", ">8",
                    "Residuals:"
                ]
                colors = self.RED_COLORS[::-1] + self.BLUE_COLORS[1:]
            else:
                names = get_variable_values_sorted(class_var) + \
                        [class_var.name + ":"]
                colors = [QColor(*col) for col in class_var.colors]

            names = [
                CanvasText(self.canvas, name, alignment=Qt.AlignVCenter)
                for name in names
            ]
            totalwidth = sum(text.boundingRect().width() for text in names)

            # compute the x position of the center of the legend
            y = y1 + self.ATTR_NAME_OFFSET + self.ATTR_VAL_OFFSET + 35
            distance = 30
            startx = (x0 + x1) / 2 - (totalwidth + (len(names)) * distance) / 2

            names[-1].setPos(startx + 15, y)
            names[-1].show()
            xoffset = names[-1].boundingRect().width() + distance

            size = 8

            for i in range(len(names) - 1):
                if self.interior_coloring == self.PEARSON:
                    edgecolor = Qt.black
                else:
                    edgecolor = colors[i]

                CanvasRectangle(self.canvas, startx + xoffset, y - size / 2,
                                size, size, edgecolor, colors[i])
                names[i].setPos(startx + xoffset + 10, y)
                xoffset += distance + names[i].boundingRect().width()

        self.canvas.clear()
        self.areas = []

        data = self.discrete_data
        if data is None:
            return
        subset = self.subset_data
        attr_list = self.get_attr_list()
        class_var = data.domain.class_var
        if class_var:
            sql = type(data) == SqlTable
            name = not sql and data.name
            # save class_var because it is removed in the next line
            data = data[:, attr_list + [class_var]]
            data.domain.class_var = class_var
            if not sql:
                data.name = name
        else:
            data = data[:, attr_list]
        # TODO: check this
        # data = Preprocessor_dropMissing(data)
        if len(data) == 0:
            self.warning(5, "No valid data for current attributes.")
            return
        else:
            self.warning(5)

        if self.interior_coloring == self.PEARSON:
            apriori_dists = [
                get_distribution(data, attr) for attr in attr_list
            ]
        else:
            apriori_dists = []

        def get_max_label_width(attr):
            values = get_variable_values_sorted(data.domain[attr])
            maxw = 0
            for val in values:
                t = CanvasText(self.canvas, val, 0, 0, bold=0, show=False)
                maxw = max(int(t.boundingRect().width()), maxw)
            return maxw

        # get the maximum width of rectangle
        xoff = 20
        width = 20
        if len(attr_list) > 1:
            text = CanvasText(self.canvas, attr_list[1], bold=1, show=0)
            max_ylabel_w1 = min(get_max_label_width(attr_list[1]), 150)
            width = 5 + text.boundingRect().height() + \
                self.ATTR_VAL_OFFSET + max_ylabel_w1
            xoff = width
            if len(attr_list) == 4:
                text = CanvasText(self.canvas, attr_list[3], bold=1, show=0)
                max_ylabel_w2 = min(get_max_label_width(attr_list[3]), 150)
                width += text.boundingRect().height() + \
                    self.ATTR_VAL_OFFSET + max_ylabel_w2 - 10

        # get the maximum height of rectangle
        height = 100
        yoff = 45
        square_size = min(self.canvas_view.width() - width - 20,
                          self.canvas_view.height() - height - 20)

        if square_size < 0:
            return  # canvas is too small to draw rectangles
        self.canvas_view.setSceneRect(0, 0, self.canvas_view.width(),
                                      self.canvas_view.height())

        drawn_sides = set()
        draw_positions = {}

        conditionaldict, distributiondict = \
            get_conditional_distribution(data, attr_list)
        conditionalsubsetdict = None
        if subset:
            conditionalsubsetdict, _ = \
                get_conditional_distribution(subset, attr_list)

        # draw rectangles
        draw_data(attr_list, (xoff, xoff + square_size),
                  (yoff, yoff + square_size), 0, "", len(attr_list))
        draw_legend((xoff, xoff + square_size), (yoff, yoff + square_size))
        self.update_selection_rects()
Ejemplo n.º 51
0
class OWVennDiagram(widget.OWWidget):
    name = "Venn Diagram"
    icon = "icons/VennDiagram.svg"

    inputs = [("Data", Orange.data.Table, "setData", widget.Multiple)]
    outputs = [("Data", Orange.data.Table)]

    # Selected disjoint subset indices
    selection = settings.Setting([])
    #: Stored input set hints
    #: {(index, inputname, attributes): (selectedattrname, itemsettitle)}
    #: The 'selectedattrname' can be None
    inputhints = settings.Setting({})
    #: Use identifier columns for instance matching
    useidentifiers = settings.Setting(True)
    autocommit = settings.Setting(False)

    def __init__(self, parent=None):
        super().__init__(parent)

        # Output changed flag
        self._changed = False
        # Diagram update is in progress
        self._updating = False
        # Input update is in progress
        self._inputUpdate = False
        # All input tables have the same domain.
        self.samedomain = True
        # Input datasets in the order they were 'connected'.
        self.data = OrderedDict()
        # Extracted input item sets in the order they were 'connected'
        self.itemsets = OrderedDict()

        # GUI
        box = gui.widgetBox(self.controlArea, "Info")
        self.info = gui.widgetLabel(box, "No data on input\n")

        self.identifiersBox = gui.radioButtonsInBox(
            self.controlArea,
            self,
            "useidentifiers", [],
            box="Data Instance Identifiers",
            callback=self._on_useidentifiersChanged)
        self.useequalityButton = gui.appendRadioButton(
            self.identifiersBox, "Use instance equality")
        rb = gui.appendRadioButton(self.identifiersBox, "Use identifiers")
        self.inputsBox = gui.indentedBox(self.identifiersBox,
                                         sep=gui.checkButtonOffsetHint(rb))
        self.inputsBox.setEnabled(bool(self.useidentifiers))

        for i in range(5):
            box = gui.widgetBox(self.inputsBox,
                                "Data set #%i" % (i + 1),
                                addSpace=False)
            box.setFlat(True)
            model = itemmodels.VariableListModel(parent=self)
            cb = QComboBox()
            cb.setModel(model)
            cb.activated[int].connect(self._on_inputAttrActivated)
            box.setEnabled(False)
            # Store the combo in the box for later use.
            box.combo_box = cb
            box.layout().addWidget(cb)

        gui.rubber(self.controlArea)

        box = gui.widgetBox(self.controlArea, "Output")
        cb = gui.checkBox(box, self, "autocommit", "Commit on any change")
        b = gui.button(box, self, "Commit", callback=self.commit, default=True)
        gui.setStopper(self, b, cb, "_changed", callback=self.commit)

        # Main area view
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.setRenderHint(QPainter.Antialiasing)
        self.view.setBackgroundRole(QPalette.Window)
        self.view.setFrameStyle(QGraphicsView.StyledPanel)

        self.mainArea.layout().addWidget(self.view)
        self.vennwidget = VennDiagram()
        self.vennwidget.resize(400, 400)
        self.vennwidget.itemTextEdited.connect(self._on_itemTextEdited)
        self.scene.selectionChanged.connect(self._on_selectionChanged)

        self.scene.addItem(self.vennwidget)

        self.resize(self.controlArea.sizeHint().width() + 550,
                    max(self.controlArea.sizeHint().height(), 550))

        self._queue = []

    def setData(self, data, key=None):
        self.error(0)
        if not self._inputUpdate:
            # Store hints only on the first setData call.
            self._storeHints()
            self._inputUpdate = True

        if key in self.data:
            if data is None:
                # Remove the input
                self._remove(key)
            else:
                # Update existing item
                self._update(key, data)
        elif data is not None:
            # TODO: Allow setting more them 5 inputs and let the user
            # select the 5 to display.
            if len(self.data) == 5:
                self.error(0, "Can only take 5 inputs.")
                return
            # Add a new input
            self._add(key, data)

    def handleNewSignals(self):
        self._inputUpdate = False

        # Check if all inputs are from the same domain.
        domains = [input.table.domain for input in self.data.values()]
        samedomain = all(domain_eq(d1, d2) for d1, d2 in pairwise(domains))

        self.useequalityButton.setEnabled(samedomain)
        self.samedomain = samedomain

        has_identifiers = all(
            source_attributes(input.table.domain)
            for input in self.data.values())

        if not samedomain and not self.useidentifiers:
            self.useidentifiers = 1
        elif samedomain and not has_identifiers:
            self.useidentifiers = 0

        incremental = all(inc for _, inc in self._queue)

        if incremental:
            # Only received updated data on existing link.
            self._updateItemsets()
        else:
            # Links were removed and/or added.
            self._createItemsets()
            self._restoreHints()
            self._updateItemsets()

        del self._queue[:]

        self._createDiagram()
        if self.data:
            self.info.setText("{} data sets on input.\n".format(len(
                self.data)))
        else:
            self.info.setText("No data on input\n")

        self._updateInfo()
        super().handleNewSignals()

    def _invalidate(self, keys=None, incremental=True):
        """
        Invalidate input for a list of input keys.
        """
        if keys is None:
            keys = list(self.data.keys())

        self._queue.extend((key, incremental) for key in keys)

    def itemsetAttr(self, key):
        index = list(self.data.keys()).index(key)
        _, combo = self._controlAtIndex(index)
        model = combo.model()
        attr_index = combo.currentIndex()
        if attr_index >= 0:
            return model[attr_index]
        else:
            return None

    def _controlAtIndex(self, index):
        group_box = self.inputsBox.layout().itemAt(index).widget()
        combo = group_box.combo_box
        return group_box, combo

    def _setAttributes(self, index, attrs):
        box, combo = self._controlAtIndex(index)
        model = combo.model()

        if attrs is None:
            model[:] = []
            box.setEnabled(False)
        else:
            if model[:] != attrs:
                model[:] = attrs

            box.setEnabled(True)

    def _add(self, key, table):
        name = table.name
        index = len(self.data)
        attrs = source_attributes(table.domain)

        self.data[key] = _InputData(key, name, table)

        self._setAttributes(index, attrs)

        self._invalidate([key], incremental=False)

        item = self.inputsBox.layout().itemAt(index)
        box = item.widget()
        box.setTitle("Data set: {}".format(name))

    def _remove(self, key):
        index = list(self.data.keys()).index(key)

        # Clear possible warnings.
        self.warning(index)

        self._setAttributes(index, None)

        del self.data[key]

        layout = self.inputsBox.layout()
        item = layout.takeAt(index)
        layout.addItem(item)
        inputs = list(self.data.values())

        for i in range(5):
            box, _ = self._controlAtIndex(i)
            if i < len(inputs):
                title = "Data set: {}".format(inputs[i].name)
            else:
                title = "Data set #{}".format(i + 1)
            box.setTitle(title)

        self._invalidate([key], incremental=False)

    def _update(self, key, table):
        name = table.name
        index = list(self.data.keys()).index(key)
        attrs = source_attributes(table.domain)

        self.data[key] = self.data[key]._replace(name=name, table=table)

        self._setAttributes(index, attrs)
        self._invalidate([key])

        item = self.inputsBox.layout().itemAt(index)
        box = item.widget()
        box.setTitle("Data set: {}".format(name))

    def _itemsForInput(self, key):
        useidentifiers = self.useidentifiers or not self.samedomain

        def items_by_key(key, input):
            attr = self.itemsetAttr(key)
            if attr is not None:
                return [
                    str(inst[attr]) for inst in input.table
                    if not numpy.isnan(inst[attr])
                ]
            else:
                return []

        def items_by_eq(key, input):
            return list(map(ComparableInstance, input.table))

        input = self.data[key]
        if useidentifiers:
            items = items_by_key(key, input)
        else:
            items = items_by_eq(key, input)
        return items

    def _updateItemsets(self):
        assert list(self.data.keys()) == list(self.itemsets.keys())
        for key, input in list(self.data.items()):
            items = self._itemsForInput(key)
            item = self.itemsets[key]
            item = item._replace(items=items)
            name = input.name
            if item.name != name:
                item = item._replace(name=name, title=name)
            self.itemsets[key] = item

    def _createItemsets(self):
        olditemsets = dict(self.itemsets)
        self.itemsets.clear()

        for key, input in self.data.items():
            items = self._itemsForInput(key)
            name = input.name
            if key in olditemsets and olditemsets[key].name == name:
                # Reuse the title (which might have been changed by the user)
                title = olditemsets[key].title
            else:
                title = name

            itemset = _ItemSet(key=key, name=name, title=title, items=items)
            self.itemsets[key] = itemset

    def _storeHints(self):
        if self.data:
            self.inputhints.clear()
            for i, (key, input) in enumerate(self.data.items()):
                attrs = source_attributes(input.table.domain)
                attrs = tuple(attr.name for attr in attrs)
                selected = self.itemsetAttr(key)
                if selected is not None:
                    attr_name = selected.name
                else:
                    attr_name = None
                itemset = self.itemsets[key]
                self.inputhints[(i, input.name, attrs)] = \
                    (attr_name, itemset.title)

    def _restoreHints(self):
        settings = []
        for i, (key, input) in enumerate(self.data.items()):
            attrs = source_attributes(input.table.domain)
            attrs = tuple(attr.name for attr in attrs)
            hint = self.inputhints.get((i, input.name, attrs), None)
            if hint is not None:
                attr, name = hint
                attr_ind = attrs.index(attr) if attr is not None else -1
                settings.append((attr_ind, name))
            else:
                return

        # all inputs match the stored hints
        for i, key in enumerate(self.itemsets):
            attr, itemtitle = settings[i]
            self.itemsets[key] = self.itemsets[key]._replace(title=itemtitle)
            _, cb = self._controlAtIndex(i)
            cb.setCurrentIndex(attr)

    def _createDiagram(self):
        self._updating = True

        oldselection = list(self.selection)

        self.vennwidget.clear()
        n = len(self.itemsets)
        self.disjoint = disjoint(set(s.items) for s in self.itemsets.values())

        vennitems = []
        colors = colorpalette.ColorPaletteHSV(n)

        for i, (key, item) in enumerate(self.itemsets.items()):
            gr = VennSetItem(text=item.title, count=len(item.items))
            color = colors[i]
            color.setAlpha(100)
            gr.setBrush(QBrush(color))
            gr.setPen(QPen(Qt.NoPen))
            vennitems.append(gr)

        self.vennwidget.setItems(vennitems)

        for i, area in enumerate(self.vennwidget.vennareas()):
            area_items = list(map(str, list(self.disjoint[i])))
            if i:
                area.setText("{0}".format(len(area_items)))

            label = disjoint_set_label(i, n, simplify=False)
            head = "<h4>|{}| = {}</h4>".format(label, len(area_items))
            if len(area_items) > 32:
                items_str = ", ".join(map(escape, area_items[:32]))
                hidden = len(area_items) - 32
                tooltip = (
                    "{}<span>{}, ...</br>({} items not shown)<span>".format(
                        head, items_str, hidden))
            elif area_items:
                tooltip = "{}<span>{}</span>".format(
                    head, ", ".join(map(escape, area_items)))
            else:
                tooltip = head

            area.setToolTip(tooltip)

            area.setPen(QPen(QColor(10, 10, 10, 200), 1.5))
            area.setFlag(QGraphicsPathItem.ItemIsSelectable, True)
            area.setSelected(i in oldselection)

        self._updating = False
        self._on_selectionChanged()

    def _updateInfo(self):
        # Clear all warnings
        self.warning(list(range(5)))

        if not len(self.data):
            self.info.setText("No data on input\n")
        else:
            self.info.setText("{0} data sets on input\n".format(len(
                self.data)))

        if self.useidentifiers:
            for i, key in enumerate(self.data):
                if not source_attributes(self.data[key].table.domain):
                    self.warning(
                        i,
                        "Data set #{} has no suitable identifiers.".format(i +
                                                                           1))

    def _on_selectionChanged(self):
        if self._updating:
            return

        areas = self.vennwidget.vennareas()
        indices = [i for i, area in enumerate(areas) if area.isSelected()]

        self.selection = indices

        self.invalidateOutput()

    def _on_useidentifiersChanged(self):
        self.inputsBox.setEnabled(self.useidentifiers == 1)
        # Invalidate all itemsets
        self._invalidate()
        self._updateItemsets()
        self._createDiagram()

        self._updateInfo()

    def _on_inputAttrActivated(self, attr_index):
        combo = self.sender()
        # Find the input index to which the combo box belongs
        # (they are reordered when removing inputs).
        index = None
        inputs = list(self.data.items())
        for i in range(len(inputs)):
            _, c = self._controlAtIndex(i)
            if c is combo:
                index = i
                break

        assert (index is not None)

        key, _ = inputs[index]

        self._invalidate([key])
        self._updateItemsets()
        self._createDiagram()

    def _on_itemTextEdited(self, index, text):
        text = str(text)
        key = list(self.itemsets.keys())[index]
        self.itemsets[key] = self.itemsets[key]._replace(title=text)

    def invalidateOutput(self):
        if self.autocommit:
            self.commit()
        else:
            self._changed = True

    def commit(self):
        selected_subsets = []

        selected_items = reduce(
            set.union, [self.disjoint[index] for index in self.selection],
            set())

        def match(val):
            if numpy.isnan(val):
                return False
            else:
                return str(val) in selected_items

        source_var = Orange.data.StringVariable("source")
        item_id_var = Orange.data.StringVariable("item_id")

        names = [itemset.title.strip() for itemset in self.itemsets.values()]
        names = uniquify(names)

        for i, (key, input) in enumerate(self.data.items()):
            if self.useidentifiers:
                attr = self.itemsetAttr(key)
                if attr is not None:
                    mask = list(
                        map(match, (inst[attr] for inst in input.table)))
                else:
                    mask = [False] * len(input.table)

                def instance_key(inst):
                    return str(inst[attr])
            else:
                mask = [
                    ComparableInstance(inst) in selected_items
                    for inst in input.table
                ]
                _map = {item: str(i) for i, item in enumerate(selected_items)}

                def instance_key(inst):
                    return _map[ComparableInstance(inst)]

            mask = numpy.array(mask, dtype=bool)
            subset = Orange.data.Table(input.table.domain, input.table[mask])
            if len(subset) == 0:
                continue

            # add columns with source table id and set id

            id_column = [[instance_key(inst)] for inst in subset]
            source_names = numpy.array([[names[i]]] * len(subset))

            subset = append_column(subset, "M", source_var, source_names)
            subset = append_column(subset, "M", item_id_var, id_column)

            selected_subsets.append(subset)

        if selected_subsets:
            data = table_concat(selected_subsets)
            # Get all variables which are not constant between the same
            # item set
            varying = varying_between(data, [item_id_var])

            if source_var in varying:
                varying.remove(source_var)

            data = reshape_wide(data, varying, [item_id_var], [source_var])
            # remove the temporary item set id column
            data = drop_columns(data, [item_id_var])
        else:
            data = None

        self.send("Data", data)

    def getSettings(self, *args, **kwargs):
        self._storeHints()
        return super().getSettings(self, *args, **kwargs)
Ejemplo n.º 52
0
class BrushingModel(QObject):
    brushSizeChanged = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged = pyqtSignal(int)

    minBrushSize = 1
    maxBrushSize = 61
    defaultBrushSize = 3
    defaultDrawnNumber = 1
    defaultColor = Qt.white
    erasingColor = Qt.black
    erasingNumber = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb = QRect()  #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not (self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b - 1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b + 1)

    def setBrushColor(self, color):
        self.drawColor = color
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved  # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert (self.pos == pos)
            self.moveTo(QPointF(pos.x() + 0.0001,
                                pos.y() + 0.0001))  # move a little

        # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage.
        # We seem to get better results if we do the following:
        # 1) Slightly offset the source window because apparently there is a small shift in the data
        # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x)
        # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image,
        #     applying some threshold to determine if the final pixel is on or off.

        tempi = QImage(QSize(4 * self.bb.width(), 4 * self.bb.height()),
                       QImage.Format_ARGB32_Premultiplied)  #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        # Offset the source window.  At first I thought the right offset was 0.5, because
        #  that would seem to make sure points are rounded to pixel CENTERS, but
        #  experimentation indicates that 0.25 is slightly better for some reason...
        source_rect = QRectF(QPointF(self.bb.x() + 0.25,
                                     self.bb.y() + 0.25),
                             QSizeF(self.bb.width(), self.bb.height()))
        target_rect = QRectF(QPointF(0, 0),
                             QSizeF(4 * self.bb.width(), 4 * self.bb.height()))
        self.scene.render(painter, target=target_rect, source=source_rect)
        painter.end()

        # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing
        ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int)
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr //= 4 * 4

        downsample_threshold = (7. / 16) * 255
        labels = numpy.where(ndarr >= downsample_threshold,
                             numpy.uint8(self.drawnNumber), numpy.uint8(0))
        labels = labels.swapaxes(0, 1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(
                labels) == 0:
            labels[labels.shape[0] // 2,
                   labels.shape[1] // 2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()),
                                       labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x, y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(
            QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap,
                 Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1))
        #grow bounding box
        self.bb.setLeft(
            min(self.bb.left(), max(0, x - self.brushSize // 2 - 1)))
        self.bb.setRight(
            max(self.bb.right(),
                min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1)))
        self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1)))
        self.bb.setBottom(
            max(self.bb.bottom(),
                min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1)))

        #update/move position
        self.pos = pos
Ejemplo n.º 53
0
class FlowChartView(QWidget):
    """
    Flowchart view
    """
    def __init__(self, parent):
        """
        Constructs FlowChartView widget 

        @param parent:
        @type parent: 
        """
        QWidget.__init__(self, parent)

        self.steps = []
        self.timestamps = []
        self.arrows = []

        self.createWidget()

    def createWidget(self):
        """
        Create the widget
        """
        self.diagramScene = QGraphicsScene(self)

        self.view = QGraphicsView(self.diagramScene)

        self.view.setRenderHint(QPainter.Antialiasing)

        # set the main layout
        layout = QVBoxLayout()

        self.logEdit = QTextEdit()
        self.logEdit.setReadOnly(True)

        hSplitter2 = QSplitter(self)
        hSplitter2.setOrientation(Qt.Vertical)

        hSplitter2.addWidget(self.view)
        hSplitter2.addWidget(self.logEdit)

        hSplitter2.setStretchFactor(0, 1)

        layout.addWidget(hSplitter2)
        self.setLayout(layout)

    def reset(self):
        """
        Clear all 
        """
        #self.diagramScene.clear()

        for stp in self.steps:
            self.diagramScene.removeItem(stp)

        for stp in self.arrows:
            self.diagramScene.removeItem(stp)

        for stamp in self.timestamps:
            self.diagramScene.removeItem(stamp)

        self.diagramScene.clear()
        self.diagramScene.update()
        self.view.resetCachedContent()

        self.steps = []
        self.arrows = []
        self.timestamps = []
        self.logEdit.setText("")

    def addStep(self,
                text,
                color="#A5A2A5",
                width=400,
                height=40,
                data=None,
                textBold=False,
                textItalic=False,
                timestamp="00:00:00"):
        """
        Add step
        """
        # take the last one
        if len(self.steps):
            latestBlock = self.steps[-1:][0]
        else:
            latestBlock = None

        newBlock = BlockItem(self,
                             text,
                             blockColor=color,
                             width=width,
                             height=height,
                             data=data,
                             bold=textBold,
                             italic=textItalic)
        if width == 100:
            newBlock.setPos(400 / 2 - 100 / 2, len(self.steps) * 80)
        elif width == 300:
            newBlock.setPos(400 / 2 - 300 / 2, len(self.steps) * 80)
        else:
            newBlock.setPos(0, len(self.steps) * 80)

        self.steps.append(newBlock)
        self.diagramScene.addItem(newBlock)

        newTimestampBlock = TimestampItem(self, timestamp)
        newTimestampBlock.setPos(-200, len(self.timestamps) * 80)

        self.timestamps.append(newTimestampBlock)
        self.diagramScene.addItem(newTimestampBlock)

        if latestBlock is not None:
            newArrow = LineItem(latestBlock, newBlock)
            self.diagramScene.addItem(newArrow)
            self.arrows.append(newArrow)

        if QtHelper.str2bool(Settings.instance().readValue(
                key='TestRun/auto-scrolling-graph')):
            self.view.centerOn(newBlock)
        return newBlock
Ejemplo n.º 54
0
class QPokerWidget(QWidget):
    def __init__(self, dataDir="", parent=None):
        QWidget.__init__(self, parent)
        self.renderer = QSvgRenderer(dataDir + "poker.svg")
        self.scene = QGraphicsScene()
        self.chat = QGraphicsSimpleTextItem()
        self.table = QGraphicsSvgItem(dataDir + "poker.svg")
        self.table.setSharedRenderer(self.renderer)
        self.table.setElementId("table")
        self.table.setMatrix(self.renderer.matrixForElement("transform_table"))
        self.scene.addItem(self.chat)
        self.scene.addItem(self.table)
        self.board = []
        for i in range(5):
            card = AnimatedGraphicsSvgItem(dataDir + "svg-cards.svg",
                                           self.table)
            card.setElementId("back")
            parent = self.renderer.matrixForElement("transform_table")
            child = self.renderer.matrixForElement("transform_card%i" % i)
            cardMatrix = child.translate(-parent.dx(), -parent.dy())
            card.setMatrix(cardMatrix)
            #card.setFlag(QGraphicsSvgItem.ItemIsMovable, True)
            card.scale(0.5, 0.5)
            card.hide()
            self.scene.addItem(card)
            self.board.append(card)
        self.seats = []
        self.names = []
        self.moneys = []
        self.bets = []
        for i in range(10):
            seat = SeatItem()

            def seatClickedEvent(seat=i):
                seatClickedCallback = self.seatClicked
                seatClickedCallback(seat)

            seat.event = seatClickedEvent
            seat.setSharedRenderer(self.renderer)
            seat.setElementId("seat")
            seat.setMatrix(
                self.renderer.matrixForElement("transform_seat%i" % i))
            self.scene.addItem(seat)
            self.seats.append(seat)
            name = QGraphicsSimpleTextItem(seat)
            name.setMatrix(self.renderer.matrixForElement("seat_name"))
            self.scene.addItem(name)
            self.names.append(name)
            money = QGraphicsSimpleTextItem(seat)
            money.setMatrix(self.renderer.matrixForElement("seat_money"))
            self.scene.addItem(money)
            self.moneys.append(money)
            bet = QGraphicsSimpleTextItem()
            bet.setMatrix(self.renderer.matrixForElement("transform_bet%i" %
                                                         i))
            self.scene.addItem(bet)
            self.bets.append(bet)
        self.pots = []
        for i in range(9):
            pot = QGraphicsSimpleTextItem()
            pot.setMatrix(self.renderer.matrixForElement("transform_pot%i" %
                                                         i))
            self.scene.addItem(pot)
            self.pots.append(pot)
        self.view = QGraphicsView(self)
        self.view.setScene(self.scene)
        self.view.resize(800, 600)
        self.fold = ActionItem()
        self.fold.setText("fold")
        self.fold.setPos(0, 550)
        self.scene.addItem(self.fold)
        self.fold.event = lambda: self.foldClicked()
        self.check = ActionItem()
        self.check.setText("check")
        self.check.setPos(50, 550)
        self.scene.addItem(self.check)
        self.check.event = lambda: self.checkClicked()
        self.call = ActionItem()
        self.call.setText("call")
        self.call.setPos(100, 550)
        self.scene.addItem(self.call)
        self.call.event = lambda: self.callClicked()
        self.bet = ActionItem()
        self.bet.setText("bet")
        self.bet.setPos(150, 550)
        self.scene.addItem(self.bet)
        self.bet.event = lambda: self.betClicked()

    def renderChat(self, message):
        self.chat.setText(message)

    def renderBoard(self, cards):
        for i in range(len(cards)):
            item = self.board[i]
            card = cards[i]
            item.setElementId(card2SvgElement(card))
            if item.isVisible() == False:
                item.show()
        for i in range(len(cards), len(self.board)):
            item = self.board[i]
            item.hide()
            item.setElementId('back')

    def renderStart(self):
        map(lambda svgItem: svgItem.setElementId('back'), self.board)
        map(lambda svgItem: svgItem.hide(), self.board)

    def renderPlayerArrive(self, seat, name):
        self.names[seat].setText(name)
        self.names[seat].show()

    def renderPlayerLeave(self, seat):
        self.names[seat].setText('')
        self.names[seat].hide()
        self.moneys[seat].hide()
        self.bets[seat].hide()

    def renderPlayerChips(self, seat, money, bet):
        if bet > 0:
            self.bets[seat].setText(str(bet))
            self.bets[seat].show()
        else:
            self.bets[seat].hide()
        self.moneys[seat].setText(str(money))
        self.moneys[seat].show()

    def renderPot(self, index, amount):
        self.pots[index].setText(str(amount))
        self.pots[index].show()

    def renderPotReset(self):
        for pot in self.pots:
            pot.setText("")
            pot.hide()

    def renderPosition(self, seatInPosition):
        for i in range(len(self.seats)):
            seat = self.seats[i]
            if i == seatInPosition:
                seat.setElementId("seat_inposition")
            else:
                seat.setElementId("seat")

    def renderPositionReset(self):
        for seat in self.seats:
            seat.setElementId("seat")

    def keyPressEvent(self, event):
        if event.text() == "q":
            self.view.scale(1.1, 1.1)
        elif event.text() == "a":
            self.view.scale(0.9, 0.9)

    seatClicked = lambda seat: None
    foldClicked = lambda: None
    checkClicked = lambda: None
    callClicked = lambda: None
    betClicked = lambda: None
Ejemplo n.º 55
0
class TakeDragGame(QWidget):
    def __init__(self, parent=None):
        super(TakeDragGame, self).__init__(parent)

        # This is always the same
        self.dot2 = QGraphicsTextItem(':')
        self.dot1 = QGraphicsTextItem(':')
        self.animations = []
        self.digits = []
        self.main_layout = QHBoxLayout()
        self.setLayout(self.main_layout)
        self.scene = QGraphicsScene()
        self.scene.setSceneRect(0, 0, 600, 400)
        self.view = QGraphicsView()
        self.view.setScene(self.scene)
        # TODO: Check if its better with opengl or not
        # self.view.setViewport(QtOpenGL.QGLWidget())
        self.main_layout.addWidget(self.view)
        # self.setWindowState(Qt.WindowMaximized)
        self.view.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.image_bank = None
        self.create_and_add_images()

        # self.scene.setBackgroundBrush(QBrush(Qt.red, Qt.SolidPattern))

        # self.populate()
        # self.animator = QTimer()
        # self.animator.timeout.connect(self.animate)
        # self.animate()

    def create_and_add_images(self):
        self.load_images_json_file()
        self.add_background_to_image()
        self.add_background_from_image()
        if self.image_bank is not None:
            for image_id in self.image_bank.keys():
                if "clothes" in self.image_bank[image_id]["categories"]:
                    image_path = self.image_bank[image_id]["path"]
                    new_image = DraggableItem(image_path, self.background_from_image)
                    new_image.moved_signal.moved.connect(self.item_moved)
                    self.image_bank[image_id]["widget"] = new_image
                    newpos_x = self.background_from_image.boundingRect().width() / 2 - new_image.boundingRect().width() / 2
                    newpos_y = self.background_from_image.boundingRect().height() / 2 - new_image.boundingRect().height() / 2
                    new_image.setPos(newpos_x, newpos_y)
                    # self.scene.addItem(new_image)
                    new_image.setZValue(30)

    def item_moved(self, pos):
        widget = self.sender().get_parent()
        print widget.zValue()
        print self.background_from_image.zValue()
        print self.background_to_image.zValue()
        item_br = widget.sceneBoundingRect()
        if self.background_from_image.sceneBoundingRect().contains(item_br):
            widget.setParentItem(self.background_from_image)
            newpos_x = self.background_from_image.boundingRect().width() / 2 - widget.boundingRect().width() / 2
            newpos_y = self.background_from_image.boundingRect().height() / 2 - widget.boundingRect().height() / 2
            # self.background_to_image.stackBefore(self.background_from_image)
            widget.setPos(newpos_x, newpos_y)
        elif self.background_to_image.sceneBoundingRect().contains(item_br):
            widget.setParentItem(self.background_to_image)
            newpos_x = self.background_to_image.boundingRect().width() / 2 - widget.boundingRect().width() / 2
            newpos_y = self.background_to_image.boundingRect().height() / 2 - widget.boundingRect().height() / 2
            # self.background_from_image.stackBefore(self.background_to_image)
            widget.setPos(newpos_x, newpos_y)



    def load_images_json_file(self):
        with open(os.path.join(CURRENT_PATH, './resources/images.json')) as f:
            self.image_bank = json.load(f)

    def add_background_from_image(self, ):
        assert self.image_bank is not None, "Images need to be loaded before calling this method (try load_images_json_file)"
        if "Background from" in self.image_bank:
            background_from_pixmap = QPixmap(self.image_bank["Background from"]["path"])
            self.background_from_image = QGraphicsPixmapItem(background_from_pixmap)
            self.scene.addItem(self.background_from_image)
            self.background_from_image.setZValue(2)

    def add_background_to_image(self, ):
        assert self.image_bank is not None, "Images need to be loaded before calling this method (try load_images_json_file)"
        if "Background to" in self.image_bank:
            background_to_pixmap = QPixmap(self.image_bank["Background to"]["path"])
            self.background_to_image = QGraphicsPixmapItem(background_to_pixmap)
            self.scene.addItem(self.background_to_image)
            self.background_to_image.setZValue(2)

    def resizeEvent(self, event):
        view_size = self.view.size()
        new_background_height = (1.5 / 4.) * view_size.height()
        background_to_pixmap = QPixmap(self.image_bank["Background to"]["path"])
        background_to_pixmap = background_to_pixmap.scaled(new_background_height, new_background_height,
                                                           Qt.KeepAspectRatio)
        if not self.background_to_image:
            self.background_to_image = QGraphicsPixmapItem(background_to_pixmap)
        else:
            self.background_to_image.setPixmap(background_to_pixmap)
        sugested_x_position = int(2 * (view_size.width() / 3.))
        if sugested_x_position < 0:
            sugested_x_position = 0
        sugested_y_position = int(view_size.height() / 2. - background_to_pixmap.size().height() / 2)
        if sugested_y_position < 0:
            sugested_y_position = 0
        self.background_to_image.setPos(sugested_x_position, sugested_y_position)

        #####################
        new_background_height = (2.2 / 4.) * view_size.height()
        background_from_pixmap = QPixmap(self.image_bank["Background from"]["path"])
        background_from_pixmap = background_from_pixmap.scaled(new_background_height, new_background_height,
                                                               Qt.KeepAspectRatio)
        if not self.background_to_image:
            self.background_from_image = QGraphicsPixmapItem(background_from_pixmap)
        else:
            self.background_from_image.setPixmap(background_from_pixmap)

        sugested_x_position = int(view_size.width() / 5. - background_from_pixmap.size().height() / 2)
        if sugested_x_position < 0:
            sugested_x_position = 0
        sugested_y_position = int(view_size.height() / 2. - background_from_pixmap.size().height() / 2)
        if sugested_y_position < 0:
            sugested_y_position = 0
        self.background_from_image.setPos(sugested_x_position, sugested_y_position)

        ####
        new_widget_height = (1 / 4.) * view_size.height()
        if self.image_bank is not None:
            for image_id in self.image_bank.keys():
                if "clothes" in self.image_bank[image_id]["categories"]:
                    widget = self.image_bank[image_id]["widget"]
                    pixmap = widget.pixmap
                    pixmap = pixmap.scaled(new_widget_height, new_widget_height,
                                           Qt.KeepAspectRatio)
                    widget.setPixmap(pixmap)
                    print widget.moved_flag
                    if not widget.moved_flag:
                        newpos_x = self.background_from_image.boundingRect().width() / 2 - widget.boundingRect().width() / 2
                        newpos_y = self.background_from_image.boundingRect().height() / 2 - widget.boundingRect().height() / 2
                        widget.setPos(newpos_x, newpos_y)

        super(TakeDragGame, self).resizeEvent(event)
Ejemplo n.º 56
0
class BrushingModel(QObject):
    brushSizeChanged     = pyqtSignal(int)
    brushColorChanged    = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged   = pyqtSignal(int)

    minBrushSize       = 1
    maxBrushSize       = 61
    defaultBrushSize   = 3
    defaultDrawnNumber = 1
    defaultColor       = Qt.white
    erasingColor       = Qt.black
    erasingNumber      = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb    = QRect() #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not(self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b-1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b+1)

    def setBrushColor(self, color):
        self.drawColor = color
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert(self.pos == pos)
            self.moveTo(QPointF(pos.x()+0.0001, pos.y()+0.0001)) # move a little

        tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        self.scene.render(painter, target=QRectF(), source=QRectF(QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height())))
        painter.end()

        ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0]
        labels = numpy.where(ndarr>0,numpy.uint8(self.drawnNumber),numpy.uint8(0))
        labels = labels.swapaxes(0,1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0:
            labels[labels.shape[0]//2, labels.shape[1]//2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x,y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX,oldY), QSize(1,1))
        #grow bounding box
        self.bb.setLeft(  min(self.bb.left(),   max(0,                   x-self.brushSize/2-1) ) )
        self.bb.setRight( max(self.bb.right(),  min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) )
        self.bb.setTop(   min(self.bb.top(),    max(0,                   y-self.brushSize/2-1) ) )
        self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) )

        #update/move position
        self.pos = pos
Ejemplo n.º 57
0
class ImagesPreviewer(foundations.ui.common.QWidgetFactory(uiFile=UI_FILE)):
    """
	| This class provides the Application images previewer.
	| It defines methods to navigate through the list of given images ( List of images paths ),
		zoom in / out and fit the displayed image, etc...
	"""
    def __init__(self, parent, paths=None, *args, **kwargs):
        """
		This method initializes the class.

		:param parent: Object parent. ( QObject )
		:param paths: Images paths. ( Tuple / List )
		:param \*args: Arguments. ( \* )
		:param \*\*kwargs: Keywords arguments. ( \*\* )
		"""

        LOGGER.debug("> Initializing '{0}()' class.".format(
            self.__class__.__name__))

        super(ImagesPreviewer, self).__init__(parent, *args, **kwargs)

        # --- Setting class attributes. ---
        self.__container = parent
        self.__paths = None
        self.paths = paths

        self.__uiResourcesDirectory = "resources"
        self.__uiResourcesDirectory = os.path.join(os.path.dirname(__file__),
                                                   self.__uiResourcesDirectory)
        self.__uiPreviousImage = "Previous.png"
        self.__uiNextImage = "Next.png"
        self.__uiZoomOutImage = "Zoom_Out.png"
        self.__uiZoomInImage = "Zoom_In.png"

        # Ensure the ui object is destroyed on close to avoid memory leaks.
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.__graphicsSceneBackgroundColor = QColor(32, 32, 32)
        self.__minimumZoomFactor = 0.05
        self.__maximumZoomFactor = 25
        self.__displayGraphicsItemMargin = 32
        self.__graphicsSceneWidth = QApplication.desktop().screenGeometry(
            QApplication.desktop().primaryScreen()).width() * (
                1 / self.__minimumZoomFactor * 1.75)
        self.__graphicsSceneHeight = QApplication.desktop().screenGeometry(
            QApplication.desktop().primaryScreen()).height() * (
                1 / self.__minimumZoomFactor * 1.75)
        self.__wheelZoomFactor = 350.0
        self.__keyZoomFactor = 1.20

        self.__graphicsView = None
        self.__graphicsScene = None
        self.__displayGraphicsItem = None

        ImagesPreviewer.__initializeUi(self)

        self.loadImage()

    #******************************************************************************************************************
    #***	Attributes properties.
    #******************************************************************************************************************
    @property
    def container(self):
        """
		This method is the property for **self.__container** attribute.

		:return: self.__container. ( QObject )
		"""

        return self.__container

    @container.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def container(self, value):
        """
		This method is the setter method for **self.__container** attribute.

		:param value: Attribute value. ( QObject )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "container"))

    @container.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def container(self):
        """
		This method is the deleter method for **self.__container** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "container"))

    @property
    def paths(self):
        """
		This method is the property for **self.__paths** attribute.

		:return: self.__paths. ( Tuple / List )
		"""

        return self.__paths

    @paths.setter
    @foundations.exceptions.handleExceptions(AssertionError)
    def paths(self, value):
        """
		This method is the setter method for **self.__paths** attribute.

		:param value: Attribute value. ( Tuple / List )
		"""

        if value is not None:
            assert type(value) in (
                tuple, list
            ), "'{0}' attribute: '{1}' type is not 'tuple' or 'list'!".format(
                "paths", value)
            for element in value:
                assert type(
                    element
                ) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
                    "paths", element)
        self.__paths = value

    @paths.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def paths(self):
        """
		This method is the deleter method for **self.__paths** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "paths"))

    @property
    def uiResourcesDirectory(self):
        """
		This method is the property for **self.__uiResourcesDirectory** attribute.

		:return: self.__uiResourcesDirectory. ( String )
		"""

        return self.__uiResourcesDirectory

    @uiResourcesDirectory.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiResourcesDirectory(self, value):
        """
		This method is the setter method for **self.__uiResourcesDirectory** attribute.

		:param value: Attribute value. ( String )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiResourcesDirectory"))

    @uiResourcesDirectory.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiResourcesDirectory(self):
        """
		This method is the deleter method for **self.__uiResourcesDirectory** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiResourcesDirectory"))

    @property
    def uiPreviousImage(self):
        """
		This method is the property for **self.__uiPreviousImage** attribute.

		:return: self.__uiPreviousImage. ( String )
		"""

        return self.__uiPreviousImage

    @uiPreviousImage.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiPreviousImage(self, value):
        """
		This method is the setter method for **self.__uiPreviousImage** attribute.

		:param value: Attribute value. ( String )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiPreviousImage"))

    @uiPreviousImage.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiPreviousImage(self):
        """
		This method is the deleter method for **self.__uiPreviousImage** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiPreviousImage"))

    @property
    def uiNextImage(self):
        """
		This method is the property for **self.__uiNextImage** attribute.

		:return: self.__uiNextImage. ( String )
		"""

        return self.__uiNextImage

    @uiNextImage.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiNextImage(self, value):
        """
		This method is the setter method for **self.__uiNextImage** attribute.

		:param value: Attribute value. ( String )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiNextImage"))

    @uiNextImage.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiNextImage(self):
        """
		This method is the deleter method for **self.__uiNextImage** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiNextImage"))

    @property
    def uiZoomOutImage(self):
        """
		This method is the property for **self.__uiZoomOutImage** attribute.

		:return: self.__uiZoomOutImage. ( String )
		"""

        return self.__uiZoomOutImage

    @uiZoomOutImage.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiZoomOutImage(self, value):
        """
		This method is the setter method for **self.__uiZoomOutImage** attribute.

		:param value: Attribute value. ( String )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiZoomOutImage"))

    @uiZoomOutImage.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiZoomOutImage(self):
        """
		This method is the deleter method for **self.__uiZoomOutImage** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiZoomOutImage"))

    @property
    def uiZoomInImage(self):
        """
		This method is the property for **self.__uiZoomInImage** attribute.

		:return: self.__uiZoomInImage. ( String )
		"""

        return self.__uiZoomInImage

    @uiZoomInImage.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiZoomInImage(self, value):
        """
		This method is the setter method for **self.__uiZoomInImage** attribute.

		:param value: Attribute value. ( String )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiZoomInImage"))

    @uiZoomInImage.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiZoomInImage(self):
        """
		This method is the deleter method for **self.__uiZoomInImage** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiZoomInImage"))

    @property
    def graphicsSceneBackgroundColor(self):
        """
		This method is the property for **self.__graphicsSceneBackgroundColor** attribute.

		:return: self.__graphicsSceneBackgroundColor. ( QColors )
		"""

        return self.__graphicsSceneBackgroundColor

    @graphicsSceneBackgroundColor.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsSceneBackgroundColor(self, value):
        """
		This method is the setter method for **self.__graphicsSceneBackgroundColor** attribute.

		:param value: Attribute value. ( QColors )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "graphicsSceneBackgroundColor"))

    @graphicsSceneBackgroundColor.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsSceneBackgroundColor(self):
        """
		This method is the deleter method for **self.__graphicsSceneBackgroundColor** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "graphicsSceneBackgroundColor"))

    @property
    def graphicsSceneWidth(self):
        """
		This method is the property for **self.__graphicsSceneWidth** attribute.

		:return: self.__graphicsSceneWidth. ( Integer )
		"""

        return self.__graphicsSceneWidth

    @graphicsSceneWidth.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsSceneWidth(self, value):
        """
		This method is the setter method for **self.__graphicsSceneWidth** attribute.

		:param value: Attribute value. ( Integer )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "graphicsSceneWidth"))

    @graphicsSceneWidth.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsSceneWidth(self):
        """
		This method is the deleter method for **self.__graphicsSceneWidth** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "graphicsSceneWidth"))

    @property
    def graphicsSceneHeight(self):
        """
		This method is the property for **self.__graphicsSceneHeight** attribute.

		:return: self.__graphicsSceneHeight. ( Object )
		"""

        return self.__graphicsSceneHeight

    @graphicsSceneHeight.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsSceneHeight(self, value):
        """
		This method is the setter method for **self.__graphicsSceneHeight** attribute.

		:param value: Attribute value. ( Object )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "graphicsSceneHeight"))

    @graphicsSceneHeight.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsSceneHeight(self):
        """
		This method is the deleter method for **self.__graphicsSceneHeight** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "graphicsSceneHeight"))

    @property
    def minimumZoomFactor(self):
        """
		This method is the property for **self.__minimumZoomFactor** attribute.

		:return: self.__minimumZoomFactor. ( Float )
		"""

        return self.__minimumZoomFactor

    @minimumZoomFactor.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def minimumZoomFactor(self, value):
        """
		This method is the setter method for **self.__minimumZoomFactor** attribute.

		:param value: Attribute value. ( Float )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "minimumZoomFactor"))

    @minimumZoomFactor.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def minimumZoomFactor(self):
        """
		This method is the deleter method for **self.__minimumZoomFactor** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "minimumZoomFactor"))

    @property
    def maximumZoomFactor(self):
        """
		This method is the property for **self.__maximumZoomFactor** attribute.

		:return: self.__maximumZoomFactor. ( Float )
		"""

        return self.__maximumZoomFactor

    @maximumZoomFactor.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def maximumZoomFactor(self, value):
        """
		This method is the setter method for **self.__maximumZoomFactor** attribute.

		:param value: Attribute value. ( Float )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "maximumZoomFactor"))

    @maximumZoomFactor.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def maximumZoomFactor(self):
        """
		This method is the deleter method for **self.__maximumZoomFactor** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "maximumZoomFactor"))

    @property
    def wheelZoomFactor(self):
        """
		This method is the property for **self.__wheelZoomFactor** attribute.

		:return: self.__wheelZoomFactor. ( Float )
		"""

        return self.__wheelZoomFactor

    @wheelZoomFactor.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def wheelZoomFactor(self, value):
        """
		This method is the setter method for **self.__wheelZoomFactor** attribute.

		:param value: Attribute value. ( Float )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "wheelZoomFactor"))

    @wheelZoomFactor.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def wheelZoomFactor(self):
        """
		This method is the deleter method for **self.__wheelZoomFactor** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "wheelZoomFactor"))

    @property
    def keyZoomFactor(self):
        """
		This method is the property for **self.__keyZoomFactor** attribute.

		:return: self.__keyZoomFactor. ( Float )
		"""

        return self.__keyZoomFactor

    @keyZoomFactor.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def keyZoomFactor(self, value):
        """
		This method is the setter method for **self.__keyZoomFactor** attribute.

		:param value: Attribute value. ( Float )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "keyZoomFactor"))

    @keyZoomFactor.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def keyZoomFactor(self):
        """
		This method is the deleter method for **self.__keyZoomFactor** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "keyZoomFactor"))

    @property
    def graphicsView(self):
        """
		This method is the property for **self.__graphicsView** attribute.

		:return: self.__graphicsView. ( QGraphicsView )
		"""

        return self.__graphicsView

    @graphicsView.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsView(self, value):
        """
		This method is the setter method for **self.__graphicsView** attribute.

		:param value: Attribute value. ( QGraphicsView )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "graphicsView"))

    @graphicsView.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsView(self):
        """
		This method is the deleter method for **self.__graphicsView** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "graphicsView"))

    @property
    def graphicsScene(self):
        """
		This method is the property for **self.__graphicsScene** attribute.

		:return: self.__graphicsScene. ( QGraphicsScene )
		"""

        return self.__graphicsScene

    @graphicsScene.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsScene(self, value):
        """
		This method is the setter method for **self.__graphicsScene** attribute.

		:param value: Attribute value. ( QGraphicsScene )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "graphicsScene"))

    @graphicsScene.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def graphicsScene(self):
        """
		This method is the deleter method for **self.__graphicsScene** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "graphicsScene"))

    @property
    def displayGraphicsItem(self):
        """
		This method is the property for **self.__displayGraphicsItem** attribute.

		:return: self.__displayGraphicsItem. ( QGraphicsItem )
		"""

        return self.__displayGraphicsItem

    @displayGraphicsItem.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def displayGraphicsItem(self, value):
        """
		This method is the setter method for **self.__displayGraphicsItem** attribute.

		:param value: Attribute value. ( QGraphicsItem )
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "displayGraphicsItem"))

    @displayGraphicsItem.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def displayGraphicsItem(self):
        """
		This method is the deleter method for **self.__displayGraphicsItem** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "displayGraphicsItem"))

    #******************************************************************************************************************
    #***	Class methods.
    #******************************************************************************************************************
    def show(self):
        """
		This method reimplements the :meth:`QWidget.show` method.
		"""

        super(ImagesPreviewer, self).show()

        foundations.ui.common.centerWidgetOnScreen(self)

    def closeEvent(self, event):
        """
		This method reimplements the :meth:`QWidget.closeEvent` method.

		:param event: QEvent ( QEvent )
		"""

        LOGGER.debug(
            "> Removing '{0}' from Images Previewers list.".format(self))
        self.__container.imagesPreviewers.remove(self)

        event.accept()

    def wheelEvent(self, event):
        """
		This method reimplements the :meth:`QWidget.wheelEvent` method.

		:param event: QEvent ( QEvent )
		"""

        self.scaleView(pow(1.5, event.delta() / self.__wheelZoomFactor))

    def keyPressEvent(self, event):
        """
		This method reimplements the :meth:`QWidget.keyPressEvent` method.

		:param event: QEvent ( QEvent )
		"""

        key = event.key()
        if key == Qt.Key_Plus:
            self.scaleView(self.__keyZoomFactor)
        elif key == Qt.Key_Minus:
            self.scaleView(1 / self.__keyZoomFactor)
        else:
            super(ImagesPreviewer, self).keyPressEvent(event)

    def __initializeUi(self):
        """
		This method initializes the Widget ui.
		"""

        LOGGER.debug("> Initializing '{0}' ui.".format(
            self.__class__.__name__))

        self.Previous_Image_pushButton.setIcon(
            QIcon(
                os.path.join(self.__uiResourcesDirectory,
                             self.__uiPreviousImage)))
        self.Next_Image_pushButton.setIcon(
            QIcon(os.path.join(self.__uiResourcesDirectory,
                               self.__uiNextImage)))
        self.Zoom_In_pushButton.setIcon(
            QIcon(
                os.path.join(self.__uiResourcesDirectory,
                             self.__uiZoomInImage)))
        self.Zoom_Out_pushButton.setIcon(
            QIcon(
                os.path.join(self.__uiResourcesDirectory,
                             self.__uiZoomOutImage)))
        len(self.__paths) <= 1 and self.Navigation_frame.hide()

        LOGGER.debug("> Initializing graphics View.")
        self.__graphicsView = QGraphicsView()
        self.__graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.__graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.__graphicsView.setTransformationAnchor(
            QGraphicsView.AnchorUnderMouse)
        self.__graphicsView.setDragMode(QGraphicsView.ScrollHandDrag)
        # Reimplementing QGraphicsView wheelEvent method.
        self.__graphicsView.wheelEvent = self.wheelEvent

        LOGGER.debug("> Initializing graphics scene.")
        self.__graphicsScene = QGraphicsScene(self.__graphicsView)
        self.__graphicsScene.setItemIndexMethod(QGraphicsScene.NoIndex)
        self.__graphicsScene.setSceneRect(
            -(float(self.__graphicsSceneWidth)) / 2,
            -(float(self.__graphicsSceneHeight)) / 2,
            float(self.__graphicsSceneWidth),
            float(self.__graphicsSceneHeight))

        self.__graphicsView.setScene(self.__graphicsScene)
        self.__graphicsView.setBackgroundBrush(
            QBrush(self.__graphicsSceneBackgroundColor))

        self.Images_Previewer_frame_gridLayout.addWidget(self.__graphicsView)

        # Signals / Slots.
        self.__container.engine.imagesCaches.QImage.contentAdded.connect(
            self.__engine_imagesCaches_QImage__contentAdded)
        self.Previous_Image_pushButton.clicked.connect(
            self.__Previous_Image_pushButton__clicked)
        self.Next_Image_pushButton.clicked.connect(
            self.__Next_Image_pushButton__clicked)
        self.Zoom_Out_pushButton.clicked.connect(
            self.__Zoom_Out_pushButton__clicked)
        self.Zoom_In_pushButton.clicked.connect(
            self.__Zoom_In_pushButton__clicked)
        self.Zoom_Fit_pushButton.clicked.connect(
            self.__Zoom_Fit_pushButton__clicked)

    def __Images_Informations_label_setUi(self):
        """
		This method sets the **Images_Informations_label** Widget ui.
		"""

        if not self.__displayGraphicsItem:
            return

        image = self.__displayGraphicsItem.image
        self.Images_Informations_label.setText(
            "{0} - {1}x{2} px - {3} bit".format(
                os.path.basename(image.data.path), image.data.width,
                image.data.height, image.data.bpp / 4))

    def __engine_imagesCaches_QImage__contentAdded(self, content):
        """
		This method is triggered by the Application **QImage** images cache when content has been added.

		:param content: Cache added content. ( List )
		"""

        if not self.__paths:
            return

        path = foundations.common.getFirstItem(content)
        if not path in self.__paths:
            return

        image = self.__container.engine.imagesCaches.QImage.getContent(path)
        self.__setDisplayGraphicsItem(image)

    def __Previous_Image_pushButton__clicked(self, checked):
        """
		This method is triggered when **Previous_Image_pushButton** Widget is clicked.

		:param checked: Checked state. ( Boolean )
		"""

        self.loopThroughImages(True)

    def __Next_Image_pushButton__clicked(self, checked):
        """
		This method is triggered when **Next_Image_pushButton** Widget is clicked.

		:param checked: Checked state. ( Boolean )
		"""

        self.loopThroughImages()

    def __Zoom_In_pushButton__clicked(self, checked):
        """
		This method is triggered when **Zoom_In_pushButton** Widget is clicked.

		:param checked: Checked state. ( Boolean )
		"""

        self.scaleView(self.__keyZoomFactor)

    def __Zoom_Out_pushButton__clicked(self, checked):
        """
		This method is triggered when **Zoom_Out_pushButton** Widget is clicked.

		:param checked: Checked state. ( Boolean )
		"""

        self.scaleView(1 / self.__keyZoomFactor)

    def __Zoom_Fit_pushButton__clicked(self, checked):
        """
		This method is triggered when **Zoom_Fit_pushButton** Widget is clicked.

		:param checked: Checked state. ( Boolean )
		"""

        self.fitImage()

    def __clearGraphicsScene(self):
        """
		This method clears the View.
		"""

        for graphicsItem in self.__graphicsScene.items():
            self.__graphicsScene.removeItem(graphicsItem)

    def __setDisplayGraphicsItem(self, image):
        """
		This method sets the View using given image.

		:param image: Image to display. ( Qimage )
		"""

        self.__clearGraphicsScene()

        LOGGER.debug("> Initializing graphics item.")
        self.__displayGraphicsItem = Image_QGraphicsItem(image=image)
        self.__graphicsScene.addItem(self.__displayGraphicsItem)

        self.__Images_Informations_label_setUi()

    def loadImage(self, index=0):
        """
		This method loads the display image in the View.

		:param index: Index to load. ( Integer )
		:return: Method success. ( Boolean )
		"""

        if not self.__paths:
            return False

        image = sibl_gui.ui.common.getImage(self.__paths[index])
        self.__setDisplayGraphicsItem(image)

        return True

    def scaleView(self, scaleFactor):
        """
		This method scales the Previewer view.

		:param scaleFactor: Float ( Float )
		:return: Method success. ( Boolean )
		"""

        graphicsView = self.findChild(QGraphicsView)
        factor = graphicsView.matrix().scale(scaleFactor, scaleFactor).mapRect(
            QRectF(0, 0, 1, 1)).width()
        if factor < self.__minimumZoomFactor or factor > self.__maximumZoomFactor:
            return False

        graphicsView.scale(scaleFactor, scaleFactor)
        return True

    def fitWindow(self):
        """
		This method fits the View window.
		
		:return: Method success. ( Boolean )
		"""

        if not self.__displayGraphicsItem:
            return False

        desktopWidth = QApplication.desktop().screenGeometry(
            QApplication.desktop().primaryScreen()).width()
        desktopHeight = QApplication.desktop().screenGeometry(
            QApplication.desktop().primaryScreen()).height()
        width = min(desktopWidth * 0.80, self.__displayGraphicsItem.width)
        height = min(desktopHeight * 0.80, self.__displayGraphicsItem.height)
        self.resize(width, height)

        foundations.ui.common.centerWidgetOnScreen(self)

        return True

    def fitImage(self):
        """
		This method fits the image to the View.
		
		:return: Method success. ( Boolean )
		"""

        if not self.__displayGraphicsItem:
            return False

        self.__graphicsView.fitInView(
            QRectF(
                -(self.__displayGraphicsItem.width / 2) -
                (self.__displayGraphicsItemMargin / 2),
                -(self.__displayGraphicsItem.height / 2) -
                (self.__displayGraphicsItemMargin / 2),
                self.__displayGraphicsItem.width +
                self.__displayGraphicsItemMargin,
                self.__displayGraphicsItem.height +
                self.__displayGraphicsItemMargin), Qt.KeepAspectRatio)
        return True

    def loopThroughImages(self, backward=False):
        """
		This method loops through View images.

		:param backward: Looping backward. ( Boolean )
		:return: Method success. ( Boolean )
		"""

        index = self.__paths.index(self.__displayGraphicsItem.image.data.path)
        index += not backward and 1 or -1
        if index < 0:
            index = len(self.__paths) - 1
        elif index > len(self.__paths) - 1:
            index = 0
        self.loadImage(index)
        return True