def Paint(self):
        scene = QGraphicsScene()
        scene.setBackgroundBrush(Qt.transparent)
        scene.addLine(5, 5, 5, 213, QPen(self.settings["axis"]))
        scene.addLine(2, 210, 210, 210, QPen(self.settings["axis"]))
        mod_num = int(self.ui.moduleNum.currentText())
        max_sim = max(self.points_sim, key=lambda x: x[mod_num])[mod_num]
        max_mm = max(self.points_mm, key=lambda x: x[mod_num])[mod_num]
        max_time = max(max_mm, max_sim)

        for i in range(10):
            scene.addLine(4, 210 - (i + 1) * 20, 6, 210 - (i + 1) * 20, QPen(self.settings["axis"]))
            font = QFont()
            font.setPointSize(6)
            if int(0.1*max_time*(i + 1)) != 0:
                t2 = scene.addText(str(int(0.1*max_time*(i + 1))), font)
                t2.setPos(-18, 200 - (i + 1) * 20)

        i = 1
        x0 = 5 + 200 / self.num
        y0 = 210 - float(self.points_mm[0][mod_num]) / max_time * 200
        for p in self.points_mm:
            x = 5 + i * 200 / self.num
            y = 210 - float(p[mod_num])/max_time * 200
            scene.addLine(x0, y0, x, y, QPen(self.settings["mm"]))
            scene.addLine(x - 2, y - 2, x + 2, y + 2, QPen(self.settings["mm"]))
            scene.addLine(x + 2, y - 2, x - 2, y + 2, QPen(self.settings["mm"]))
            x0 = x
            y0 = y
            i += 1
        i = 1
        x0 = 5 + 200 / self.num
        y0 = 210 - float(self.points_sim[0][mod_num]) / max_time * 200
        for p in self.points_sim:
            x = 5 + i * 200 / self.num
            y = 210 - float(p[mod_num])/max_time * 200
            scene.addLine(x0, y0, x, y, QPen(self.settings["sim"]))
            scene.addLine(x - 2, y - 2, x + 2, y + 2, QPen(self.settings["sim"]))
            scene.addLine(x + 2, y - 2, x - 2, y + 2, QPen(self.settings["sim"]))
            x0 = x
            y0 = y
            i += 1
        self.ui.graph.setScene(scene)

        self.ui.table.setRowCount(len(self.simplesystems))
        self.simplesystems.sort(key = lambda x: x.simrel)
        for i in range(len(self.simplesystems)):
            self.ui.table.setItem(i, 0, QTableWidgetItem(self.simplesystems[i].id))
        self.simplesystems.sort(key = lambda x: x.mmrel)
        for i in range(len(self.simplesystems)):
            self.ui.table.setItem(i, 1, QTableWidgetItem(self.simplesystems[i].id))
            if self.ui.table.item(i, 0).text() != self.ui.table.item(i, 1).text():
                self.ui.table.item(i, 0).setForeground(QBrush(QColor(255,0,0)))
                self.ui.table.item(i, 1).setForeground(QBrush(QColor(255,0,0)))
            else:
                self.ui.table.item(i, 0).setForeground(QBrush(QColor(0,255,0)))
                self.ui.table.item(i, 1).setForeground(QBrush(QColor(0,255,0)))
        self.simplesystems.sort(key = lambda x: x.rel)
        for i in range(len(self.simplesystems)):
            self.ui.table.setItem(i, 2, QTableWidgetItem(self.simplesystems[i].id))
Beispiel #2
0
class Level(QFrame):
    def __init__(self, parent):
        QFrame.__init__(self,parent)

        self.filename = QString()
        self.copiedItem = QByteArray()
        self.pasteOffset = 5
        self.prevPoint = QPoint()
        self.addOffset = 5
        
        self.screenSize = (320, 240)
        self.bgColor = QColor(244,244,244)
        '''0.Portrait 1.Landscape'''
        self.orientation = 0
        self.currentItem = None
        

        self.printer = QPrinter(QPrinter.HighResolution)
        self.printer.setPageSize(QPrinter.Letter)


        '''1.Header'''
        self.levelBar = LevelBar(self)
        
        '''3.Tiler'''
        self.tiler = TileMapGrid(self)#Tiler(self)
        self.tiler.setMinimumHeight(100)
        #self.tiler.currentChanged.connect(self.closeDesigner)
        #self.tiler.setTabsClosable(True)
        #self.tiler.setTabShape(0)
        #self.tiler.hide()
        #self.levelLayout.addWidget(self.levelBar) 
        
        '''2.view'''
        viewLayoutWidget = QFrame()
        viewLayoutWidget.setFrameShape(QFrame.StyledPanel)
        viewLayout = QHBoxLayout(viewLayoutWidget)
        #viewLayout.setMargin(10)
        self.view = LevelView(viewLayoutWidget)
        '''scene'''
        self.scene = QGraphicsScene(self)
        #self.scene.selectionChanged.connect(self.setConnect)
        #self.view.setStyleSheet("border: 1px solid red;")
        
        self.setBackgroundColor(self.bgColor)
        self.setScreenSize(self.screenSize)
        
        self.view.setScene(self.scene)
        self.view.setAlignment(Qt.AlignCenter)
        self.scroll_off = 1
        self.setScrollBar()
        
        viewLayout.setMargin(0)
        viewLayout.addWidget(self.view)

        self.wrapped = [] # Needed to keep wrappers alive
        layout = QVBoxLayout(self)
        layout.addWidget(self.levelBar)
        layout.addWidget(viewLayoutWidget)
        layout.addWidget(self.tiler)
        layout.setMargin(0)
        self.setLayout(layout)
        
    def setScrollBar(self):
        if(self.scroll_off):
            self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.scroll_off = 0
        else:
            self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            self.scroll_off = 1
        
    def setBackgroundColor(self,color):
        self.bgColor = color
        self.scene.setBackgroundBrush(QBrush(color))
        
    def setScreenSize(self,size):
        self.screenSize = size
        self.setOrientation(self.orientation)
        
    def setOrientation(self,idx):
        self.orientation = idx
        if(idx == 0):
            self.view.setMaximumSize(self.screenSize[1], self.screenSize[0])
            self.scene.setSceneRect(0, 0, self.screenSize[1], self.screenSize[0])
        else:
            self.view.setMaximumSize(self.screenSize[0], self.screenSize[1])
            self.scene.setSceneRect(0, 0, self.screenSize[0], self.screenSize[1])
        
    def offerSave(self):
        if (Dirty and QMessageBox.question(self,
                            "Designer - Unsaved Changes",
                            "Save unsaved changes?",
                            QMessageBox.Yes|QMessageBox.No) == 
           QMessageBox.Yes):
            self.save()


    def position(self):
        point = self.mapFromGlobal(QCursor.pos())
        if not self.view.geometry().contains(point):
            coord = random.randint(36, 144)
            point = QPoint(coord, coord)
        else:
            if point == self.prevPoint:
                point += QPoint(self.addOffset, self.addOffset)
                self.addOffset += 5
            else:
                self.addOffset = 5
                self.prevPoint = point
        return self.view.mapToScene(point)
    
    def selectedItem(self):
        items = self.scene.selectedItems()
        if len(items) == 1:
            return items[0]
        return None
    
    def current(self,item):
        self.scene.clearSelection()
        sceneItems = self.scene.items()
        for items in sceneItems:
            if(items != item):
                item.setSelected(False)
                if(item.isConnected()):
                    self.propertyBar.disconnectText(item)
                    item.setConnected(False)
        self.currentItem = item
        self.currentItem.setConnected(True)
        self.currentItem.setSelected(True)
        self.propertyBar.connectText(self.currentItem)
        self.propertyBar.initText(self.currentItem)


    def addText(self):
        item = TextItem("SomeText", self.position())
        self.connect(item, SIGNAL("current"),self.current)
        self.connect(item, SIGNAL("copy"),self.copy)
        self.connect(item, SIGNAL("cut"),self.cut)
        self.connect(item, SIGNAL("paste"),self.paste)
        self.connect(item, SIGNAL("delete"),self.delete)
        #self.current(item)
        self.scene.addItem(item)
        

    def copy(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copiedItem.clear()
        self.pasteOffset = 5
        stream = QDataStream(self.copiedItem, QIODevice.WriteOnly)
        self.writeItemToStream(stream, item)


    def cut(self):
        item = self.selectedItem()
        if item is None:
            return
        self.copy()
        self.scene.removeItem(item)
        del item


    def paste(self):
        if self.copiedItem.isEmpty():
            return
        stream = QDataStream(self.copiedItem, QIODevice.ReadOnly)
        item = self.readItemFromStream(stream, self.pasteOffset)
        self.pasteOffset += 5
        #self.scene.addItem(item)
        
    def delete(self):
        items = self.scene.selectedItems()
        if (len(items) and QMessageBox.question(self,
                "Designer - Delete",
                "Delete {0} item{1}?".format(len(items),
                "s" if len(items) != 1 else ""),
                QMessageBox.Yes|QMessageBox.No) ==
                QMessageBox.Yes):
            while items:
                item = items.pop()
                self.scene.removeItem(item)
                del item
                
    def readItemFromStream(self, stream, offset=0):
        type = QString()
        position = QPointF()
        matrix = QMatrix()
        stream >> type >> position >> matrix
        if offset:
            position += QPointF(offset, offset)
        if type == "Text":
            text = QString()
            font = QFont()
            stream >> text >> font
            self.scene.addItem(TextItem(text, position, font, matrix))
        elif type == "Box":
            rect = QRectF()
            stream >> rect
            style = Qt.PenStyle(stream.readInt16())
            self.scene.addItem(BoxItem(position, style, matrix))
        elif type == "Pixmap":
            pixmap = QPixmap()
            stream >> pixmap
            self.scene.addItem(self.createPixmapItem(pixmap, position, matrix))


    def writeItemToStream(self, stream, item):
        if isinstance(item, QGraphicsTextItem):
            stream << QString("Text") << item.pos() \
                   << item.matrix() << item.toPlainText() << item.font()
        elif isinstance(item, QGraphicsPixmapItem):
            stream << QString("Pixmap") << item.pos() \
                   << item.matrix() << item.pixmap()
        elif isinstance(item, BoxItem):
            stream << QString("Box") << item.pos() \
                   << item.matrix() << item.rect
            stream.writeInt16(item.style)

    def rotate(self):
        for item in self.scene.selectedItems():
            item.rotate(30)


    def print_(self):
        dialog = QPrintDialog(self.printer)
        if dialog.exec_():
            painter = QPainter(self.printer)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setRenderHint(QPainter.TextAntialiasing)
            self.scene.clearSelection()
            #self.removeBorders()
            self.scene.render(painter)
            #self.addBorders()


    def open(self):
        self.offerSave()
        path = (QFileInfo(self.filename).path()
                if not self.filename.isEmpty() else ".")
        fname = QFileDialog.getOpenFileName(self,
                "Page Designer - Open", path,
                "Page Designer Files (*.pgd)")
        if fname.isEmpty():
            return
        self.filename = fname
        fh = None
        try:
            fh = QFile(self.filename)
            if not fh.open(QIODevice.ReadOnly):
                raise IOError, unicode(fh.errorString())
            items = self.scene.items()
            while items:
                item = items.pop()
                self.scene.removeItem(item)
                del item
            self.addBorders()
            stream = QDataStream(fh)
            stream.setVersion(QDataStream.Qt_4_2)
            magic = stream.readInt32()
            if magic != MagicNumber:
                raise IOError, "not a valid .pgd file"
            fileVersion = stream.readInt16()
            if fileVersion != FileVersion:
                raise IOError, "unrecognised .pgd file version"
            while not fh.atEnd():
                self.readItemFromStream(stream)
        except IOError, e:
            QMessageBox.warning(self, "Page Designer -- Open Error",
                    "Failed to open {0}: {1}".format(self.filename, e))
        finally:
Beispiel #3
0
class SelectByColorDlg(QDialog):
    def __init__(self, color, pieceItems):
        super().__init__()
        self._color = color
        self.resize(800, 800)

        self.scene = QGraphicsScene()
        layout = QVBoxLayout(self)
        self.view = _MyView(self)
        layout.addWidget(self.view)
        self.view.setScene(self.scene)
        self._view_widget = QGLWidget()
        self.view.setViewport(self._view_widget)
        self.view.setMouseTracking(True)

        gry = sum(color) / 3.0
        if (gry < 168):
            bg = [224,]*3
        else:
            bg = [128,]*3
        self.scene.setBackgroundBrush(QBrush(QColor(*bg)))

        self.setup_scene(self.scene, pieceItems)
        d = self.piece_diag
        self.view.scale(60./d, 60./d)

        self._hover_radius = 1.0
        self.selected_item_ids = []

    def setup_scene(self, scene, pieceItems):
        root = self._rootitem = _RootItem(self._color)
        scene.addItem(root)
        # order piece items by color distance of the most similar color
        pairs = [(self._distance(item), item) for item in pieceItems]
        pairs.sort(key = lambda pair: pair[0])

        phi_increment = 0.61803398874 * 2 * pi
        phi = 0.0

        gamma = 1.0
        # scale distance relative to average piece size
        if pairs:
            rect = pairs[0][1].boundingRect()
            diag = (rect.width()**2 + rect.height()**2) ** 0.5
            # take the median piece
            idx = len(pairs) // 2
            meddist = pairs[idx][0]
            meddist = max(meddist, .1)
            scale = 6*diag/(meddist) ** gamma
            self.piece_diag = diag
        else:
            scale = 1.0
            self.piece_diag = 1.0

        self.dist_and_id = []
        for distance, orig_item in pairs:
            item = orig_item.copy_to(root, rotate=False)
            rr = item.boundingRect()
            item.setTransformOriginPoint(rr.center())
            item.setRotation(item.angle_deg)


            item.setPos(
                scale * distance**gamma * cos(phi)-rr.width()*0.5,
                scale * distance**gamma * sin(phi)-rr.height()*0.5
            )
            self.dist_and_id.append((scale*distance**gamma, item.id))
            phi += phi_increment
        self.updateSceneRect()

    def set_hover_radius(self, r):
        self._hover_radius = r
        self.selected_item_ids = [pair[1] for pair in self.dist_and_id if pair[0] < r]
        self._rootitem.sel_size = r
        self._rootitem.update()

    def confirm_result(self):
        self.accept()

    def _distance(self, pieceItem):
        color = self._color
        def dst(c1, c2):
            c1 = rgb2Lab(c1)
            c2 = rgb2Lab(c2)
            return sum((c1i-c2i)**2 for c1i, c2i in zip(c1, c2)) ** 0.5
        if not pieceItem.dominant_colors:
            return 255.0
        return min(dst(color, piececolor) for piececolor in pieceItem.dominant_colors[:4])

    def updateSceneRect(self):
        r = self.scene.itemsBoundingRect()
        w, h = r.width(), r.height()
        a = .05
        r = r.adjusted(-w*a, -h*a, w*a, h*a)
        self.scene.setSceneRect(r)
Beispiel #4
0
class ConductorGraph(Plugin):

    _deferred_fit_in_view=Signal()
    _client_list_update_signal=Signal()
    
    def __init__(self, context):
        self._context=context
        super(ConductorGraph, self).__init__(context)
        self.initialised=False
        self.setObjectName('Conductor Graph')
        self._current_dotcode=None
        self._node_items=None
        self._edge_items=None
        self._node_item_events={}
        self._edge_item_events={}
        self._client_info_list={}
        self._widget=QWidget()
        self.cur_selected_client_name = ""
        self.pre_selected_client_name = ""
            
        # factory builds generic dotcode items
        self.dotcode_factory=PydotFactory()
        # self.dotcode_factory=PygraphvizFactory()
        self.dotcode_generator=RosGraphDotcodeGenerator()
        self.dot_to_qt=DotToQtGenerator()
        
        self._graph=ConductorGraphInfo()
        self._graph._reg_event_callback(self._update_client_list)
        self._graph._reg_period_callback(self._set_network_statisics)
        
        rospack=rospkg.RosPack()
        ui_file=os.path.join(rospack.get_path('concert_conductor_graph'), 'ui', 'conductor_graph.ui')
        loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('ConductorGraphUi')

        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))

        self._scene=QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        #self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh'))
        self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('window-new'))
        self._widget.refresh_graph_push_button.pressed.connect(self._update_conductor_graph)

        self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()
        
        self._widget.tabWidget.currentChanged.connect(self._change_client_tab)
        self._client_list_update_signal.connect(self._update_conductor_graph)
        
        #rospy.Subscriber(concert_msgs.Strings.CONCERT_CLIENT_CHANGES, ConcertClients, self._update_client_list)
        
        context.add_widget(self._widget)
    
    def restore_settings(self, plugin_settings, instance_settings):
        self.initialised=True
        self._refresh_rosgraph()
    def shutdown_plugin(self):
        pass
    
    def _update_conductor_graph(self):
        # re-enable controls customizing fetched ROS graph

        self._refresh_rosgraph()
        self._update_client_tab()

    def _refresh_rosgraph(self):
        if not self.initialised:
            return
        self._update_graph_view(self._generate_dotcode())
        
    def _generate_dotcode(self):
        return self.dotcode_generator.generate_dotcode(rosgraphinst=self._graph,
                                                       dotcode_factory=self.dotcode_factory,
                                                       orientation='LR'
                                                       )
    def _update_graph_view(self, dotcode): 
        #if dotcode==self._current_dotcode:
        #    return
        self._current_dotcode=dotcode
        self._redraw_graph_view()
   
    def _update_client_list(self):
        print "[conductor graph]: _update_client_list"       
        self._client_list_update_signal.emit()
        pass
    
    def _start_service(self,node_name,service_name):
        
        service=self._graph._client_info_list[node_name]['gateway_name']+"/"+service_name  
        info_text='' 
        
        if service_name=='status':
            service_handle=rospy.ServiceProxy(service, Status)
            call_result=service_handle()
            
            info_text="<html>"
            info_text +="<p>-------------------------------------------</p>"
            info_text +="<p><b>application_namespace: </b>" +call_result.application_namespace+"</p>"
            info_text +="<p><b>remote_controller: </b>" +call_result.remote_controller+"</p>"
            info_text +="<p><b>application_status: </b>" +call_result.application_status+"</p>"
            info_text +="</html>"
            self._client_list_update_signal.emit()

        elif service_name=='platform_info':
            service_handle=rospy.ServiceProxy(service, GetPlatformInfo)
            call_result=service_handle()

            info_text = "<html>"
            info_text += "<p>-------------------------------------------</p>"
            info_text += "<p><b>rocon_uri: </b>" + call_result.platform_info.uri + "</p>"
            info_text += "<p><b>concert_version: </b>" + call_result.platform_info.version + "</p>"
            info_text += "</html>"
            self._client_list_update_signal.emit()
            
        elif service_name=='invite':
            #sesrvice
            service_handle=rospy.ServiceProxy(service, Invite) 
            #dialog
            dlg=QDialog(self._widget) 
            dlg.setMinimumSize(400,0)
            dlg.setMaximumSize(400,0)
            dlg.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding)
            #dialog layout
            ver_layout=QVBoxLayout(dlg)           
            ver_layout.setContentsMargins (0,0,0,0)

            dynamic_arg=[]
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Remote Target Name',False,[('remote_target_name','string')]))
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Application Namespace',False,[('application_namespace','string')]))
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Cancel',False,[('cancel','bool')]))
            #button
            button_hor_sub_widget=QWidget()
            button_hor_layout=QHBoxLayout(button_hor_sub_widget)   
                   
            btn_call=QPushButton("Call")
            btn_cancel=QPushButton("cancel")
            
            btn_call.clicked.connect(lambda: dlg.done(0))
            btn_call.clicked.connect(lambda : self._call_invite_service(service,service_handle,dynamic_arg))

            btn_cancel.clicked.connect(lambda: dlg.done(0))
            #add button
            button_hor_layout.addWidget(btn_call)            
            button_hor_layout.addWidget(btn_cancel)
            #add button layout            
            ver_layout.addWidget(button_hor_sub_widget)

            dlg.setVisible(True)        

        elif service_name=='start_app':
            #sesrvice
            service_handle=rospy.ServiceProxy(service, StartApp) 
            #dialog
            dlg=QDialog(self._widget) 
            dlg.setMinimumSize(400,0)
            dlg.setMaximumSize(400,0)
            dlg.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding)
            #dialog layout
            ver_layout=QVBoxLayout(dlg)           
            ver_layout.setContentsMargins (0,0,0,0)

            dynamic_arg=[]
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Name',False,[('name','string')]))
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Remappings',True,[('remap to','string'),('remap from','string')]))
            #button
            button_hor_sub_widget=QWidget()
            button_hor_layout=QHBoxLayout(button_hor_sub_widget)   
                   
            btn_call=QPushButton("Call")
            btn_cancel=QPushButton("cancel")
            
            btn_call.clicked.connect(lambda: dlg.done(0))
            btn_call.clicked.connect(lambda : self._call_start_app_service(service,service_handle,dynamic_arg))
            
            btn_cancel.clicked.connect(lambda: dlg.done(0))
            #add button
            button_hor_layout.addWidget(btn_call)            
            button_hor_layout.addWidget(btn_cancel)
            #add button layout            
            ver_layout.addWidget(button_hor_sub_widget)

            dlg.setVisible(True)        

        elif service_name=='stop_app':
            service_handle=rospy.ServiceProxy(service, StopApp)
            call_result=service_handle()

            info_text="<html>"
            info_text +="<p>-------------------------------------------</p>"
            info_text +="<p><b>stopped: </b>" +str(call_result.stopped)+"</p>"
            info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>"
            info_text +="<p><b>message: </b>" +call_result.message+"</p>"
            info_text +="</html>"

            self._update_client_tab()
        else:
            print 'has no service'
            return
        
        # display the result of calling service  
        # get tab widget handle
        service_text_widget=None
        cur_tab_widget=self._widget.tabWidget.currentWidget()        
        
        if cur_tab_widget==None:
            return
            
        object_name='services_text_widget'
        for k in cur_tab_widget.children():
            if k.objectName().count(object_name) >=1 :
                service_text_widget=k
                break
        if service_text_widget==None:
            return
            
        service_text_widget.clear()
        service_text_widget.appendHtml(info_text)

    def _call_invite_service(self,service,service_handle,dynamic_arg):        
        remote_target_name=""
        application_namespace=""
        cancel=False

        for k in dynamic_arg:
            if k.name=='Remote Target Name':
                item_widget=k._get_param_list()[0][0][1]
                remote_target_name=item_widget.toPlainText()
            
            elif k.name=='Application Namespace':
                item_widgetwidget=k._get_param_list()[0][0][1]
                application_namespace=item_widget.toPlainText()
            
            elif k.name=='Cancel':
                item_widget=k._get_param_list()[0][0][1]    
                cancel=item_widget.itemData(item_widget.currentIndex())
        #calling service
        call_result=service_handle(remote_target_name,application_namespace,cancel)
        #status update
        self._client_list_update_signal.emit()
        # display the result of calling service  

        info_text="<html>"
        info_text +="<p>-------------------------------------------</p>"
        info_text +="<p><b>result: </b>" +str(call_result.result)+"</p>"
        info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>"
        info_text +="<p><b>message: </b>" +call_result.message+"</p>"
        info_text +="</html>"        
        # get tab widget handle
        service_text_widget=None
        cur_tab_widget=self._widget.tabWidget.currentWidget()        
        if cur_tab_widget==None:
            return

        object_name='services_text_widget'
        for k in cur_tab_widget.children():
            if k.objectName().count(object_name) >=1 :
                service_text_widget=k
                break
        if service_text_widget==None:
            return
            
        service_text_widget.clear()
        service_text_widget.appendHtml(info_text)

        pass
    
    def _call_start_app_service(self,service,service_handle,dynamic_arg):
        name=""
        remappings=[]
        for k in dynamic_arg:
            if k.name=='Name':
                name=k._get_param_list()[0][0][1].toPlainText()
            elif k.name=='Remappings':    
                for l in k._get_param_list():
                    remap_to=l[0][1].toPlainText()
                    remap_from=l[1][1].toPlainText()
                    remappings.append(Remapping(remap_to,remap_from))
        #calling service
        call_result=service_handle(name,remappings)
        #status update
        self._client_list_update_signal.emit()

        # display the result of calling service          
        info_text = ''
        info_text="<html>"
        info_text +="<p>-------------------------------------------</p>"
        info_text +="<p><b>started: </b>" +str(call_result.started)+"</p>"
        info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>"
        info_text +="<p><b>message: </b>" +call_result.message+"</p>"
        info_text +="<p><b>app_namespace: </b>" +call_result.app_namespace+"</p>"
        info_text +="</html>"
        # get tab widget handle
        service_text_widget=None
        cur_tab_widget=self._widget.tabWidget.currentWidget()        
        if cur_tab_widget==None:
            return
        object_name='services_text_widget'
        for k in cur_tab_widget.children():
            if k.objectName().count(object_name) >=1 :
                service_text_widget=k
                break
        if service_text_widget==None:
            return
            
        service_text_widget.clear()
        service_text_widget.appendHtml(info_text)

        pass

    def _update_client_tab(self):
        print '[_update_client_tab]'
        self.pre_selected_client_name = self.cur_selected_client_name
        self._widget.tabWidget.clear()   
        
        for k in self._graph._client_info_list.values(): 
            main_widget=QWidget()
           
            ver_layout=QVBoxLayout(main_widget)
           
            ver_layout.setContentsMargins (9,9,9,9)
            ver_layout.setSizeConstraint (ver_layout.SetDefaultConstraint)
            
            #button layout
            sub_widget=QWidget()
            sub_widget.setAccessibleName('sub_widget')
            btn_grid_layout=QGridLayout(sub_widget)

            btn_grid_layout.setContentsMargins (9,9,9,9)

            btn_grid_layout.setColumnStretch (1, 0)
            btn_grid_layout.setRowStretch (2, 0)

            invite_btn=QPushButton("Invite")
            platform_info_btn=QPushButton("Get Platform Info")
            status_btn=QPushButton("Get Status")
            start_app_btn=QPushButton("Start App")
            stop_app_btn=QPushButton("Stop App")              

            invite_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"invite"))
            platform_info_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"platform_info"))  
            status_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"status"))  
            start_app_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"start_app"))  
            stop_app_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"stop_app"))
                    
            btn_grid_layout.addWidget(invite_btn)
            btn_grid_layout.addWidget(platform_info_btn)
            btn_grid_layout.addWidget(status_btn)
            btn_grid_layout.addWidget(start_app_btn)
            btn_grid_layout.addWidget(stop_app_btn)             
            ver_layout.addWidget(sub_widget)            

            #client information layout
            context_label = QLabel()
            context_label.setText("Client information")
            ver_layout.addWidget(context_label)
            
            app_context_widget=QPlainTextEdit()
            app_context_widget.setObjectName(k["name"]+'_'+'app_context_widget')
            app_context_widget.setAccessibleName('app_context_widget')
            app_context_widget.appendHtml(k["app_context"])
            app_context_widget.setReadOnly(True) 
            
            cursor = app_context_widget.textCursor()
            cursor.movePosition(QTextCursor.Start,QTextCursor.MoveAnchor,0)
            app_context_widget.setTextCursor(cursor)
            ver_layout.addWidget(app_context_widget)
            
            #service layout
            context_label = QLabel()
            context_label.setText("Service result")
            ver_layout.addWidget(context_label)
            
            services_text_widget=QPlainTextEdit()
            services_text_widget.setObjectName(k["name"]+'_'+'services_text_widget')
            services_text_widget.setReadOnly(True) 
            cursor = services_text_widget.textCursor()
            cursor.movePosition(QTextCursor.Start,QTextCursor.MoveAnchor,0)
            services_text_widget.setTextCursor(cursor)            
            ver_layout.addWidget(services_text_widget)
            
            # new icon
            path=""
            if k["is_new"]==True:
                path=os.path.join(os.path.dirname(os.path.abspath(__file__)),"../../resources/images/new.gif")            

            #add tab
            self._widget.tabWidget.addTab(main_widget,QIcon(path), k["name"]);

        #set previous selected tab
        for k in range(self._widget.tabWidget.count()):
            tab_text=self._widget.tabWidget.tabText(k)
            if tab_text == self.pre_selected_client_name:
                self._widget.tabWidget.setCurrentIndex(k)

    def _change_client_tab(self,index):
        self.cur_selected_client_name = self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex())
        if self._widget.tabWidget.widget(index) !=None:
            for k in  self._widget.tabWidget.widget(index).children():
                if k.objectName().count("services_text_widget"):
                    k.clear()
        pass    
        
    def _set_network_statisics(self):
        if self._edge_items == None:
            return
        else:
            for edge_items in self._edge_items.itervalues():
                for edge_item in edge_items:
                     edge_dst_name=edge_item.to_node._label.text()
                     edge_item.setToolTip(str(self._graph._client_info_list[edge_dst_name]['conn_stats']))
                     
    def _redraw_graph_view(self):
        self._scene.clear()
        self._node_item_events={}
        self._edge_item_events={}
        self._node_items=None
        self._edge_items=None

        if self._widget.highlight_connections_check_box.isChecked():
            highlight_level=3
        else:
            highlight_level=1
            
        highlight_level=3 if self._widget.highlight_connections_check_box.isChecked() else 1

        # layout graph and create qt items
        (nodes, edges)=self.dot_to_qt.dotcode_to_qt_items(self._current_dotcode,
                                                            highlight_level=highlight_level,
                                                            same_label_siblings=True)
        self._node_items=nodes
        self._edge_items=edges

        # if we wish to make special nodes, do that here (maybe subclass GraphItem, just like NodeItem does)
        #node
        for node_item in nodes.itervalues():
            # set the color of conductor to orange           
            if node_item._label.text()==self._graph._concert_conductor_name:
                royal_blue=QColor(65, 105, 255)
                node_item._default_color=royal_blue
                node_item.set_color(royal_blue)

            # redefine mouse event
            self._node_item_events[node_item._label.text()]=GraphEventHandler(self._widget.tabWidget,node_item,node_item.mouseDoubleClickEvent);
            node_item.mouseDoubleClickEvent=self._node_item_events[node_item._label.text()].NodeEvent;
            
            self._scene.addItem(node_item)
            
        #edge
        for edge_items in edges.itervalues():
            for edge_item in edge_items:
                #redefine the edge hover event
                
                self._edge_item_events[edge_item._label.text()]=GraphEventHandler(self._widget.tabWidget,edge_item,edge_item._label.hoverEnterEvent);
                edge_item._label.hoverEnterEvent =self._edge_item_events[edge_item._label.text()].EdgeEvent;
                
                #self._edge_item_events[edge_item._label.text()]=GraphEventHandler(self._widget.tabWidget,edge_item,edge_item.mouseDoubleClickEvent);
                #edge_item.mouseDoubleClickEvent=self._edge_item_events[edge_item._label.text()].EdgeEvent;

                edge_item.add_to_scene(self._scene)

                #set the color of node as connection strength one of red, yellow, green
                edge_dst_name=edge_item.to_node._label.text()
                if edge_dst_name in self._graph._client_info_list.keys():
                  connection_strength=self._graph._client_info_list[edge_dst_name]['connection_strength']
                  if connection_strength=='very_strong':
                      green=QColor(0, 255, 0)
                      edge_item._default_color=green
                      edge_item.set_color(green)

                  elif connection_strength=='strong':
                      green_yellow=QColor(125, 255,0)
                      edge_item._default_color=green_yellow
                      edge_item.set_color(green_yellow)
                        
                  elif connection_strength=='normal':
                      yellow=QColor(238, 238,0)
                      edge_item._default_color=yellow
                      edge_item.set_color(yellow)

                  elif connection_strength=='weak':
                      yellow_red=QColor(255, 125,0)
                      edge_item._default_color=yellow_red
                      edge_item.set_color(yellow_red)
                      
                  elif connection_strength=='very_weak':
                      red=QColor(255, 0,0)
                      edge_item._default_color=red
                      edge_item.set_color(red)
                #set the tooltip about network information
                edge_item.setToolTip(str(self._graph._client_info_list[edge_dst_name]['conn_stats']))    

        self._scene.setSceneRect(self._scene.itemsBoundingRect())
  
        if self._widget.auto_fit_graph_check_box.isChecked():
            self._fit_in_view()

    def _fit_in_view(self):
        self._widget.graphics_view.fitInView(self._scene.itemsBoundingRect(), Qt.KeepAspectRatio)
Beispiel #5
0
class TreeDialog(QDialog):
    def __init__(self):
        import treedialog
        QDialog.__init__(self)
        self.ui = treedialog.Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.draw_buton.clicked.connect(self.new_anim)
        self.scene = QGraphicsScene()
        self.ui.image.setScene(self.scene)
        self.ui.image.setRenderHints(QPainter.HighQualityAntialiasing)

    def get_params(self):
        params = dict()
        params["branch_split"] = self.ui.branch_split.value()
        params["branch_after_range"] = (self.ui.branch_after_min.value(), self.ui.branch_after_max.value())
        params["branch_split_var"] = self.ui.branch_split_var.value()
        params["gravity"] = self.ui.gravity.value()
        params["down_die_probability"] = self.ui.down_die_probability.value()
        params["down_damping_x"] = self.ui.down_damping_x.value()
        params["down_damping_y"] = self.ui.down_damping_x.value()
        params["start_branches"] = self.ui.start_branches.value()
        params["keep_central"] = self.ui.keep_central.value()
        params["color"] = QColor(self.ui.r.value() * 255, self.ui.g.value() * 255, self.ui.b.value() * 255)
        params["color_speed"] = self.ui.color_speed.value()
        params["painter_thickness"] = self.ui.painter_thickness.value()
        params["painter_generations"] = self.ui.painter_generations.value()
        start_rand = [random.uniform(-1, 1) * self.ui.v_start_var.value() for i in range(2)]
        params["v_start"] = complex(self.ui.v_start_x.value()+start_rand[0], self.ui.v_start_y.value()+start_rand[1])
        return params

    def new_anim(self):
        image = None
        painter_id = random.randint(0, 2**32)
        self.active_painer = painter_id
        index = 0
        every = self.ui.repaint.value()

        self.scene.clear()

        tree_count = self.ui.tree_count.value()
        need_spacing = 65
        used_locations = []
        for tree_index in range(tree_count):
            z_range = 80
            base_z = random.uniform(-z_range, z_range)

            def make_base():
                return complex(10 + random.uniform(-350 + 150*tree_count, 350 + 150*tree_count), base_z)
            def closest_distance_to_used(base):
                return min([np.abs(np.real(base - item)) for item in used_locations])
            base_location = make_base()
            while not len(used_locations) == 0 and closest_distance_to_used(base_location) < need_spacing:
                base_location = make_base()

            used_locations.append(base_location)
            scale = 1.0 + 0.75 * ((z_range - base_z) / (2*z_range)) ** 2
            self.tree = Tree(self.get_params(), base_location=base_location, scale=scale)
            for iteration in self.tree.grow_iterations(self.ui.generations.value(), yield_every=every):
                self.tree.draw(self.scene, incremental=True)
                self.ui.progress.setText("Working ... displayed frame: {0}".format(index))

                gradient = QLinearGradient(self.scene.itemsBoundingRect().topLeft(),
                                           self.scene.itemsBoundingRect().bottomLeft())
                gradient.setColorAt(0.4, QColor(0, 0, 0))
                gradient.setColorAt(0, QColor(25, 25, 25))
                self.scene.setBackgroundBrush(QBrush(gradient))

                self.ui.image.repaint()
                QApplication.processEvents()
                index += every
                if self.active_painer != painter_id:
                    return

        self.ui.image.fitInView(self.scene.itemsBoundingRect(), 1)
        d = GrassDrawer(self.ui.image)
        d.draw_some_grass(150 + 75*tree_count)
        #self.ui.image.fitInView(self.scene.itemsBoundingRect(), 1)
        self.ui.progress.setText("Done. Displayed frame: {0}".format(index))
Beispiel #6
0
class View(QGraphicsView):
    
    TEXT_COLOR = QColor(1,1,1)
    BOLDISH = QFont("Times", 30, QFont.Bold)
    NORMALISH = QFont("Times", 30, QFont.Normal)
    
    def __init__(self):
        QGraphicsView.__init__(self)
        self.resize(1024, 768) 
        self.qtscene = None
        self.references = []
    
    def display_question(self, question, answers, selected_index = None, correct = None):
        self._init_scene()
        x = 50
        y = 25
        item =  QGraphicsSimpleTextItem(question)
        item.setBrush(self.TEXT_COLOR)
        item.setFont(self.BOLDISH) 
        item.setX(x)
        item.setY(y)
        self.qtscene.addItem(item)
        self.references.append(item)
        y += 75
        
        for index, answer in enumerate(answers):
            index += 1
            item =  QGraphicsSimpleTextItem("%s) %s" % (index, answer))
            item.setBrush(self.TEXT_COLOR)
            item.setFont(self.NORMALISH) 
            item.setX(x)
            item.setY(y)
            item.setAcceptHoverEvents(True)
            self.qtscene.addItem(item)
            self.references.append(item)
            #TODO: do not register click but do show check or not
            if not selected_index:
                item.hoverEnterEvent = partial(self.on_hover_answer, item) 
                item.hoverLeaveEvent = partial(self.on_unhover_answer, item) 
                item.mousePressEvent = partial(self.on_click_answer, index) 
            elif selected_index == index:
                if correct:
                    item =  QGraphicsSimpleTextItem(u"\u2713")
                    item.setBrush(QBrush(QColor(0,150,0)))
                    item.setX(0)
                else:
                    item =  QGraphicsSimpleTextItem("X")
                    item.setBrush(QBrush(QColor(255,0,0)))
                    item.setX(3)
                item.setFont(self.BOLDISH)
                item.setY(y)
                self.qtscene.addItem(item)
                self.references.append(item)
                
            y += 50
        return x, y
    
    def display_answer(self, question, answers, correct_answer, description, selected_index, correct):
        x, y = self.display_question(question, answers, selected_index, correct) #TODO pass what to check and if right or wrong
        y += 50
        item =  QGraphicsSimpleTextItem("Correct Answer: %s" % correct_answer)
        item.setBrush(self.TEXT_COLOR)
        font = QFont(self.BOLDISH)
        font.setUnderline(True)
        item.setFont(font) 
        item.setX(x)
        item.setY(y)
        self.qtscene.addItem(item)
        self.references.append(item)
        
        y += 60
        item =  QGraphicsSimpleTextItem(make_pretty(description, 55))
        item.setBrush(self.TEXT_COLOR)
        item.setFont(self.NORMALISH) 
        item.setX(x)
        item.setY(y)
        self.qtscene.addItem(item)
        self.references.append(item)
        
        item = QPushButton('Next')
        item.clicked.connect(self.on_next)
        item.setFont(self.BOLDISH) 
        item.move(x+700, y)
        self.qtscene.addWidget(item)
        self.references.append(item)
        
    
    def _init_scene(self):
        self.qtscene = QGraphicsScene(self)
        self.qtscene.setSceneRect(QRectF(0, 0, 1000, 750))
        brush = QBrush(QColor(240,245,250))
        self.qtscene.setBackgroundBrush(brush)
        self.setScene(self.qtscene)
        self.references = []
    
    def on_next(self, event):
        self.next()
    
    def on_hover_answer(self, item, event):
        item.setBrush(QBrush(QColor(100,1,1)))
    
    def on_unhover_answer(self, item, event):
        item.setBrush(self.TEXT_COLOR)
        
    def on_click_answer(self, answer_index, event):
        self.select_answer(answer_index)
    
    def keyPressEvent(self, ev):
        if ev.key() == Qt.Key_Escape:
            self.quit()
        
    def quit(self):
        qApp.quit() 
Beispiel #7
0
class Window(QWidget):
    ''' The MainWindow widget '''
    def __init__(self, game):
        super().__init__()

        self.game = game
        self.game.ui = self

        self.setWindowTitle('WordJuggler')
        self.resize(800, 600)
        self.setStyleSheet('QGroupBox { border:0; font:bold;' +
                           'padding:20px 10px; min-width:220px; }')

        self.board = BoardItem(game.width, game.height)
        self.rack = RackItem(game.rack_size, game.width, game.height)
        self.scene = QGraphicsScene()
        self.scene.setBackgroundBrush(QBrush(QColor('#f9ece0')))
        self.scene.addItem(self.board)
        self.scene.addItem(self.rack)
        self.scene.setSceneRect(self.scene.itemsBoundingRect())
        self.view = BoardView(self.scene, self)
        self.view.letterChanged.connect(self.letterChanged)

        self.ranking = QGroupBox('Rankings')
        self.rankings = QLabel()
        rankings = QVBoxLayout()
        rankings.addWidget(self.rankings)
        self.ranking.setLayout(rankings)

        self.statistic = QGroupBox('Statistics')
        self.statistics = QLabel()
        statistics = QVBoxLayout()
        statistics.addWidget(self.statistics)
        self.statistic.setLayout(statistics)

        self.move = QGroupBox('Last 10 Moves')
        self.moves = QLabel()
        moves = QVBoxLayout()
        moves.addWidget(self.moves)
        self.move.setLayout(moves)

        self.buttons = QVBoxLayout()
        self.buttons.setSpacing(3)
        self.continue_button = QPushButton('Place &Word')
        self.continue_button.setEnabled(False)
        self.continue_button.setFixedSize(130, 25)
        self.continue_button.clicked.connect(self.continueClicked)
        self.pass_button = QPushButton('&Pass')
        self.pass_button.setEnabled(False)
        self.pass_button.setFixedSize(130, 25)
        self.pass_button.clicked.connect(self.passClicked)
        self.exchange_button = QPushButton('&Exchange')
        self.exchange_button.setEnabled(False)
        self.exchange_button.setFixedSize(130, 25)
        self.exchange_button.clicked.connect(self.exchangeClicked)
        self.buttons.addWidget(self.exchange_button, alignment=Qt.AlignCenter)
        self.buttons.addWidget(self.pass_button, alignment=Qt.AlignCenter)
        self.buttons.addWidget(self.continue_button, alignment=Qt.AlignCenter)

        information = QVBoxLayout()
        information.setMargin(20)
        information.setSpacing(20)
        information.addWidget(self.ranking)
        information.addWidget(self.statistic)
        information.addWidget(self.move)
        information.addStretch()
        information.addLayout(self.buttons)

        layout = QHBoxLayout()
        layout.setSpacing(0)
        layout.setMargin(0)
        layout.addWidget(self.view)
        layout.addLayout(information)

        self.setLayout(layout)
        self.show()

        for player in self.game.players:
            player.played_cb = self.playerDone
        self.playerNext()

    def update(self, *args, **kwargs):
        self.rankings.setText(
            '<br>'.join('%i. <font color=%s>%s</font> (%i points)' %
                        (i + 1, player.color, player.name, player.score)
                        for i,player in
                        enumerate(sorted(self.game.players, reverse=True,
                                         key=attrgetter('score')))))
        self.statistics.setText(('Total Players: %i\n' +
                                 'Placed Words: %i\n' +
                                 'Remaining Letters: %i') %
                                (len(self.game.players),
                                 len(list(self.game.board.get_words())),
                                 self.game.letters.remaining_letters))
        moves = []
        for i,(player,move) in list(enumerate(self.game.moves))[-10:]:
            if move[0] == Player.PASS:
                desc = 'Pass'
            elif move[0] == Player.EXCHANGE_LETTERS:
                desc = 'Exchange (%s,%s)' % move[1:]
            else:
                desc = 'Word (%i,%i,%s,%s,%i)' % move[1:]
            moves.append('%i. <font color=%s>%s</font>' % (i + 1, player.color,
                                                           desc))
        self.moves.setText('<br>'.join(moves))

        super().update(*args, **kwargs)

    def letterChanged(self):
        ''' As soon as a letter changes we need to en/disable all controls '''
        self.exchange_button.setEnabled(False)
        self.exchange_button.setText('Exchange')
        if self.game.letters.remaining_letters >= self.game.rack_size:
            selected = ''.join(l.char for l in self.scene.items()
                               if type(l) is LetterItem and l.selected)
            if selected:
                self.exchange_button.setText('Exchange: %s' % selected)
                self.exchange_button.setEnabled(True)
        self.pass_button.setEnabled(True)
        self.continue_button.setEnabled(True if self.board.validNewWord() else
                                        False)

    def playerNext(self):
        player = self.game.next_player()

        self.letterChanged()
        self.update()
        player.update_letters()

        self.rack.name = self.game.current_player.name
        self.rack.color = self.game.current_player.color

        for i,letter in enumerate(player.letters):
            item = LetterItem(letter, self.game.letters.get_score(letter),
                              player.color)
            item.own(self.rack, i, move=False)
            self.scene.addItem(item)

        self.update()
        player.played_cb = self.playerDone
        player.play()

    def continueClicked(self):
        if type(self.game.current_player) is Human:
            self.game.current_player.continue_cb()

    def passClicked(self):
        if type(self.game.current_player) is Human:
            self.game.current_player.pass_cb()

    def exchangeClicked(self):
        if type(self.game.current_player) is Human:
            self.game.current_player.exchange_cb()

    def playerDone(self, player, move, *args):
        self.exchange_button.setEnabled(False)
        self.exchange_button.setText('Exchange')
        self.pass_button.setEnabled(False)
        self.continue_button.setEnabled(False)

        for item in self.scene.items():
            if type(item) is LetterItem and not item.is_safe and \
               not item.deleted:
                item.own(None)
                item.fade()

        for x,y,letter in self.game.board:
            if not self.board.getLetter(x, y):
                item = LetterItem(letter.char,
                                  self.game.letters.get_score(letter),
                                  letter.player.color, safe=True)
                item.own(self.board, x, y, move=False)
                self.scene.addItem(item)

        self.update()

        if self.game.state() == self.game.RUNNING:
            self.game.current_player.update_letters()
            self.playerNext()
        else:
            self.game.finish_score()
            self.update()
            self.gameOver()
        
    def getLetters(self, count, msg=''):
        print('random letters: %s' % self.game.get_letters_old(count))
        while True:
            text,ok = QInputDialog.getText(self, 'New Letters',
                'Player: <font color=%s>%s</font><br>' % (
                self.game.current_player.color, self.game.current_player.name)
                + msg + 'Tell me %i new letters in order to continue..' % count)

            text = ''.join(filter(lambda x: x in self.game.letters.letters,
                                  text.lower()))

            if len(text) == count and all(self.game.letters.available(c) for c
                                          in text):
                return text

    def gameOver(self):
        winner = sorted(self.game.players, reverse=True,
                        key=attrgetter('score'))[0]
        self.dialog = QMessageBox(QMessageBox.Information, 'Game Over',
            ('<b>Game Over!</b><br><br>The player ' +
             '<b><font color=%s>%s</font></b> has won!') %
            (winner.color, winner.name),
            QMessageBox.Ok, self)
        self.dialog.show()