def __init__(self, current_case):
        QWidget.__init__(self)

        self.__model = PlotCaseModel()

        self.__signal_mapper = QSignalMapper(self)
        self.__case_selectors = {}
        self.__case_selectors_order = []

        layout = QVBoxLayout()

        add_button_layout = QHBoxLayout()
        self.__add_case_button = QToolButton()
        self.__add_case_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.__add_case_button.setText("Add case to plot")
        self.__add_case_button.setIcon(resourceIcon("ide/small/add"))
        self.__add_case_button.clicked.connect(self.addCaseSelector)

        add_button_layout.addStretch()
        add_button_layout.addWidget(self.__add_case_button)
        add_button_layout.addStretch()

        layout.addLayout(add_button_layout)

        self.__case_layout = QVBoxLayout()
        self.__case_layout.setMargin(0)
        layout.addLayout(self.__case_layout)

        self.addCaseSelector(disabled=True, current_case=current_case)
        layout.addStretch()

        self.setLayout(layout)

        self.__signal_mapper.mapped[QWidget].connect(self.removeWidget)
Beispiel #2
0
class ProviderToolBar(QToolBar):
    '''
    Widget to display the vehicles/objects status and position
    '''

    triggered = pyqtSignal(str)

    def __init__(self, parent=None):
        super(ProviderToolBar, self).__init__(parent)
        self.signalMapper = QSignalMapper(self)
        self.setMovable(True)
        self.setFloatable(True)
        self.upToDate = False
        self.actions = []
        self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.signalMapper.mapped[str].connect(self.triggered)

    def createAction(self, provider):
        icon = QIcon(':/plugins/PosiView/ledgreen.png')
        icon.addFile(':/plugins/PosiView/ledgrey.png', QSize(), QIcon.Disabled, QIcon.Off)
        action = QAction(icon, provider.name, None)
        button = QToolButton()
        button.setDefaultAction(action)
        action.setEnabled(False)
        provider.deviceConnected.connect(action.setEnabled)
        provider.deviceDisconnected.connect(action.setDisabled)
        self.signalMapper.setMapping(action, provider.name)
        action.triggered.connect(self.signalMapper.map)
        self.addAction(action)
        self.actions.append(action)
Beispiel #3
0
    def __init__(self, auth, conversation_id, settings, version, parent = None):
        QDialog.__init__(self, parent)
        self.ui = cg.Ui_Dialog()
        self.ui.setupUi(self)
        
        self.settings = settings
        self.auth = auth
        self.version = version
        
        # Initialize signal mappers for buttons and lists for buttons pointers
        self.context_buttons_mapper = QSignalMapper(self)
        self.context_buttons_list = []
        self.destroy_buttons_mapper = QSignalMapper(self)
        self.destroy_buttons_list = []
        self.redent_buttons_mapper = QSignalMapper(self)
        self.redent_buttons_list = []
        self.like_buttons_mapper = QSignalMapper(self)
        self.like_buttons_list = []
        self.dentid_buttons_mapper = QSignalMapper(self)
        self.dentid_buttons_list = []
        
        self.ui.context.setSortingEnabled(True)
        self.ui.context.sortByColumn(2, Qt.DescendingOrder)
        for column in range(2, 6):
            self.ui.context.setColumnHidden(column, True)
        self.ui.context.setColumnWidth(0, 65)
        self.ui.context.itemActivated.connect(self.reply_to_dent)

        conversation = self.auth.get_conversation(conversation_id)
        
        self.list_handler = list_handler.List_Handler(self.callback)
        
        self.list_item = list_item.list_item()
        self.list_handler.add_data("conversation", conversation, self.settings["server"])
        self.connect_buttons()
Beispiel #4
0
    def __init__(self,
                 parent=None,
                 columns=4,
                 buttonSize=None,
                 iconSize=None,
                 toolButtonStyle=Qt.ToolButtonTextUnderIcon):
        QFrame.__init__(self, parent)

        if buttonSize is not None:
            buttonSize = QSize(buttonSize)

        if iconSize is not None:
            iconSize = QSize(iconSize)

        self.__columns = columns
        self.__buttonSize = buttonSize or QSize(50, 50)
        self.__iconSize = iconSize or QSize(26, 26)
        self.__toolButtonStyle = toolButtonStyle

        self.__gridSlots = []

        self.__buttonListener = ToolButtonEventListener(self)
        self.__buttonListener.buttonRightClicked.connect(
            self.__onButtonRightClick)

        self.__buttonListener.buttonEnter.connect(self.__onButtonEnter)

        self.__mapper = QSignalMapper()
        self.__mapper.mapped[QObject].connect(self.__onClicked)

        self.__setupUi()
Beispiel #5
0
class ProviderToolBar(QToolBar):
    '''
    Widget to display the vehicles/objects status and position
    '''

    triggered = pyqtSignal(str)

    def __init__(self, parent=None):
        super(ProviderToolBar, self).__init__(parent)
        self.signalMapper = QSignalMapper(self)
        self.setMovable(True)
        self.setFloatable(True)
        self.upToDate = False
        self.actions = []
        self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.signalMapper.mapped[str].connect(self.triggered)

    def createAction(self, provider):
        icon = QIcon(':/plugins/PosiView/ledgreen.png')
        icon.addFile(':/plugins/PosiView/ledgrey.png', QSize(), QIcon.Disabled,
                     QIcon.Off)
        action = QAction(icon, provider.name, None)
        button = QToolButton()
        button.setDefaultAction(action)
        action.setEnabled(False)
        provider.deviceConnected.connect(action.setEnabled)
        provider.deviceDisconnected.connect(action.setDisabled)
        self.signalMapper.setMapping(action, provider.name)
        action.triggered.connect(self.signalMapper.map)
        self.addAction(action)
        self.actions.append(action)
Beispiel #6
0
 def gTable(self):
     self.gtable = QTableWidget()
     self.gtable.setColumnCount(1)
     self.gtable.setRowCount(len(self.tables.tablesIdWriteMap))
     self.gtable.setHorizontalHeaderItem(
         0, QTableWidgetItem(QString("version")))
     self.hlayout.addWidget(self.gtable)
     self.sigMapper = QSignalMapper(self)
     for id in self.tables.tablesIdWriteMap:
         wlist = self.tables.tablesIdWriteMap[id]
         cbox = QComboBox(self.gtable)
         self.connect(cbox, SIGNAL("activated(QString)"), self.sigMapper,
                      SLOT("map()"))
         self.sigMapper.setMapping(cbox, id)
         l = []
         for write in wlist:
             l.append(write)
         l.sort()
         l.reverse()
         for write in l:
             cbox.addItem(QString(hex(write)))
         self.gtable.setCellWidget(id, 0, cbox)
         self.gtable.setVerticalHeaderItem(
             id, QTableWidgetItem(QString(hex(id))))
     self.connect(self.sigMapper, SIGNAL("mapped(int)"),
                  self.viewTableUpdate)
     self.gtable.setMaximumWidth(
         self.gtable.columnWidth(0) +
         self.gtable.verticalHeader().sectionSize(0) + 30)
Beispiel #7
0
class PeriodicInstrumentController(NonBlockingInstrumentController):
    def __init__(self, instrument_config):
        NonBlockingInstrumentController.__init__(self, instrument_config)

        self.mapper = QSignalMapper()
        self.timers = []

    def run(self):
        # create and start periodic timers for each command
        for i, command in enumerate(self.instr_cfg.operation_commands):
            self.log.debug("Creating timer for '{0}' command".format(
                command.name))
            timer = QTimer()
            timer.timeout.connect(self.mapper.map)
            self.mapper.setMapping(timer, i)
            timer.start(command.param)
            self.timers.append(timer)

        self.mapper.mapped.connect(self.send_command)

        NonBlockingInstrumentController.run(self)

    def quit(self):
        for timer in self.timers:
            timer.stop()
        NonBlockingInstrumentController.quit(self)

    def send_command(self, num):
        self.new_command.emit(self.instr_cfg.operation_commands[num])
 def contextMenuEvent(self, event):
   menu     = QtGui.QMenu()
   last_pos = event.pos()
   cursor   = self.cursorForPosition(last_pos)
   pos      = cursor.positionInBlock()
   line     = cursor.blockNumber()
   
   keywords = self.words_at_pos(line, pos)
   
   if len(keywords) > 0:
     keyword_mapper = QSignalMapper(self)
     
     actions = []
     
     for keyword in keywords:
       
       action_text = "Copy \"%s\"" % keyword[0].meaning
       actions.append(QtGui.QAction(action_text, None))
       
       # We can only send strings with the signal mapper, so pickle our data.
       data = pickle.dumps(keyword[0])
       data = QtCore.QString.fromAscii(data)
       
       self.connect(actions[-1], QtCore.SIGNAL("triggered()"), keyword_mapper, QtCore.SLOT("map()"))
       keyword_mapper.setMapping(actions[-1], data)
     
     self.connect(keyword_mapper, QtCore.SIGNAL("mapped(QString)"), self.copy_keyword)
     menu.addActions(actions)
     menu.addSeparator()
   
   default_menu = self.createStandardContextMenu()
   menu.addActions(default_menu.actions())
   
   menu.exec_(event.globalPos())
Beispiel #9
0
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowFlags(Qt.Window)

        self._mdi_area = QMdiArea()
        self._mdi_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self._mdi_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self._mdi_area)
        # set the size of mid_area and DocumentViewManager based on the
        # screen size.
        screen = QDesktopWidget().availableGeometry()
        self._mdi_area.resize(screen.width() - 30, screen.height() - 80)
        self.resize(self._mdi_area.size())
        self._mdi_area.subWindowActivated.connect(self.update_actions)
        self._viewer_mapper = QSignalMapper(self)
        self._viewer_mapper.mapped[QWidget].connect(self.set_active_sub_window)

        win_title = QApplication.translate(
            "DocumentViewManager",
            "Document Viewer"
        )
        self.setWindowTitle(win_title)
        self.setUnifiedTitleAndToolBarOnMac(True)
        self.statusBar().showMessage(
            QApplication.translate(
                "DocumentViewManager",
                "Ready"
            )
        )
        self._doc_viewers = {}

        self._create_menu_actions()
        self.update_actions()
Beispiel #10
0
class LEDDialog(QDialog):
    rowwidth = 20
    def __init__(self, strip, parent=None):
        super(LEDDialog,self).__init__(parent)
        self.strip = strip
        self.buttons = []
        layout = QVBoxLayout()
        btnlayout = QGridLayout()
        self.btnmapper = QSignalMapper()
        for i in xrange(int(self.strip.config['nleds'])):
            p = QPushButton()
            p.setFixedWidth(40)
            p.setFlat(True)
            p.setAutoFillBackground(True)
            self.btnmapper.setMapping( p, i)
            p.clicked.connect( self.btnmapper.map)
            self.buttons += [[p,QColor()]]
            btnlayout.addWidget(p, i/self.rowwidth, i%self.rowwidth)
        self.btnmapper.mapped['int'].connect(self.chooseColor)
        layout.addLayout(btnlayout)
        ctrllayout = QHBoxLayout()
        p = QPushButton("Refresh")
        p.clicked.connect(self.refresh)
        ctrllayout.addWidget(p)
        p = QPushButton("Set")
        p.clicked.connect(self.set)
        ctrllayout.addWidget(p)
        p = QPushButton("Close")
        p.clicked.connect(self.close)
        ctrllayout.addWidget(p)
        layout.addLayout(ctrllayout)
        self.setLayout( layout)
        self.refresh()

    def refresh(self):
        tmp = self.strip.state()
        for i in xrange(len(self.buttons)):
            c = QColor(int(tmp[i*3+0]),int(tmp[i*3+1]),int(tmp[i*3+2]))
            pal = self.buttons[i][0].palette()
            pal.setBrush( QPalette.Button, QColor(c.red(),c.green(),c.blue()))
            self.buttons[i][0].setPalette(pal)
            self.buttons[i][1] = c
        
    def set(self):
        leds = []
        for b,c in self.buttons:
            leds += [ c.red(), c.green(), c.blue() ]
        self.strip.setState(leds)
        time.sleep(0.1)
        self.refresh()
        
    def chooseColor(self, i):
        if not i < len(self.buttons): return
        initial = self.buttons[i][1]
        c = QColorDialog.getColor(initial,self)
        if initial == c: return
        pal = self.buttons[i][0].palette()
        pal.setBrush( QPalette.Button, QColor(c.red(),c.green(),c.blue()))
        self.buttons[i][0].setPalette(pal)
        self.buttons[i][1] = c
Beispiel #11
0
    def _init_translators(self):
        translator_menu = QMenu(self)

        self._trans_widget_mgr = TranslatorWidgetManager(self)
        self._trans_signal_mapper = QSignalMapper(self)

        for trans_name, config in ValueTranslatorConfig.translators.iteritems():
            trans_action = QAction( u'{}...'.format(trans_name),
                translator_menu
            )

            self._trans_signal_mapper.setMapping(trans_action, trans_name)
            trans_action.triggered.connect(self._trans_signal_mapper.map)

            translator_menu.addAction(trans_action)

        if len(translator_menu.actions()) == 0:
            self.btn_add_translator.setEnabled(False)

        else:
            self.btn_add_translator.setMenu(translator_menu)

            self._trans_signal_mapper.mapped[str].connect(self._load_translator_dialog)

        self.btn_edit_translator.setEnabled(False)
        self.btn_delete_translator.setEnabled(False)

        self.btn_edit_translator.clicked.connect(self._on_edit_translator)
        self.btn_delete_translator.clicked.connect(self._on_delete_translator)
    def __init__(self, parent, tester):
        """Construct a new dockwindow following the tester """
        self.tester = tester
        
        QtGui.QDockWidget.__init__(self, tester.testname, parent)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        
        if not self.widget():
            self.setWidget(QtGui.QWidget(self))
        
        vl = QtGui.QVBoxLayout(self.widget())
        #self.widget().setLayout(vl)
        
        panel = QtGui.QFrame(self)
        vl.addWidget(panel)
        
        self.login = QtGui.QLineEdit(self)
        self.login.textEdited.connect(self.check_logpass)
        self.password = QtGui.QLineEdit(self)
        self.password.setEchoMode(QtGui.QLineEdit.Password)
        self.password.textEdited.connect(self.check_logpass)
        
        self.tests = []
        
        fl = QtGui.QFormLayout(panel)
        fl.addRow('&Login:'******'&Password:',self.password)
        panel.setLayout(fl)
        
        panel = QtGui.QFrame(self)
        panel.setFrameShadow(QtGui.QFrame.Sunken)
        panel.setFrameShape(QtGui.QFrame.Panel)
        vl.addWidget(panel)
        
        vl2 = QtGui.QVBoxLayout(panel)
        
        signalmapper = QSignalMapper(self)
        signalmapper.mapped[int].connect(self.test)
        
        for i,test in enumerate(self.tester.tests):
            btn = QtGui.QPushButton("Test {}: {}".format(i+1,test.name),panel)
            btn.setStyleSheet(self.btn_default_stylesheet)
            btn.setEnabled(False)
            vl2.addWidget(btn)
            self.tests.append(btn)
            signalmapper.setMapping(btn,i)
            btn.clicked.connect(signalmapper.map)
        
        panel.setLayout(vl2)
        
        self.text = QtGui.QLabel("Enter your Coursera login and assignments password and push one of the test buttons above to run the test and submit the results to Coursera.")
        self.text.setWordWrap(True)
        vl.addWidget(self.text)
        self.text.setFrameShadow(QtGui.QFrame.Sunken)
        self.text.setFrameShape(QtGui.QFrame.Panel)
        self.text.setMargin(5)

        #vl.setStretch(2,1)
        vl.addStretch(1)
 def _setup_self(self):
     """Sets up self."""
     
     self.setObjectName(u'stackedWidget')
     
     self.openTabSignalMapper = QSignalMapper(self)
     
     self._build_widgets()
Beispiel #14
0
 def __init__(self, parent=None):
     super(ProviderToolBar, self).__init__(parent)
     self.signalMapper = QSignalMapper(self)
     self.setMovable(True)
     self.setFloatable(True)
     self.upToDate = False
     self.actions = []
     self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
     self.signalMapper.mapped[str].connect(self.triggered)
Beispiel #15
0
    def setupUi(self, nx, ny, keys):
        mapper = QSignalMapper()

        layout = QGridLayout(self)
        for ix in range(nx):
            for iy in range(ny):
                key = keys[iy * nx + ix]
                keyPb = QPushButton(self)
                keyPb.setFixedHeight(40)
                keyPb.setText(key[0])
                keyPb.clicked.connect(mapper.map)
                layout.addWidget(keyPb, iy, ix)
                mapper.setMapping(keyPb, key[1])
        mapper.mapped.connect(self.keyClicked)
        self.mapper = mapper
    def __init__(self, current_case):
        QWidget.__init__(self)

        self.__model = PlotCaseModel()

        self.__signal_mapper = QSignalMapper(self)
        self.__case_selectors = {}
        self.__case_selectors_order = []

        layout = QVBoxLayout()

        add_button_layout = QHBoxLayout()
        button = QPushButton(util.resourceIcon("ide/small/add"), "Add case to plot")
        button.clicked.connect(self.addCaseSelector)

        add_button_layout.addStretch()
        add_button_layout.addWidget(button)
        add_button_layout.addStretch()

        layout.addLayout(add_button_layout)

        self.__case_layout = QVBoxLayout()
        self.__case_layout.setMargin(0)
        layout.addLayout(self.__case_layout)

        self.addCaseSelector(disabled=True, current_case=current_case)
        layout.addStretch()

        self.setLayout(layout)

        self.__signal_mapper.mapped[QWidget].connect(self.removeWidget)
Beispiel #17
0
    def _createToolbarAndConnect(self):
        """Create toolbar and connect tools."""
        self.signalMapper = QSignalMapper(self)

        self._mToolbar = QToolBar(self)
        self._mToolbar.addAction(self.actionImport)
        self._mToolbar.addAction(self.actionSave)
        self._mToolbar.addSeparator()
        self._mToolbar.addAction(self.actionSelect)
        self._mToolbar.addAction(self.actionDeselect)
        self._mToolbar.addSeparator()
        self._mToolbar.addAction(self.actionDelete)

        self.actionSave.setEnabled(False)
        self.actionSelect.setEnabled(False)
        self.actionDeselect.setEnabled(False)
        self.actionDelete.setEnabled(False)

        self.toolbarLayout.insertWidget(0, self._mToolbar)

        self.connect(self.actionImport, SIGNAL("triggered()"), self.onLoad)
        self.connect(self.actionSave, SIGNAL("triggered()"), self.onSave)
        self.connect(self.actionSelect, SIGNAL("triggered()"), self.onSelect)
        self.connect(self.actionDeselect, SIGNAL("triggered()"),
                     self.onDeselect)
        self.connect(self.actionDelete, SIGNAL("triggered()"), self.onDelete)
        self.connect(self.styleButton, SIGNAL("clicked()"), self.onStyle)
Beispiel #18
0
    def __init__(self, parent=None, columns=4, buttonSize=None,
                 iconSize=None, toolButtonStyle=Qt.ToolButtonTextUnderIcon):
        QFrame.__init__(self, parent)

        if buttonSize is not None:
            buttonSize = QSize(buttonSize)

        if iconSize is not None:
            iconSize = QSize(iconSize)

        self.__columns = columns
        self.__buttonSize = buttonSize or QSize(50, 50)
        self.__iconSize = iconSize or QSize(26, 26)
        self.__toolButtonStyle = toolButtonStyle

        self.__gridSlots = []

        self.__buttonListener = ToolButtonEventListener(self)
        self.__buttonListener.buttonRightClicked.connect(
                self.__onButtonRightClick)

        self.__buttonListener.buttonEnter.connect(
                self.__onButtonEnter)

        self.__mapper = QSignalMapper()
        self.__mapper.mapped[QObject].connect(self.__onClicked)

        self.__setupUi()
Beispiel #19
0
    def __init__ (self, parent, collections=None, songs=None, busName=None, busPath=None):
        SatyrObject.__init__ (self, parent, busName, busPath)

        self.configValues= (
            ('collsNo', int, 0),
            )
        self.loadConfig ()

        self.signalMapper= QSignalMapper ()
        self.collections= []

        if songs is None:
            self.songs= []
            self.count= 0
        else:
            self.songs= songs
            self.count= len (songs)

        # if collections is not None we it means the may have changed
        if self.collsNo>0 and collections is None:
            logger.info ("loading collections from config", self.collsNo)
            for index in xrange (self.collsNo):
                collection= Collection (self, busName=busName, busPath="/collection_%04d" % index)
                self.append (collection)
        else:
            if collections is not None:
                for collection in collections:
                    self.append (collection)

        self.signalMapper.mapped.connect (self.addSongs)
    def __init__(self, current_case):
        QWidget.__init__(self)

        self.__model = PlotCaseModel()

        self.__signal_mapper = QSignalMapper(self)
        self.__case_selectors = {}
        self.__case_selectors_order = []

        layout = QVBoxLayout()

        add_button_layout = QHBoxLayout()
        self.__add_case_button = QToolButton()
        self.__add_case_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.__add_case_button.setText("Add case to plot")
        self.__add_case_button.setIcon(resourceIcon("ide/small/add"))
        self.__add_case_button.clicked.connect(self.addCaseSelector)

        add_button_layout.addStretch()
        add_button_layout.addWidget(self.__add_case_button)
        add_button_layout.addStretch()

        layout.addLayout(add_button_layout)

        self.__case_layout = QVBoxLayout()
        self.__case_layout.setContentsMargins(0, 0, 0, 0)
        layout.addLayout(self.__case_layout)

        self.addCaseSelector(disabled=True, current_case=current_case)
        layout.addStretch()

        self.setLayout(layout)

        self.__signal_mapper.mapped[QWidget].connect(self.removeWidget)
Beispiel #21
0
    def _init_translators(self):
        translator_menu = QMenu(self)

        self._trans_widget_mgr = TranslatorWidgetManager(self)
        self._trans_signal_mapper = QSignalMapper(self)

        for trans_name, config in ValueTranslatorConfig.translators.iteritems():
            trans_action = QAction( u'{}...'.format(trans_name),
                translator_menu
            )

            self._trans_signal_mapper.setMapping(trans_action, trans_name)
            trans_action.triggered.connect(self._trans_signal_mapper.map)

            translator_menu.addAction(trans_action)

        if len(translator_menu.actions()) == 0:
            self.btn_add_translator.setEnabled(False)

        else:
            self.btn_add_translator.setMenu(translator_menu)

            self._trans_signal_mapper.mapped[str].connect(self._load_translator_dialog)

        self.btn_edit_translator.setEnabled(False)
        self.btn_delete_translator.setEnabled(False)

        self.btn_edit_translator.clicked.connect(self._on_edit_translator)
        self.btn_delete_translator.clicked.connect(self._on_delete_translator)
Beispiel #22
0
    def __init__ (self, collaggr=None, songs=None, view=None):
        QAbstractTableModel.__init__ (self, view)
        # TODO: different delegate for editing tags: one with completion
        self.view_= view
        self.playlist= view.playlist
        self.edited= False

        if songs is None:
            self.collaggr= collaggr
            self.collections= self.collaggr.collections

            self.signalMapper= QSignalMapper ()
            for collNo, collection in enumerate (self.collections):
                collection.newSongs.connect (self.signalMapper.map)
                self.signalMapper.setMapping (collection, collNo)

            self.signalMapper.mapped.connect (self.addRows)
        else:
            self.collaggr= CollectionAggregator (self, songs=songs)

        self.attrNames= ('artist', 'year', 'collection', 'diskno', 'album', 'trackno', 'title', 'length', 'filepath')

        self.headers= (u'Artist', u'Year', u'Collection', u'CD', u'Album', u'Track', u'Title', u'Length', u'Path')
        # FIXME: kinda hacky
        self.fontMetrics= QFontMetrics (KGlobalSettings.generalFont ())
        # FIXME: (even more) hackish
        self.columnWidths= ("M"*15, "M"*4, "M"*15, "M"*3, "M"*20, "M"*3, "M"*25, "M"*5, "M"*200)
        logger.debug ("QPLM: ", self)
Beispiel #23
0
 def __init__(self, strip, parent=None):
     super(LEDDialog,self).__init__(parent)
     self.strip = strip
     self.buttons = []
     layout = QVBoxLayout()
     btnlayout = QGridLayout()
     self.btnmapper = QSignalMapper()
     for i in xrange(int(self.strip.config['nleds'])):
         p = QPushButton()
         p.setFixedWidth(40)
         p.setFlat(True)
         p.setAutoFillBackground(True)
         self.btnmapper.setMapping( p, i)
         p.clicked.connect( self.btnmapper.map)
         self.buttons += [[p,QColor()]]
         btnlayout.addWidget(p, i/self.rowwidth, i%self.rowwidth)
     self.btnmapper.mapped['int'].connect(self.chooseColor)
     layout.addLayout(btnlayout)
     ctrllayout = QHBoxLayout()
     p = QPushButton("Refresh")
     p.clicked.connect(self.refresh)
     ctrllayout.addWidget(p)
     p = QPushButton("Set")
     p.clicked.connect(self.set)
     ctrllayout.addWidget(p)
     p = QPushButton("Close")
     p.clicked.connect(self.close)
     ctrllayout.addWidget(p)
     layout.addLayout(ctrllayout)
     self.setLayout( layout)
     self.refresh()
 def setup_file_locs(self):
   
   # Because the default margins are ugly as h*ck.
   self.ui.tabLocs.layout().setContentsMargins(0, 0, 0, 0)
   
   # Map our buttons to functions that retrieve the necessary data.
   cfg_mapper = QSignalMapper(self)
   
   for i, item in enumerate(FILE_LOCATIONS):
     self.connect(self.ui.__dict__[item[BTN]], QtCore.SIGNAL("clicked()"), cfg_mapper, QtCore.SLOT("map()"))
     cfg_mapper.setMapping(self.ui.__dict__[item[BTN]], i)
   
   self.connect(cfg_mapper, QtCore.SIGNAL("mapped(int)"), self.__get_cfg_item)
   
   # Load in all our info from the config file.
   for item in FILE_LOCATIONS:
     self.ui.__dict__[item[TEXT]].setText(common.editor_config.get_pref(item[CFG]))
Beispiel #25
0
    def __init__(self, *args, **kwargs):
        QGraphicsScene.__init__(self, *args, **kwargs)

        self.scheme = None
        self.registry = None

        # All node items
        self.__node_items = []
        # Mapping from SchemeNodes to canvas items
        self.__item_for_node = {}
        # All link items
        self.__link_items = []
        # Mapping from SchemeLinks to canvas items.
        self.__item_for_link = {}

        # All annotation items
        self.__annotation_items = []
        # Mapping from SchemeAnnotations to canvas items.
        self.__item_for_annotation = {}

        # Is the scene editable
        self.editable = True

        # Anchor Layout
        self.__anchor_layout = AnchorLayout()
        self.addItem(self.__anchor_layout)

        self.__channel_names_visible = True
        self.__node_animation_enabled = True

        self.user_interaction_handler = None

        self.activated_mapper = QSignalMapper(self)
        self.activated_mapper.mapped[QObject].connect(
            lambda node: self.node_item_activated.emit(node)
        )
        self.hovered_mapper = QSignalMapper(self)
        self.hovered_mapper.mapped[QObject].connect(
            lambda node: self.node_item_hovered.emit(node)
        )
        self.position_change_mapper = QSignalMapper(self)
        self.position_change_mapper.mapped[QObject].connect(
            self._on_position_change
        )
        log.info("'%s' intitialized." % self)
Beispiel #26
0
 def __init__(self, parent=None):
     super(ProviderToolBar, self).__init__(parent)
     self.signalMapper = QSignalMapper(self)
     self.setMovable(True)
     self.setFloatable(True)
     self.upToDate = False
     self.actions = []
     self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
     self.signalMapper.mapped[str].connect(self.triggered)
Beispiel #27
0
    def __setupUi(self):
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        # Scroll area for the contents.
        self.__scrollArea = \
                _ToolBoxScrollArea(self, objectName="toolbox-scroll-area")

        self.__scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.__scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.__scrollArea.setSizePolicy(QSizePolicy.MinimumExpanding,
                                        QSizePolicy.MinimumExpanding)
        self.__scrollArea.setFrameStyle(QScrollArea.NoFrame)
        self.__scrollArea.setWidgetResizable(True)

        # A widget with all of the contents.
        # The tabs/contents are placed in the layout inside this widget
        self.__contents = QWidget(self.__scrollArea,
                                  objectName="toolbox-contents")

        # The layout where all the tab/pages are placed
        self.__contentsLayout = QVBoxLayout()
        self.__contentsLayout.setContentsMargins(0, 0, 0, 0)
        self.__contentsLayout.setSizeConstraint(QVBoxLayout.SetMinAndMaxSize)
        self.__contentsLayout.setSpacing(0)

        self.__contents.setLayout(self.__contentsLayout)

        self.__scrollArea.setWidget(self.__contents)

        layout.addWidget(self.__scrollArea)

        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding)

        self.__tabActionGroup = \
                QActionGroup(self, objectName="toolbox-tab-action-group")

        self.__tabActionGroup.setExclusive(self.__exclusive)

        self.__actionMapper = QSignalMapper(self)
        self.__actionMapper.mapped[QObject].connect(self.__onTabActionToogled)
Beispiel #28
0
 def __init__(self):
     Observer.__init__(self)
     QMainWindow.__init__(self)
     super(TratadorInterface, self).__init__(self)
     self.setupUi(self)
     self.erro_vertice_existe.connect(self.verticeExiste)
     self.erro_vertice_nao_existe.connect(self.verticeNaoExiste)
     self.eh_funcao.setEnabled(False)
     self.funcao_edit.setEnabled(False)
     self.grafo = None
     self.signalMapper = QSignalMapper(self)
Beispiel #29
0
class SelectMapper:
  def setupSelectMapper(self, selectMapper, selectAllButton=None):
    """selectMapper should include keys 'button'(QPushButton) and 'widget'(QWidget)
    """
    self._select = None
    self.selectMapper = selectMapper
    self.selectAllButton = selectAllButton
    self.signalMapper = QSignalMapper(self)

    for key, value in self.selectMapper.iteritems():
      # config signal mapper
      value['button'].clicked.connect(self.signalMapper.map)
      self.signalMapper.setMapping(value['button'], key)

    # connect signal mapper to slot 'select' 
    QObject.connect(self.signalMapper, SIGNAL("mapped(QString)"), self.select)
    if selectAllButton:
      selectAllButton.clicked.connect(self.selectAll)

  def select(self, select):
    select = unicode(select)
    self.selectMapper[select]['button'].setChecked(True)
    if self._select == select: return
    if self._select:
      self.selectMapper[self._select]['button'].setChecked(False)
      self.selectMapper[self._select]['widget'].hide()
    else:
      if self.selectAllButton:
        self.selectAllButton.setChecked(False)
      for key, value in self.selectMapper.iteritems():
        value['widget'].hide()
    self.selectMapper[select]['widget'].show()
    self._select = select

  def selectAll(self):
    self.selectAllButton.setChecked(True)
    if self._select == None: return
    for key, value in self.selectMapper.iteritems():
      value['button'].setChecked(False)
      value['widget'].show()
    self._select = None
Beispiel #30
0
    def __init__(self, items, colCount, parent=None):
        """
        Create Grid and setup QSignalMapper.

        Connect each item's 'clicked' signal and use the sequence index
        as map value which will be passed as argument when the Grid's
        clicked signal is emitted.

        items: sequence with widgets having a 'void clicked()' signal
        colCount: column count for each row
        parent: parent widget, default None
        """
        super(Grid, self).__init__(parent)

        # Create a grid layout.
        layout = QGridLayout()
        self.setLayout(layout)

        # Create the signal mapper.
        signalMapper = QSignalMapper(self)

        for cnt, item in enumerate(items):
            # Setup mapping for the item. In this case, the
            # mapping is the sequence index of the item.
            signalMapper.setMapping(item, cnt)

            # Connect the item's 'clicked' signal to the signal
            # mapper's 'map' slot.
            # The 'map' slot will emit the 'mapped' signal
            # when invoked and the mapping set previously will be
            # passed as an argument to the slot/signal that is
            # connected to the signal mapper's 'mapped' signal.
            item.clicked.connect(signalMapper.map)

            # Add the widget to the grid layout
            layout.addWidget(item, cnt / colCount, cnt % colCount)

        # Forward the signal mapper's 'mapped' signal via the Grid's
        # 'clicked' signal. This will handle all widgets' 'clicked'
        # ssignals.
        signalMapper.mapped.connect(self.clicked)
Beispiel #31
0
    def setup_file_locs(self):

        # Because the default margins are ugly as h*ck.
        self.ui.tabLocs.layout().setContentsMargins(0, 0, 0, 0)

        # Map our buttons to functions that retrieve the necessary data.
        cfg_mapper = QSignalMapper(self)

        for i, item in enumerate(FILE_LOCATIONS):
            self.connect(self.ui.__dict__[item[BTN]],
                         QtCore.SIGNAL("clicked()"), cfg_mapper,
                         QtCore.SLOT("map()"))
            cfg_mapper.setMapping(self.ui.__dict__[item[BTN]], i)

        self.connect(cfg_mapper, QtCore.SIGNAL("mapped(int)"),
                     self.__get_cfg_item)

        # Load in all our info from the config file.
        for item in FILE_LOCATIONS:
            self.ui.__dict__[item[TEXT]].setText(
                common.editor_config.get_pref(item[CFG]))
Beispiel #32
0
    def on_adicionar_vertice_button_clicked(self):
        if not self.grafo:
            nome = str(self.nome_edit.text())
            if nome == '':
                QMessageBox(self).critical(self, 'ERRO', 'O Gravo deve ter um nome!', buttons=QMessageBox.Ok)
                return
            self.grafo = AlgoritmosGrafoNO(nome)
            self.observe(self.grafo)
        self.limparInferencias()
        vertices = str(self.vertices_edit.text())
        vertices = vertices.split(',')
        if len(vertices) > 0:
            self.signalMapper = QSignalMapper(self)
            for vertice in vertices:
                vertice = vertice.strip()
                if vertice != '':
                    cont = self.tabela_adjacencia.rowCount()
                    item = QTableWidgetItem(vertice)
                    self.tabela_adjacencia.insertColumn(cont)
                    self.tabela_adjacencia.insertRow(cont)
                    self.tabela_adjacencia.setHorizontalHeaderItem(cont,item)
                    self.tabela_adjacencia.setVerticalHeaderItem(cont,item)
                    self.grafo.adicionarVertice(vertice)

                for x in xrange(self.tabela_adjacencia.rowCount()):
                    comboV = QComboBox(self)
                    comboH = QComboBox(self)
                    
                    comboV.addItems(['0','1'])
                    comboH.addItems(['0','1'])
                    comboV.setSizePolicy(QSizePolicy().Minimum, QSizePolicy().Minimum)
                    comboH.setSizePolicy(QSizePolicy().Minimum, QSizePolicy().Minimum)
                    self.tabela_adjacencia.setCellWidget(cont,x,comboH)
                    self.tabela_adjacencia.setCellWidget(x,cont,comboV)
                        
            for x in xrange(self.tabela_adjacencia.rowCount()):
                for y in xrange(self.tabela_adjacencia.rowCount()):
                    item = self.tabela_adjacencia.cellWidget(x, y)
                    self.connect(item, SIGNAL('currentIndexChanged(int)'),self.signalMapper, SLOT('map()'))
                    self.signalMapper.setMapping(item, '{0};{1}'.format(x,y))
                    self.connect(self.signalMapper, SIGNAL('mapped(QString)'), self.valorAlterado)
                    
            self.tabela_adjacencia.resizeColumnsToContents()
            self.tabela_adjacencia.resizeRowsToContents()
            self.fecho_origem.addItems(vertices)
            self.informacoes_vertice.addItems(vertices)
            self.busca_destino.addItems(vertices)
            self.busca_origem.addItems(vertices)
            self.remover_vertice_combo.addItems(vertices)
            self.ordem_resultado.setText(str(self.grafo.obterOrdem()))
            self.gerar_arestas_button.setEnabled(True)
            self.vertices_edit.clear()
Beispiel #33
0
 def loadPlugins(self):
     """Looks for all plugins and creates menu entries, signals and
        slots for them."""
     self.pluginSignalMapper = QSignalMapper(self)
     for p in plugin_list:
         click_action = QAction(p.name, self)
         self.menuPlugins.addAction(click_action)
         self.connect(click_action, SIGNAL("triggered()"),
                      self.pluginSignalMapper, SLOT("map()"))
         self.pluginSignalMapper.setMapping(click_action, QString(p.name))
     self.connect(self.pluginSignalMapper,
                  SIGNAL("mapped(const QString &)"),
                  self.image_browser.handlePluginClicked)
    def contextMenuEvent(self, event):
        menu = QtGui.QMenu()
        last_pos = event.pos()
        cursor = self.cursorForPosition(last_pos)
        pos = cursor.positionInBlock()
        line = cursor.blockNumber()

        keywords = self.words_at_pos(line, pos)

        if len(keywords) > 0:
            keyword_mapper = QSignalMapper(self)

            actions = []

            for keyword in keywords:

                action_text = "Copy \"%s\"" % keyword[0].meaning
                actions.append(QtGui.QAction(action_text, None))

                # We can only send strings with the signal mapper, so pickle our data.
                data = pickle.dumps(keyword[0])
                data = QtCore.QString.fromAscii(data)

                self.connect(actions[-1], QtCore.SIGNAL("triggered()"),
                             keyword_mapper, QtCore.SLOT("map()"))
                keyword_mapper.setMapping(actions[-1], data)

            self.connect(keyword_mapper, QtCore.SIGNAL("mapped(QString)"),
                         self.copy_keyword)
            menu.addActions(actions)
            menu.addSeparator()

        default_menu = self.createStandardContextMenu()
        menu.addActions(default_menu.actions())

        menu.exec_(event.globalPos())
Beispiel #35
0
    def init ( self, parent ):
        """ Finishes initializing the editor by creating the underlying toolkit
            widget.
        """
        super( RadioEditor, self ).init( parent )

        # The control is a grid layout:
        self.control = layout = QGridLayout()
        layout.setSpacing( 0 )
        layout.setMargin( 0 )

        self._mapper = QSignalMapper()
        QObject.connect( self._mapper, SIGNAL( 'mapped(QWidget *)' ),
                         self.update_object )

        self.rebuild_editor()
Beispiel #36
0
  def setupSelectMapper(self, selectMapper, selectAllButton=None):
    """selectMapper should include keys 'button'(QPushButton) and 'widget'(QWidget)
    """
    self._select = None
    self.selectMapper = selectMapper
    self.selectAllButton = selectAllButton
    self.signalMapper = QSignalMapper(self)

    for key, value in self.selectMapper.iteritems():
      # config signal mapper
      value['button'].clicked.connect(self.signalMapper.map)
      self.signalMapper.setMapping(value['button'], key)

    # connect signal mapper to slot 'select' 
    QObject.connect(self.signalMapper, SIGNAL("mapped(QString)"), self.select)
    if selectAllButton:
      selectAllButton.clicked.connect(self.selectAll)
Beispiel #37
0
 def _connectSignals(self):
     self._signalMapper = QSignalMapper()
     for widgetName, modelAttr in self.FIELDS:
         widget = getattr(self, widgetName)
         self._widget2ModelAttr[widget] = modelAttr
         self._signalMapper.setMapping(widget, widget)
         if isinstance(widget, QComboBox):
             widget.currentIndexChanged.connect(self._signalMapper.map)
         elif isinstance(widget, QSpinBox):
             widget.valueChanged.connect(self._signalMapper.map)
         elif isinstance(widget, QLineEdit):
             widget.editingFinished.connect(self._signalMapper.map)
         elif isinstance(widget, QPlainTextEdit):
             widget.textChanged.connect(self._signalMapper.map)
         elif isinstance(widget, QCheckBox):
             widget.stateChanged.connect(self._signalMapper.map)
     self._signalMapper.mapped[QWidget].connect(self.widgetChanged)
Beispiel #38
0
    def __setupUi(self):
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        # Scroll area for the contents.
        self.__scrollArea = \
                _ToolBoxScrollArea(self, objectName="toolbox-scroll-area")

        self.__scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.__scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.__scrollArea.setSizePolicy(QSizePolicy.MinimumExpanding,
                                        QSizePolicy.MinimumExpanding)
        self.__scrollArea.setFrameStyle(QScrollArea.NoFrame)
        self.__scrollArea.setWidgetResizable(True)

        # A widget with all of the contents.
        # The tabs/contents are placed in the layout inside this widget
        self.__contents = QWidget(self.__scrollArea,
                                  objectName="toolbox-contents")

        # The layout where all the tab/pages are placed
        self.__contentsLayout = QVBoxLayout()
        self.__contentsLayout.setContentsMargins(0, 0, 0, 0)
        self.__contentsLayout.setSizeConstraint(QVBoxLayout.SetMinAndMaxSize)
        self.__contentsLayout.setSpacing(0)

        self.__contents.setLayout(self.__contentsLayout)

        self.__scrollArea.setWidget(self.__contents)

        layout.addWidget(self.__scrollArea)

        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Fixed,
                           QSizePolicy.MinimumExpanding)

        self.__tabActionGroup = \
                QActionGroup(self, objectName="toolbox-tab-action-group")

        self.__tabActionGroup.setExclusive(self.__exclusive)

        self.__actionMapper = QSignalMapper(self)
        self.__actionMapper.mapped[QObject].connect(self.__onTabActionToogled)
Beispiel #39
0
    def __init__(self, parent = None):
        QMainWindow.__init__(self, parent)
        self.setWindowFlags(Qt.Window)

        self._mdi_area = QMdiArea()
        self.setCentralWidget(self._mdi_area)

        self._mdi_area.subWindowActivated.connect(self.update_actions)
        self._viewer_mapper = QSignalMapper(self)
        self._viewer_mapper.mapped[QWidget].connect(self.set_active_sub_window)

        win_title = QApplication.translate("DocumentViewManager","Document Viewer")
        self.setWindowTitle(win_title)
        self.setUnifiedTitleAndToolBarOnMac(True)
        self.statusBar().showMessage(QApplication.translate("DocumentViewManager","Ready"))

        self._doc_viewers = {}

        self._create_menu_actions()
        self.update_actions()
Beispiel #40
0
    def __init__(self, *args, **kwargs):
        QGraphicsScene.__init__(self, *args, **kwargs)

        self.scheme = None
        self.registry = None

        # All node items
        self.__node_items = []
        # Mapping from SchemeNodes to canvas items
        self.__item_for_node = {}
        # All link items
        self.__link_items = []
        # Mapping from SchemeLinks to canvas items.
        self.__item_for_link = {}

        # All annotation items
        self.__annotation_items = []
        # Mapping from SchemeAnnotations to canvas items.
        self.__item_for_annotation = {}

        # Is the scene editable
        self.editable = True

        # Anchor Layout
        self.__anchor_layout = AnchorLayout()
        self.addItem(self.__anchor_layout)

        self.__channel_names_visible = True
        self.__node_animation_enabled = True

        self.user_interaction_handler = None

        self.activated_mapper = QSignalMapper(self)
        self.activated_mapper.mapped[QObject].connect(
            lambda node: self.node_item_activated.emit(node)
        )
        self.hovered_mapper = QSignalMapper(self)
        self.hovered_mapper.mapped[QObject].connect(
            lambda node: self.node_item_hovered.emit(node)
        )
        self.position_change_mapper = QSignalMapper(self)
        self.position_change_mapper.mapped[QObject].connect(
            self._on_position_change
        )
        log.info("'%s' intitialized." % self)
Beispiel #41
0
    def gTable(self):
      self.gtable = QTableWidget()
      self.gtable.setColumnCount(1)	
      self.gtable.setRowCount(len(self.tables.tablesIdWriteMap))
      self.gtable.setHorizontalHeaderItem(0, QTableWidgetItem(QString("version")))
      self.hlayout.addWidget(self.gtable)
      self.sigMapper = QSignalMapper(self)
      for id in self.tables.tablesIdWriteMap:
         wlist = self.tables.tablesIdWriteMap[id]
         cbox = QComboBox(self.gtable)
         self.connect(cbox, SIGNAL("activated(QString)"), self.sigMapper, SLOT("map()"))
         self.sigMapper.setMapping(cbox, id)
         l = [] 
         for write in wlist:
           l.append(write)
         l.sort()
         l.reverse()
         for write in l:
	   cbox.addItem(QString(hex(write))) 
	 self.gtable.setCellWidget(id, 0, cbox)
	 self.gtable.setVerticalHeaderItem(id, QTableWidgetItem(QString(hex(id))))
      self.connect(self.sigMapper, SIGNAL("mapped(int)"),  self.viewTableUpdate) 
      self.gtable.setMaximumWidth(self.gtable.columnWidth(0) + self.gtable.verticalHeader().sectionSize(0) + 30)  
    def __init__(self, parent, tester):
        """Construct a new dockwindow following the tester """
        self.tester = tester

        QtGui.QDockWidget.__init__(self, tester.testname, parent)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        if not self.widget():
            self.setWidget(QtGui.QWidget(self))

        vl = QtGui.QVBoxLayout(self.widget())
        #self.widget().setLayout(vl)

        panel = QtGui.QFrame(self)
        vl.addWidget(panel)

        self.login = QtGui.QLineEdit(self)
        self.login.textEdited.connect(self.check_logpass)
        self.password = QtGui.QLineEdit(self)
        self.password.setEchoMode(QtGui.QLineEdit.Password)
        self.password.textEdited.connect(self.check_logpass)

        self.tests = []

        fl = QtGui.QFormLayout(panel)
        fl.addRow('&Login:'******'&Password:', self.password)
        panel.setLayout(fl)

        panel = QtGui.QFrame(self)
        panel.setFrameShadow(QtGui.QFrame.Sunken)
        panel.setFrameShape(QtGui.QFrame.Panel)
        vl.addWidget(panel)

        vl2 = QtGui.QVBoxLayout(panel)

        signalmapper = QSignalMapper(self)
        signalmapper.mapped[int].connect(self.test)

        for i, test in enumerate(self.tester.tests):
            btn = QtGui.QPushButton("Test {}: {}".format(i + 1, test.name),
                                    panel)
            btn.setStyleSheet(self.btn_default_stylesheet)
            btn.setEnabled(False)
            vl2.addWidget(btn)
            self.tests.append(btn)
            signalmapper.setMapping(btn, i)
            btn.clicked.connect(signalmapper.map)

        panel.setLayout(vl2)

        self.text = QtGui.QLabel(
            "Enter your Coursera login and assignments password and push one of the test buttons above to run the test and submit the results to Coursera."
        )
        self.text.setWordWrap(True)
        vl.addWidget(self.text)
        self.text.setFrameShadow(QtGui.QFrame.Sunken)
        self.text.setFrameShape(QtGui.QFrame.Panel)
        self.text.setMargin(5)

        #vl.setStretch(2,1)
        vl.addStretch(1)
class MainWindowStart(QMainWindow, MainWindow_Pro.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindowStart, self).__init__(parent)
        # Mappers for connecting buttons and labels
        self.myMapper = QSignalMapper(self)
        self.myMapper_StyleSheet = QSignalMapper(self)
        # Load UI
        self.setupUi(self)

        self.regex_edits = QRegExp(r"(^[0]+$|^$)")
        self._filter = Filter()
        self.filename = QString()
        self.edit1_delayh.installEventFilter(self._filter)
        self.sizeLabel = QLabel()
        self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.statusBar1.addPermanentWidget(self.sizeLabel)
        self.statusBar1.setSizeGripEnabled(False)

        self.create_connections()
        self.assign_shortcuts()

        self.create_tool_bar()
        self.update_devices_list()
        # self.button_stop.clicked.connect(self.stop_all)
        # List of valve pushbuttons
        self.valve_list = [
            self.valve1, self.valve2, self.valve3, self.valve4, self.valve5,
            self.valve6, self.valve7, self.valve8
        ]

        # GroupBoxes for grouping labels and buttons on each row, used for applying StyleSheets
        self.group_boxes = [
            self.groupbox1, self.groupbox2, self.groupbox3, self.groupbox4,
            self.groupbox5, self.groupbox6, self.groupbox7, self.groupbox8
        ]
        # List of lineEdits
        self.lineEdits_list = [
            (self.edit1_delayh, self.edit1_delaym, self.edit1_delays,
             self.edit1_onh, self.edit1_onm, self.edit1_ons, self.edit1_offh,
             self.edit1_offm, self.edit1_offs, self.edit1_totalh,
             self.edit1_totalm, self.edit1_totals),
            (self.edit2_delayh, self.edit2_delaym, self.edit2_delays,
             self.edit2_onh, self.edit2_onm, self.edit2_ons, self.edit2_offh,
             self.edit2_offm, self.edit2_offs, self.edit2_totalh,
             self.edit2_totalm, self.edit2_totals),
            (self.edit3_delayh, self.edit3_delaym, self.edit3_delays,
             self.edit3_onh, self.edit3_onm, self.edit3_ons, self.edit3_offh,
             self.edit3_offm, self.edit3_offs, self.edit3_totalh,
             self.edit3_totalm, self.edit3_totals),
            (self.edit4_delayh, self.edit4_delaym, self.edit4_delays,
             self.edit4_onh, self.edit4_onm, self.edit4_ons, self.edit4_offh,
             self.edit4_offm, self.edit4_offs, self.edit4_totalh,
             self.edit4_totalm, self.edit4_totals),
            (self.edit5_delayh, self.edit5_delaym, self.edit5_delays,
             self.edit5_onh, self.edit5_onm, self.edit5_ons, self.edit5_offh,
             self.edit5_offm, self.edit5_offs, self.edit5_totalh,
             self.edit5_totalm, self.edit5_totals),
            (self.edit6_delayh, self.edit6_delaym, self.edit6_delays,
             self.edit6_onh, self.edit6_onm, self.edit6_ons, self.edit6_offh,
             self.edit6_offm, self.edit6_offs, self.edit6_totalh,
             self.edit6_totalm, self.edit6_totals),
            (self.edit7_delayh, self.edit7_delaym, self.edit7_delays,
             self.edit7_onh, self.edit7_onm, self.edit7_ons, self.edit7_offh,
             self.edit7_offm, self.edit7_offs, self.edit7_totalh,
             self.edit7_totalm, self.edit7_totals),
            (self.edit8_delayh, self.edit8_delaym, self.edit8_delays,
             self.edit8_onh, self.edit8_onm, self.edit8_ons, self.edit8_offh,
             self.edit8_offm, self.edit8_offs, self.edit8_totalh,
             self.edit8_totalm, self.edit8_totals)
        ]

        for index, editLabels in enumerate(self.lineEdits_list, 1):

            for index2, lineedits in enumerate(editLabels, 0):
                # Apply mapper (GUIObject, objectIndex)
                self.myMapper_StyleSheet.setMapping(
                    self.lineEdits_list[index - 1][index2], index - 1)
                # Connect mapper to signal
                (self.lineEdits_list[index - 1][index2]).textChanged.connect(
                    self.myMapper_StyleSheet.map)
                # Set event Filter, for detecting when Focus changes
                self.lineEdits_list[index - 1][index2].installEventFilter(
                    self._filter)
            # Set Mappers for buttons (1..8)
            self.myMapper.setMapping(self.valve_list[index - 1], index)
            # Connect mapper to signal for detecting clicks on buttons
            (self.valve_list[index - 1]).clicked.connect(self.myMapper.map)
        # Connect to signal for enabling labelEdits
        self.myMapper.mapped['int'].connect(self.enable_fields)
        # Connect to signal for changing color of groupbox used for visual indication
        self.myMapper_StyleSheet.mapped['int'].connect(self.valve_color_status)

    # Create Keyboard Shortcuts
    def assign_shortcuts(self):
        self.actionArchivo_Nuevo.setShortcut(QKeySequence.New)
        self.action_Abrir.setShortcut(QKeySequence.Open)
        self.action_Guardar.setShortcut(QKeySequence.Save)
        self.actionGuardar_Como.setShortcut(QKeySequence.SaveAs)
        self.action_Limpiar.setShortcut('Ctrl+L')
        self.actionVAL_508_Ayuda.setShortcut(QKeySequence.HelpContents)
        self.action_Salir.setShortcut(QKeySequence.Close)
        # self.actionPreferencias.setShortcut(QKeySequence.Preferences)

        self.action_Detener_USB.setShortcut('Ctrl+Shift+C')
        self.action_Ejecutar.setShortcut('Ctrl+Shift+X')
        self.action_Para_Valvulas.setShortcut('Ctrl+Shift+P')

    # Create connections to signals
    def create_connections(self):
        self.actionArchivo_Nuevo.triggered.connect(self.new_file)
        self.action_Abrir.triggered.connect(self.open_file)
        self.action_Guardar.triggered.connect(self.save_file)
        self.actionGuardar_Como.triggered.connect(self.save_file_as)
        self.action_Limpiar.triggered.connect(self.clean_fields)
        self.action_Salir.triggered.connect(self.close)
        self.actionVAL_508_Ayuda.triggered.connect(self.show_help)
        self.actionAcerca_de_VAL_508.triggered.connect(self.show_about)

        self.action_Detener_USB.triggered.connect(self.stop_usb)
        self.action_Ejecutar.triggered.connect(self.execute)
        self.action_Para_Valvulas.triggered.connect(self.stop_all)

    # Creation of About Dialog
    def show_about(self):
        about = aboutdialog.AboutDialog(self)
        about.show()

    # Creation of Help Form
    def show_help(self):
        form = helpform.HelpForm('Help.html', self)
        form.show()

    def new_file(self):
        self.filename = QString()
        self.clean_fields()

    # Close connection to arduino before closing Program
    def closeEvent(self, QCloseEvent):
        try:
            self.thread_connection.serial_connection.close()
            logging.debug("Thread running and killed at closing program")
        except AttributeError:
            logging.debug("Thread was not running when closing program OK")

    def clean_fields(self):
        for index, editLabels in enumerate(self.lineEdits_list, 1):
            for index2, lineedits in enumerate(editLabels, 0):
                self.lineEdits_list[index - 1][index2].setText('0')

    def save_file_as(self):
        filename_copy = self.filename
        logging.info("Current filename: %s" % self.filename)
        my_home = os.path.expanduser('~')
        self.filename = QFileDialog.getSaveFileName(
            self, self.tr('Guardar como'),
            os.path.join(my_home, "archivo.txt"), "", "",
            QFileDialog.DontUseNativeDialog)
        logging.info("Filename to save: %s" % self.filename)
        if not self.filename.isNull():
            if self.filename.endsWith(QString('.txt')):
                self.write_data_to_file('w')
            else:
                self.filename.append(QString('.txt'))
                messageBox = QMessageBox(self)
                messageBox.setStyleSheet(
                    'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
                messageBox.setWindowTitle(self.tr('Advertencia'))
                messageBox.setText(
                    self.tr(u"El archivo ya existe, ¿Reemplazar?"))
                messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
                messageBox.setIconPixmap(QPixmap(':/broken_file.png'))
                if messageBox.exec_() == QMessageBox.Yes:
                    self.write_data_to_file('w')
                else:
                    try:
                        while True:
                            self.filename = QFileDialog.getSaveFileName(
                                self, self.tr('Guardar como'),
                                os.path.join(my_home, "archivo.txt"), "", "",
                                QFileDialog.DontUseNativeDialog)
                            if self.filename.isNull():
                                raise Saved_Canceled()
                            else:
                                messageBox = QMessageBox(self)
                                messageBox.setStyleSheet(
                                    'QMessageBox QLabel {font: bold 14pt "Cantarell";}'
                                )
                                messageBox.setWindowTitle(
                                    self.tr('Advertencia'))
                                messageBox.setText(
                                    self.tr(
                                        u"El archivo ya existe, ¿Reemplazar?"))
                                messageBox.setStandardButtons(QMessageBox.Yes
                                                              | QMessageBox.No)
                                messageBox.setIconPixmap(
                                    QPixmap(':/broken_file.png'))
                                if messageBox.exec_() == QMessageBox.Yes:
                                    self.write_data_to_file('w')
                                    raise Saved_Accepted()
                    except Saved_Canceled:
                        self.filename = filename_copy
                    except Saved_Accepted:
                        pass
        logging.info("Current filename after operation: %s" % self.filename)

    def save_file(self):
        if self.filename.isNull():
            self.save_file_as()
        else:
            self.write_data_to_file('w')

    # Colect data for arduino
    def execute(self):
        string_data = ''
        list_strings = []
        if str(self.arduino_combobox.currentText()):
            self.statusBar1.showMessage(self.tr('Conectando...'))
            # Gather all  the contents of each row of valves and create a list of lists with them
            for elem_edit in self.lineEdits_list:
                # delay
                string_data = string_data + str(
                    ((int(elem_edit[0].text()) * 3600) +
                     (int(elem_edit[1].text()) * 60) +
                     (int(elem_edit[2].text()))) * 1000) + ';'
                # ON
                string_data = string_data + str(
                    ((int(elem_edit[3].text()) * 3600) +
                     (int(elem_edit[4].text()) * 60) +
                     (int(elem_edit[5].text()))) * 1000) + ';'
                # OFF
                string_data = string_data + str(
                    ((int(elem_edit[6].text()) * 3600) +
                     (int(elem_edit[7].text()) * 60) +
                     (int(elem_edit[8].text()))) * 1000) + ';'
                # Total
                string_data = string_data + str(
                    ((int(elem_edit[9].text()) * 3600) +
                     (int(elem_edit[10].text()) * 60) +
                     (int(elem_edit[11].text()))) * 1000) + ';'

                list_strings.append(string_data)
                string_data = ''

            # Start QThread for communicating with arduino
            self.thread_connection = Arduino_Communication(
                str(self.arduino_combobox.currentText()), list_strings)
            self.thread_connection.start()
            self.action_Ejecutar.setEnabled(False)
            self.action_Para_Valvulas.setEnabled(False)

            # Connect to current QThread instance in order to know the status of it's termination
            # This line used only when stopping current task
            self.thread_connection.finished.connect(self.finished_thread)
            self.thread_connection.connection_exit_status.connect(
                self.finished_thread)
        else:
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Advertencia'))
            messageBox.setText(self.tr("Arduino no seleccionado"))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()

    # Inform QThread to stop sending data to arduino
    def stop_usb(self):
        if str(self.arduino_combobox.currentText()):
            try:
                self.statusBar1.showMessage(self.tr(u'Conexión detenida'))
                if self.thread_connection.isRunning():
                    mutex.lock()
                    self.thread_connection.kill_serial = True
                    mutex.unlock()
            except AttributeError:
                logging.debug("Thread not running \'disconnected! \'")
        else:
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Advertencia'))
            messageBox.setText(self.tr("Arduino no seleccionado"))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()

    def enable_fields(self, index):
        hours_reg = QRegExp(r"0*[0-9]{1,3}")
        sec_reg = QRegExp(r"(0*[0-9])|(0*[0-5][0-9])")
        for counter, line_edit in enumerate(self.lineEdits_list[index - 1]):
            line_edit.setEnabled(self.valve_list[index - 1].isChecked())
            if counter % 3 == 0:
                line_edit.setValidator(QRegExpValidator(hours_reg, self))
            else:
                line_edit.setValidator(QRegExpValidator(sec_reg, self))

    def valve_color_status(self, index):
        logging.info("Checking color from valve button")
        for edit in self.lineEdits_list[index]:
            if edit.text().contains(self.regex_edits):
                self.group_boxes[index].setStyleSheet('''QGroupBox {
                                                      border: 2px solid;
                                                      border-color: rgba(255, 255, 255, 0);}'''
                                                      )
            else:
                self.group_boxes[index].setStyleSheet(
                    '''QGroupBox {background-color: rgba(103, 255, 126, 150);
                                                      border: 2px solid;
                                                      border-color: rgba(255, 255, 255, 255);}'''
                )
                break

    def create_tool_bar(self):
        self.label_arduino = QLabel(self.tr('Dispositivos: '))
        self.toolBar.addWidget(self.label_arduino)

        self.arduino_combobox = QComboBox()
        self.arduino_combobox.setToolTip(self.tr('Seleccionar Arduino'))
        self.arduino_combobox.setFocusPolicy(Qt.NoFocus)

        # Update List of Arduino devices
        self.reload = QAction(QIcon(":/reload.png"), self.tr("&Refrescar"),
                              self)
        self.reload.setShortcut(QKeySequence.Refresh)
        self.reload.setToolTip(self.tr('Refrescar Dispositivos'))
        self.reload.triggered.connect(self.update_devices_list)

        self.toolBar.addWidget(self.arduino_combobox)
        self.toolBar.addAction(self.reload)

    # Update current usb devices connected to PC
    def update_devices_list(self):
        device_list = serial.tools.list_ports.comports()
        current_arduino = self.arduino_combobox.currentText()
        self.arduino_combobox.clear()
        for device_index, device in enumerate(sorted(device_list)):
            self.arduino_combobox.addItem(device.device)
            if device.device == current_arduino:
                self.arduino_combobox.setCurrentIndex(device_index)

    # Stop current arduino task
    def stop_all(self):
        if str(self.arduino_combobox.currentText()):
            self.thread_connection = Arduino_Communication(
                str(self.arduino_combobox.currentText()))
            self.thread_connection.start()
            self.action_Ejecutar.setEnabled(False)
            self.action_Para_Valvulas.setEnabled(False)
            self.action_Detener_USB.setEnabled(False)
            self.thread_connection.finished.connect(self.finished_thread)
            self.thread_connection.connection_exit_status.connect(
                self.finished_thread)
        else:
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Advertencia'))
            messageBox.setText(self.tr("Arduino no seleccionado"))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()

    def open_file(self):
        try:
            my_home = os.path.expanduser('~')
            file_name = QFileDialog.getOpenFileName(
                self, self.tr('Abrir archivo'), my_home, '*.txt', '*.txt',
                QFileDialog.DontUseNativeDialog)
            logging.warning("file_name type: %s" % type(file_name))
            list_values = []
            if not file_name.isNull():
                with open(file_name) as fp:
                    for line in fp:
                        list_values.extend([line.replace('\n', '')])
                logging.info("List Content: %s" % list_values)
                count = 0
                for elems in self.lineEdits_list:
                    for inner_elem in elems:
                        if not unicode(list_values[count]).isdigit():
                            raise Uncompatible_Data()
                        inner_elem.setText(list_values[count])
                        count = count + 1
                self.filename = file_name
        except (IOError, OSError):
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(self.tr('No se pudo abrir el archivo'))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/broken_file.png'))
            messageBox.exec_()
        except (IndexError, Uncompatible_Data):
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(self.tr('Formato Incompatible'))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/broken_file.png'))
            messageBox.exec_()

    # Inform the user if we were able to send data successfully to arduino
    def finished_thread(self, error=None, message=''):
        if error == 'error':
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(message)
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_error.png'))
            messageBox.exec_()
            return
        elif error == 'success':
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr(u'Éxito'))
            messageBox.setText(message)
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/usb_success.png'))
            messageBox.exec_()
            return
        elif error == 'stopped':
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr(u'Éxito'))
            messageBox.setText(message)
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIconPixmap(QPixmap(':/success_general.png'))
            messageBox.exec_()
            return
        self.action_Ejecutar.setEnabled(True)
        self.action_Para_Valvulas.setEnabled(True)
        self.action_Detener_USB.setEnabled(True)
        self.statusBar1.showMessage(self.tr('Finalizado'))

    # Save data to disk
    def write_data_to_file(self, open_mode):
        progressDialog = QProgressDialog()
        progressDialog.setModal(True)
        progressDialog.setLabelText(self.tr('Guardando...'))
        progressDialog.setMaximum(8)
        progressDialog.setCancelButton(None)
        progressDialog.show()

        try:
            # File is closed automatically even on error
            with open(unicode(self.filename), open_mode) as file_obj:
                for count, elem_edit in enumerate(self.lineEdits_list, 1):
                    file_obj.write(''.join([str(elem_edit[0].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[1].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[2].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[3].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[4].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[5].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[6].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[7].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[8].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[9].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[10].text()), '\n']))
                    file_obj.write(''.join([str(elem_edit[11].text()), '\n']))
                    progressDialog.setValue(count)
        except (IOError, OSError):
            progressDialog.close()
            messageBox = QMessageBox(self)
            messageBox.setStyleSheet(
                'QMessageBox QLabel {font: bold 14pt "Cantarell";}')
            messageBox.setWindowTitle(self.tr('Error'))
            messageBox.setText(self.tr('Error al guardar'))
            messageBox.setStandardButtons(QMessageBox.Ok)
            messageBox.setIcon(QMessageBox.Critical)
            messageBox.exec_()

        else:
            self.statusBar1.showMessage(self.tr('Guardado'), 3000)
Beispiel #44
0
class DocumentViewManager(QMainWindow):
    """
    MDI area for displaying supporting documents within a given context e.g.
    supporting documents for a specific household based on the lifetime of the
    'SourceDocumentManager' instance.
    """
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowFlags(Qt.Window)

        self._mdi_area = QMdiArea()
        self._mdi_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self._mdi_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self._mdi_area)
        # set the size of mid_area and DocumentViewManager based on the
        # screen size.
        screen = QDesktopWidget().availableGeometry()
        self._mdi_area.resize(screen.width() - 30, screen.height() - 80)
        self.resize(self._mdi_area.size())
        self._mdi_area.subWindowActivated.connect(self.update_actions)
        self._viewer_mapper = QSignalMapper(self)
        self._viewer_mapper.mapped[QWidget].connect(self.set_active_sub_window)

        win_title = QApplication.translate(
            "DocumentViewManager",
            "Document Viewer"
        )
        self.setWindowTitle(win_title)
        self.setUnifiedTitleAndToolBarOnMac(True)
        self.statusBar().showMessage(
            QApplication.translate(
                "DocumentViewManager",
                "Ready"
            )
        )
        self._doc_viewers = {}

        self._create_menu_actions()
        self.update_actions()

    def center(self):
        """
        Move the Document viewer to the center of the screen.
        """
        # Get the current screens' dimensions...
        screen = QDesktopWidget().availableGeometry()
        # ... and get this windows' dimensions
        mdi_area_size = self.frameGeometry()
        # The horizontal position
        hpos = (screen.width() - mdi_area_size.width()) / 2
        # vertical position
        vpos = (screen.height() - mdi_area_size.height()) / 2
        # repositions the window
        self.move(hpos, vpos)

    def _create_menu_actions(self):
        self._window_menu = self.menuBar().addMenu(
            QApplication.translate(
                "DocumentViewManager","&Windows"))

        self._close_act = QAction(
            QApplication.translate("DocumentViewManager",
                                                         "Cl&ose"), self)
        self._close_act.setStatusTip(
            QApplication.translate("DocumentViewManager",
                                   "Close the active document viewer"))
        self._close_act.triggered.connect(self._mdi_area.closeActiveSubWindow)

        self._close_all_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "Close &All"), self
        )
        self._close_all_act.setStatusTip(
            QApplication.translate("DocumentViewManager",
                                   "Close all the document viewers")
        )
        self._close_all_act.triggered.connect(
            self._mdi_area.closeAllSubWindows
        )

        self._tile_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "&Tile"), self
        )
        self._tile_act.setStatusTip(
            QApplication.translate("DocumentViewManager",
                                   "Tile the document viewers"))
        self._tile_act.triggered.connect(self.tile_windows)

        self._cascade_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "&Cascade"), self)
        self._cascade_act.setStatusTip(QApplication.translate(
            "DocumentViewManager",
            "Cascade the document viewers"))
        self._cascade_act.triggered.connect(self.cascade_windows)

        self._next_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "Ne&xt"), self)
        self._next_act.setStatusTip(
            QApplication.translate(
                "DocumentViewManager",
                "Move the focus to the next document viewer"
            )
        )
        self._next_act.triggered.connect(self._mdi_area.activateNextSubWindow)

        self._previous_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "Pre&vious"), self)
        self._previous_act.setStatusTip(
            QApplication.translate(
                "DocumentViewManager",
                "Move the focus to the previous document viewer"
            )
        )
        self._previous_act.triggered.connect(
            self._mdi_area.activatePreviousSubWindow
        )

        self._separator_act = QAction(self)
        self._separator_act.setSeparator(True)

        self.update_window_menu()
        self._window_menu.aboutToShow.connect(self.update_window_menu)

    def cascade_windows(self):
        #Cascade document windows
        self._mdi_area.cascadeSubWindows()

    def tile_windows(self):
        #Arrange document windows to occupy the available space in mdi area
        self._mdi_area.tileSubWindows()

    def update_actions(self):
        if self._mdi_area.activeSubWindow():
            has_mdi_child = True

        else:
            has_mdi_child = False

        self._close_act.setEnabled(has_mdi_child)
        self._close_all_act.setEnabled(has_mdi_child)
        self._tile_act.setEnabled(has_mdi_child)
        self._cascade_act.setEnabled(has_mdi_child)
        self._previous_act.setEnabled(has_mdi_child)
        self._next_act.setEnabled(has_mdi_child)
        self._separator_act.setVisible(has_mdi_child)

    def update_window_menu(self):
        self._window_menu.clear()
        self._window_menu.addAction(self._close_act)
        self._window_menu.addAction(self._close_all_act)
        self._window_menu.addSeparator()
        self._window_menu.addAction(self._tile_act)
        self._window_menu.addAction(self._cascade_act)
        self._window_menu.addSeparator()
        self._window_menu.addAction(self._next_act)
        self._window_menu.addAction(self._previous_act)
        self._window_menu.addAction(self._separator_act)

        windows = self._mdi_area.subWindowList()
        self._separator_act.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            text = "%d. %s" % (i + 1, window.windowTitle())

            win_action = self._window_menu.addAction(text)
            win_action.setCheckable(True)
            win_action.setChecked(window is self._mdi_area.activeSubWindow())
            win_action.triggered.connect(self._viewer_mapper.map)
            self._viewer_mapper.setMapping(win_action, window)

    def load_viewer(self, document_widget, visible=True):
        """
        Open a new instance of the viewer or activate an existing one if the
        document had been previously loaded.
        :param document_widget: Contains all the necessary information required
        to load the specific document.
        :type document_widget: DocumentWidget
        :param visible: True to show the view manager after the viewer has
        been loaded, otherwise it will be the responsibility of the caller to
        enable visibility.
        :type visible: bool
        :returns: True if the document was successfully loaded, else False.
        :rtype: bool
        """
        doc_identifier = document_widget.file_identifier()

        if doc_identifier in self._doc_viewers:

            doc_sw = self._doc_viewers[doc_identifier]

            self._mdi_area.setActiveSubWindow(doc_sw)
            doc_sw.showNormal()

        else:
            doc_viewer = self._create_viewer(document_widget)

            abs_doc_path = self.absolute_document_path(document_widget)

            if not QFile.exists(abs_doc_path):
                msg = QApplication.translate(
                    "DocumentViewManager",
                    "The selected document does not exist."
                    "\nPlease check the supporting documents' "
                    "repository setting."
                )
                QMessageBox.critical(
                    self,
                    QApplication.translate(
                        "DocumentViewManager","Invalid Document"
                    ),
                    msg
                )

                return False

            doc_viewer.load_document(abs_doc_path)

            self._doc_viewers[doc_identifier] = doc_viewer

            self._mdi_area.addSubWindow(doc_viewer)

            doc_viewer.show()

        if not self.isVisible() and visible:
            self.setVisible(True)

        if self.isMinimized():
            self.showNormal()

        self.center()

        return True

    def set_active_sub_window(self, viewer):
        if viewer:
            self._mdi_area.setActiveSubWindow(viewer)

    def absolute_document_path(self, document_widget):
        """
        Build the absolute document path using info from the document widget.
        :param document_widget: Instance of document widget.
        :return: Absolute path of the supporting document.
        :rtype: str
        """
        abs_path = ''

        file_manager = document_widget.fileManager
        if not file_manager is None:
            network_repository = file_manager.networkPath
            file_id = document_widget.file_identifier()
            source_entity = document_widget.doc_source_entity()
            profile_name = current_profile().name
            doc_type = document_widget.doc_type_value().lower().replace(
                ' ', '_'
            )
            file_name, file_extension = guess_extension(
                document_widget.displayName()
            )

            abs_path = network_repository + "/" +profile_name + '/' +\
                       unicode(source_entity) + "/" + unicode(doc_type) + "/" +\
                       unicode(file_id) + unicode(file_extension)

        return abs_path

    def reset(self):
        """
        Removes all document viewers in the view area.
        The QCloseEvent sent to each sub-window will decrement the register.
        """
        self._mdi_area.closeAllSubWindows()

    def _create_viewer(self, document_widget):
        """
        Creates a new instance of a document viewer.
        :param document_widget: Contains all
        the necessary information required
        to load the specific document.
        :return: Document viewer object
        :rtype: DocumentViewer
        """
        doc_viewer = DocumentViewer(
            self._mdi_area, document_widget.file_identifier()
        )
        doc_viewer.setAttribute(Qt.WA_DeleteOnClose)
        doc_viewer.setWindowTitle(
            document_widget.displayName()
        )

        # TODO: Incorporate logic for determining
        # TODO: viewer based on document type
        ph_viewer = PhotoViewer()

        # v_layout = QVBoxLayout()
        # v_layout.addWidget(ph_viewer)
        # doc_viewer.setLayout(v_layout)

        doc_viewer.set_view_widget(ph_viewer)

        doc_viewer.closed.connect(self._on_viewer_closed)

        return doc_viewer

    def remove_viewer(self, viewer_id):
        """
        Close and remove the viewer with the specified viewer ID.
        """
        if viewer_id in self._doc_viewers:
            viewer = self._doc_viewers[viewer_id]
            self._mdi_area.setActiveSubWindow(viewer)
            self._mdi_area.closeActiveSubWindow()

        self._on_viewer_closed(viewer_id)

    def _on_viewer_closed(self,file_id):
        """
        Slot raised when a document viewer is closed.
        """
        if file_id in self._doc_viewers:
            del self._doc_viewers[file_id]
class CaseSelectionWidget(QWidget):

    caseSelectionChanged = pyqtSignal()

    def __init__(self, current_case):
        QWidget.__init__(self)

        self.__model = PlotCaseModel()

        self.__signal_mapper = QSignalMapper(self)
        self.__case_selectors = {}
        self.__case_selectors_order = []

        layout = QVBoxLayout()

        add_button_layout = QHBoxLayout()
        button = QPushButton(util.resourceIcon("ide/small/add"), "Add case to plot")
        button.clicked.connect(self.addCaseSelector)

        add_button_layout.addStretch()
        add_button_layout.addWidget(button)
        add_button_layout.addStretch()

        layout.addLayout(add_button_layout)

        self.__case_layout = QVBoxLayout()
        self.__case_layout.setMargin(0)
        layout.addLayout(self.__case_layout)

        self.addCaseSelector(disabled=True, current_case=current_case)
        layout.addStretch()

        self.setLayout(layout)

        self.__signal_mapper.mapped[QWidget].connect(self.removeWidget)


    def __caseName(self, widget):
        """ @rtype: str """
        return str(self.__case_selectors[widget].currentText())

    def getPlotCaseNames(self):
        if self.__model.rowCount() == 0:
            return []

        return [self.__caseName(widget) for widget in self.__case_selectors_order]


    def addCaseSelector(self, disabled=False, current_case=None):
        if len(self.__case_selectors_order) == 5:
            return

        widget = QWidget()

        layout = QHBoxLayout()
        layout.setMargin(0)
        widget.setLayout(layout)

        combo = QComboBox()
        combo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLengthWithIcon)
        combo.setMinimumContentsLength(20)
        combo.setModel(self.__model)

        if current_case is not None:
            index = 0
            for item in self.__model:
                if item == current_case:
                    combo.setCurrentIndex(index)
                    break
                index += 1

        combo.currentIndexChanged.connect(self.caseSelectionChanged.emit)



        layout.addWidget(combo, 1)

        button = QToolButton()
        button.setAutoRaise(True)
        button.setDisabled(disabled)
        button.setIcon(util.resourceIcon("ide/small/delete"))
        button.clicked.connect(self.__signal_mapper.map)

        layout.addWidget(button)

        self.__case_selectors[widget] = combo
        self.__case_selectors_order.append(widget)
        self.__signal_mapper.setMapping(button, widget)

        self.__case_layout.addWidget(widget)

        self.caseSelectionChanged.emit()



    def removeWidget(self, widget):
        self.__case_layout.removeWidget(widget)
        del self.__case_selectors[widget]
        self.__case_selectors_order.remove(widget)
        widget.setParent(None)
        self.caseSelectionChanged.emit()
Beispiel #46
0
    def _create_connections(self):
        """ Creates connections in MainWindow """

        # TODO rewrite the connection to a modern style
        # Menu: File
        self.connect(self.ui.actionQuit, QtCore.SIGNAL('triggered()'),
                     QtCore.SLOT('close()'))
        self.connect(self.ui.actionOpen, QtCore.SIGNAL('triggered()'),
                     self._open_file)
        self.connect(self.ui.actionOpen_folder, QtCore.SIGNAL('triggered()'),
                     self._open_folder_dialog)

        # Menu: TOOLS
        self.connect(self.ui.actionConvert_files, QtCore.SIGNAL('triggered()'),
                     self._show_convert_files)
        self.connect(self.ui.actionDownload_CTU_UHB_data,
                     QtCore.SIGNAL('triggered()'), self._show_download_db)
        self.connect(self.ui.actionAttribute_selection,
                     QtCore.SIGNAL('triggered()'),
                     self._show_attribute_selection)
        self.connect(self.ui.actionExport_to_PDF, QtCore.SIGNAL('triggered()'),
                     self._export_to_pdf)
        # self.connect(self.ui.actionSet_Clear_Baseline, QtCore.SIGNAL('triggered()'), self._show_set_clear_bsln)
        self.connect(self.ui.actionSent_annotations,
                     QtCore.SIGNAL('triggered()'), self._show_sent_annotations)

        group_paper = QtGui.QActionGroup(self)
        self.ui.actionEU.setActionGroup(group_paper)
        self.ui.actionUS.setActionGroup(group_paper)
        self.connect(self.ui.actionEU, QtCore.SIGNAL('triggered()'),
                     self._set_paper)
        self.connect(self.ui.actionUS, QtCore.SIGNAL('triggered()'),
                     self._set_paper)
        ''' create dictionary in the following format: action: name '''
        e = EnumAnnType
        pui = self.ui
        dactions = {
            pui.actionCursor: e.select,
            pui.actionBasal: e.basal,
            pui.actionBaseline: e.baseline,
            pui.actionRecovery: e.recovery,
            pui.actionNo_recovery: e.no_recovery,
            pui.actionExcessive_UA: e.excessive_ua,
            pui.actionEllipse: e.ellipse,
            pui.actionEllipseNote: e.ellipsenote,
            pui.actionNote: e.note,
            pui.actionEvaluationNote: e.evaluation_note
        }

        if DEBUG_FIGO_ANN:
            dactions[pui.actionFloating_Baseline] = e.floating_baseline
            dactions[pui.actionAcceleration] = e.acceleration
            dactions[pui.actionDeceleration] = e.deceleration
            dactions[pui.actionUA] = e.uterine_contraction

        group_ann = QtGui.QActionGroup(self)
        for action in dactions.iterkeys():
            if isinstance(action, QtGui.QAction):  # just to check the type
                action.setActionGroup(group_ann)

        # self.ui.actionBasal.triggered.connect(self._debug_slot)
        # self.ui.actionBaseline.triggered.connect(self._set_annotation_action)

        signal_mapper = QSignalMapper(self)

        # signal_mapper.setMapping(self.ui.actionBaseline, 'baseline')
        # self.connect(self.ui.actionBaseline, QtCore.SIGNAL('triggered()'), signal_mapper.map)
        # self.connect(signal_mapper, QtCore.SIGNAL('mapped()'), self._set_annotation_action)

        # for d in dactions.iteritems():
        for action, name in dactions.iteritems():
            signal_mapper.setMapping(action, name)

            if isinstance(action, QtGui.QAction):  # just to check the type
                action.triggered.connect(signal_mapper.map)
                # self.connect(action, QtCore.SIGNAL('triggered()'), signal_mapper.map)

        signal_mapper.mapped[QtCore.QString].connect(self._ann_set_action)
        # self.connect(self.ui.actionUS, QtCore.SIGNAL('triggered()'), self._set_paper)
        # self.connect(signal_mapper, QtCore.SIGNAL('mapped()'), self._set_annotation_action)

        # signal_mapper = QtCore.QSignalMapper(self)
        #
        # # for d in dactions.iteritems():
        # for action, name in dactions.iteritems():
        #     signal_mapper.setMapping(action, name)
        #
        #     if isinstance(action, QtGui.QAction):  # just to check the type
        #         # action.triggered.connect(signal_mapper.map)
        #         self.connect(action, QtCore.SIGNAL('triggered()'), signal_mapper.map)
        #
        # # signal_mapper.mapped[QtCore.QString].connect(self._set_annotation_action)
        # # self.connect(self.ui.actionUS, QtCore.SIGNAL('triggered()'), self._set_paper)
        # self.connect(signal_mapper, QtCore.SIGNAL('mapped()'), self._set_annotation_action)

        # self.ui.actionAnnShowHide.triggered.connect(self._show_ann_show_hide)
        self.connect(self.ui.actionSave, QtCore.SIGNAL('triggered()'),
                     self._toolbar_ann_save)
        self.connect(self.ui.actionDelete, QtCore.SIGNAL('triggered()'),
                     self._toolbar_ann_delete)

        self.ui.actionCaliper.triggered.connect(self._caliper_set)
        self.ui.actionCaliperFHR.triggered.connect(self._caliper_set)
        self.ui.actionCaliperTOCO.triggered.connect(self._caliper_set)

        self.ui.actionFIGO_acc_dec.triggered.connect(
            self._caliper_set_figo_acc_dec)
        self.ui.actionFIGO_UA.triggered.connect(self._caliper_set_figo_ua)
        self.ui.actionCaliperReset.triggered.connect(self._caliper_reset)

        # Menu: View
        self.connect(self.ui.actionClinical_information,
                     QtCore.SIGNAL('triggered()'), self._dock_clin_info_toggle)
        self.connect(self.ui.dockClinInfo,
                     QtCore.SIGNAL("visibilityChanged(bool)"),
                     self._dock_clin_info_visibility)
        self.connect(self.ui.actionData_browser, QtCore.SIGNAL('triggered()'),
                     self._dock_databrowse_toggle)
        self.connect(self.ui.dockDataBrowser,
                     QtCore.SIGNAL("visibilityChanged(bool)"),
                     self._dock_databrowse_visibility)
        self.connect(self.ui.actionAnnToolbarVisible,
                     QtCore.SIGNAL('triggered()'), self._toolbar_ann_toggle)
        self.connect(self.ui.toolBar, QtCore.SIGNAL('visibilityChanged(bool)'),
                     self._toolbar_ann_visibility)
        self.connect(self.ui.actionAnnToolbarAlign_right,
                     QtCore.SIGNAL('triggered()'), self._toolbar_align)

        # Menu: Help
        self.connect(self.ui.actionAbout, QtCore.SIGNAL('triggered()'),
                     self._show_about)

        # SIGNALS
        self.ui.PlotWidget.fhrPlot.signal_ann_changed.connect(
            self._toolbar_ann_changed)
        self.ui.PlotWidget.tocoPlot.signal_ann_changed.connect(
            self._toolbar_ann_changed)
        self._attSelectForm.signal_sel_att_changed.connect(
            self._update_data_browser)

        if DEBUG_TOOLS is True:
            self.ui.actionDebug_CalibSignal.triggered.connect(
                self.plot_calibration_signal)

            if self._dataBrowserWidget.bDebugStageIICorrect:
                self._dataBrowserWidget.debug_stageI_signal.connect(
                    self.debug_plot_stage1)
Beispiel #47
0
class ImportData(QWizard, Ui_frmImport):
    def __init__(self,parent=None):
        QWizard.__init__(self,parent)
        self.setupUi(self) 
        self.curr_profile = current_profile()

        #Connect signals   
        self.btnBrowseSource.clicked.connect(self.setSourceFile)
        self.lstDestTables.itemClicked.connect(self.destSelectChanged)
        self.btnSrcUp.clicked.connect(self.srcItemUp)
        self.btnSrcDown.clicked.connect(self.srcItemDown)
        self.btnSrcAll.clicked.connect(self.checkSrcItems)
        self.btnSrcNone.clicked.connect(self.uncheckSrcItems)
        self.btnDestUp.clicked.connect(self.targetItemUp)
        self.btnDestDown.clicked.connect(self.targetItemDown)
        self.lstSrcFields.currentRowChanged[int].connect(self.sourceRowChanged)
        self.lstTargetFields.currentRowChanged[int].connect(self.destRowChanged)
        self.lstTargetFields.currentRowChanged[int].connect(self._enable_disable_trans_tools)
        self.chk_virtual.toggled.connect(self._on_load_virtual_columns)

        #Data Reader
        self.dataReader = None
         
        #Init
        self.registerFields()
        
        #Geometry columns
        self.geomcols = []

        #Initialize value translators from definitions
        self._init_translators()

        #self._set_target_fields_stylesheet()

    def _init_translators(self):
        translator_menu = QMenu(self)

        self._trans_widget_mgr = TranslatorWidgetManager(self)
        self._trans_signal_mapper = QSignalMapper(self)

        for trans_name, config in ValueTranslatorConfig.translators.iteritems():
            trans_action = QAction( u'{}...'.format(trans_name),
                translator_menu
            )

            self._trans_signal_mapper.setMapping(trans_action, trans_name)
            trans_action.triggered.connect(self._trans_signal_mapper.map)

            translator_menu.addAction(trans_action)

        if len(translator_menu.actions()) == 0:
            self.btn_add_translator.setEnabled(False)

        else:
            self.btn_add_translator.setMenu(translator_menu)

            self._trans_signal_mapper.mapped[str].connect(self._load_translator_dialog)

        self.btn_edit_translator.setEnabled(False)
        self.btn_delete_translator.setEnabled(False)

        self.btn_edit_translator.clicked.connect(self._on_edit_translator)
        self.btn_delete_translator.clicked.connect(self._on_delete_translator)

    def _load_translator_dialog(self, config_key):
        """
        Load translator dialog.
        """
        dest_column = self._selected_destination_column()
        src_column = self._selected_source_column()

        if dest_column:
            #Check if there is an existing dialog in the manager
            trans_dlg = self._trans_widget_mgr.translator_widget(dest_column)

            if trans_dlg is None:
                trans_config = ValueTranslatorConfig.translators.get(config_key, None)

                #Safety precaution
                if trans_config is None: return

                try:
                    trans_dlg = trans_config.create(
                        self,
                        self._source_columns(),
                        self.targetTab,
                        dest_column,
                        src_column
                    )

                except RuntimeError as re:
                    QMessageBox.critical(
                        self,
                        QApplication.translate(
                            'ImportData',
                            'Value Translator'
                        ),
                        unicode(re)
                    )

                    return

            self._handle_translator_dlg(dest_column, trans_dlg)

    def _handle_translator_dlg(self, key, dlg):
        if dlg.exec_() == QDialog.Accepted:
            self._trans_widget_mgr.add_widget(key, dlg)

        self._enable_disable_trans_tools()

    def _on_edit_translator(self):
        """
        Slot to load the translator widget specific for the selected column for editing.
        """
        dest_column = self._selected_destination_column()

        if dest_column:
            #Check if there is an existing dialog in the manager
            trans_dlg = self._trans_widget_mgr.translator_widget(dest_column)

            self._handle_translator_dlg(dest_column, trans_dlg)

    def _on_delete_translator(self):
        """
        Slot for deleting the translator widget for the selected column.
        """
        dest_column = self._selected_destination_column()

        self._delete_translator(dest_column)

    def _delete_translator(self, destination_column):
        if not destination_column:
            return

        res = self._trans_widget_mgr.remove_translator_widget(destination_column)

        self._enable_disable_trans_tools()

    def _enable_disable_trans_tools(self, index=-1):
        """
        Enable/disable appropriate value translator tools based on the selected
        column.
        """
        dest_column = self._selected_destination_column()

        if dest_column:
            #Check if there is an existing dialog in the manager
            trans_dlg = self._trans_widget_mgr.translator_widget(dest_column)

            if trans_dlg is None:
                self.btn_add_translator.setEnabled(True)
                self.btn_edit_translator.setEnabled(False)
                self.btn_delete_translator.setEnabled(False)

            else:
                self.btn_add_translator.setEnabled(False)
                self.btn_edit_translator.setEnabled(True)
                self.btn_delete_translator.setEnabled(True)

        else:
            self.btn_add_translator.setEnabled(False)
            self.btn_edit_translator.setEnabled(False)
            self.btn_delete_translator.setEnabled(False)

    def _selected_destination_column(self):
        dest_field_item = self.lstTargetFields.currentItem()

        if dest_field_item is None:
            return ""

        else:
            return dest_field_item.text()

    def _selected_source_column(self):
        src_field_item = self.lstSrcFields.currentItem()

        if src_field_item is None:
            return ""

        else:
            return src_field_item.text()

    def _set_target_fields_stylesheet(self):
        self.lstTargetFields.setStyleSheet("QListWidget#lstTargetFields::item:selected"
                                           " { selection-background-color: darkblue }")

    def registerFields(self):
        #Register wizard fields
        pgSource = self.page(0)
        pgSource.registerField("srcFile*",self.txtDataSource)
        pgSource.registerField("typeText",self.rbTextType)
        pgSource.registerField("typeSpatial",self.rbSpType)
        
        #Destination table configuration
        destConf = self.page(1)
        destConf.registerField("optAppend",self.rbAppend)
        destConf.registerField("optOverwrite",self.rbOverwrite)
        destConf.registerField("tabIndex*",self.lstDestTables)
        destConf.registerField("geomCol",self.geomClm,"currentText",SIGNAL("currentIndexChanged(int)"))
        
    def initializePage(self,pageid):
        #Re-implementation of wizard page initialization
        if pageid == 1:
            #Reference to checked listwidget item representing table name
            self.destCheckedItem=None
            self.geomClm.clear()
            
            if self.field("typeText"):
                self.loadTables("textual")
                self.geomClm.setEnabled(False)
                
            elif self.field("typeSpatial"):
                self.loadTables("spatial")
                self.geomClm.setEnabled(True)
                
        if pageid == 2:
            self.lstSrcFields.clear()
            self.lstTargetFields.clear()
            self.assignCols()
            self._enable_disable_trans_tools()

    def _source_columns(self):
        return self.dataReader.getFields()

    def assignCols(self):
        #Load source and target columns respectively
        srcCols = self._source_columns()
        
        for c in srcCols:
            srcItem = QListWidgetItem(c,self.lstSrcFields)
            srcItem.setCheckState(Qt.Unchecked)
            srcItem.setIcon(QIcon(":/plugins/stdm/images/icons/column.png"))
            self.lstSrcFields.addItem(srcItem)
            
        #Destination Columns
        tabIndex = int(self.field("tabIndex"))
        self.targetTab = self.destCheckedItem.text()
        targetCols = table_column_names(self.targetTab, False, True)

        #Remove geometry columns in the target columns list
        for gc in self.geomcols:            
            colIndex = getIndex(targetCols,gc)
            if colIndex != -1:
                targetCols.remove(gc)

        #Remove 'id' column if there
        id_idx = getIndex(targetCols, 'id')
        if id_idx != -1:
            targetCols.remove('id')

        self._add_target_table_columns(targetCols)

    def _add_target_table_columns(self, items, style=False):
        for item in items:
            list_item = QListWidgetItem(item)

            if style:
                color = QColor(0, 128, 255)
                list_item.setTextColor(color)

            self.lstTargetFields.addItem(list_item)
                
    def _on_load_virtual_columns(self, state):
        """
        Load/unload relationships in the list of destination table columns.
        """
        virtual_columns = self.dataReader.entity_virtual_columns(self.targetTab)

        if state:
            if len(virtual_columns) == 0:
                msg = QApplication.translate("ImportData",
                    "There are no virtual columns for the specified table.")
                QMessageBox.warning(
                    self,
                    QApplication.translate(
                        'ImportData',
                        'Import Data'
                    ),
                    msg
                )
                self.chk_virtual.setChecked(False)

                return

            self._add_target_table_columns(virtual_columns, True)

        else:
            self._remove_destination_table_fields(virtual_columns)

    def _remove_destination_table_fields(self, fields):
        """Remove the specified columns from the destination view."""
        for f in fields:
            list_items = self.lstTargetFields.findItems(f, Qt.MatchFixedString)
            if len(list_items) > 0:
                list_item = list_items[0]

                row = self.lstTargetFields.row(list_item)

                rem_item = self.lstTargetFields.takeItem(row)
                del rem_item

                #Delete translator if already defined for the given column
                self._delete_translator(f)

    def loadGeomCols(self, table):
        #Load geometry columns based on the selected table 
        self.geomcols = table_column_names(table, True, True)
        self.geomClm.clear()
        self.geomClm.addItems(self.geomcols)
                
    def loadTables(self, type):
        #Load textual or spatial tables
        self.lstDestTables.clear()
        tables = None
        if type == "textual":
            tables = profile_user_tables(self.curr_profile, False, True)
            
        elif type == "spatial":
            tables = profile_spatial_tables(self.curr_profile)
        if tables is not None:
            for t in tables:
                tabItem = QListWidgetItem(t,self.lstDestTables)
                tabItem.setCheckState(Qt.Unchecked)
                tabItem.setIcon(QIcon(":/plugins/stdm/images/icons/table.png"))
                self.lstDestTables.addItem(tabItem)
                
    def validateCurrentPage(self):
        #Validate the current page before proceeding to the next one
        validPage=True
        
        if not QFile.exists(unicode(self.field("srcFile"))):
            self.ErrorInfoMessage("The specified source file does not exist.")
            validPage = False
            
        else:
            if self.dataReader:
                self.dataReader.reset()
            self.dataReader = OGRReader(unicode(self.field("srcFile")))
            
            if not self.dataReader.isValid():
                self.ErrorInfoMessage("The source file could not be opened."
                                      "\nPlease check is the given file type "
                                      "is supported")
                validPage = False
                
        if self.currentId()==1:
            if self.destCheckedItem == None:                                                        
                self.ErrorInfoMessage("Please select the destination table.")
                validPage = False
                
        if self.currentId()==2:
            validPage = self.execImport()

        return validPage

    def setSourceFile(self):
        #Set the file path to the source file
        imageFilters = "Comma Separated Value (*.csv);;ESRI Shapefile (*.shp);;AutoCAD DXF (*.dxf)" 
        sourceFile = QFileDialog.getOpenFileName(self,"Select Source File",vectorFileDir(),imageFilters)
        if sourceFile != "":
            self.txtDataSource.setText(sourceFile) 
        
    def getSrcDestPairs(self):
        #Return the matched source and destination columns
        srcDest = {}
        for l in range(self.lstTargetFields.count()):
            if l < self.lstSrcFields.count():                
                srcItem = self.lstSrcFields.item(l)
                if srcItem.checkState() == Qt.Checked:
                    destItem = self.lstTargetFields.item(l)
                    srcDest[srcItem.text()] = destItem.text()
                    
        return srcDest
        
    def execImport(self):
        #Initiate the import process
        success = False
        matchCols = self.getSrcDestPairs()
        
        #Specify geometry column
        geom_column=None
        
        if self.field("typeSpatial"):
            geom_column = self.field("geomCol")
            
        # Ensure that user has selected at least one column if it is a
        # non-spatial table
        if len(matchCols) == 0:
            self.ErrorInfoMessage("Please select at least one source column.")
            return success

        value_translator_manager = self._trans_widget_mgr.translator_manager()
               
        # try:
        if self.field("optOverwrite"):
            entity = self.curr_profile.entity_by_name(self.targetTab)
            dependencies = entity.dependencies()
            view_dep = dependencies['views']
            entity_dep = [e.name for e in entity.children()]
            entities_dep_str = ', '.join(entity_dep)
            views_dep_str = ', '.join(view_dep)

            if len(entity_dep) > 0 or len(view_dep) > 0:
                del_msg = QApplication.translate(
                    'ImportData',
                    "Overwriting existing records will permanently \n"
                    "remove records from other tables linked to the \n"
                    "records. The following tables will be affected."
                    "\n{}\n{}"
                    "\nClick Yes to proceed importing or No to cancel.".
                        format(entities_dep_str, views_dep_str)
                )
                del_result = QMessageBox.critical(
                    self,
                    QApplication.translate(
                        "ImportData",
                        "Overwrite Import Data Warning"
                    ),
                    del_msg,
                    QMessageBox.Yes | QMessageBox.No
                )

                if del_result == QMessageBox.Yes:
                    self.dataReader.featToDb(
                        self.targetTab, matchCols, False, self, geom_column,
                        translator_manager=value_translator_manager
                    )
                    # Update directory info in the registry
                    setVectorFileDir(self.field("srcFile"))

                    self.InfoMessage(
                        "All features have been imported successfully!")

                else:
                    success = False
        else:
            self.dataReader.featToDb(
                self.targetTab, matchCols, True, self, geom_column,
                translator_manager=value_translator_manager
            )
            self.InfoMessage(
                "All features have been imported successfully!"
            )
            #Update directory info in the registry
            setVectorFileDir(self.field("srcFile"))
            success = True
        # except:
        #     self.ErrorInfoMessage(unicode(sys.exc_info()[1]))

        return success

    def _clear_dest_table_selections(self, exclude=None):
        #Clears checked items in destination table list view
        if exclude is None:
            exclude = []

        for i in range(self.lstDestTables.count()):
            item = self.lstDestTables.item(i)
            if item.checkState() == Qt.Checked and not item.text() in exclude:
                item.setCheckState(Qt.Unchecked)
        
    def destSelectChanged(self, item):
        """
        Handler when a list widget item is clicked,
        clears previous selections
        """
        if not self.destCheckedItem is None:
            if item.checkState() == Qt.Checked:
                self.destCheckedItem.setCheckState(Qt.Unchecked) 
            else:
                self.destCheckedItem = None 
              
        if item.checkState() == Qt.Checked:
            self.destCheckedItem = item

            #Ensure other selected items have been cleared
            self._clear_dest_table_selections(exclude=[item.text()])

            #Load geometry columns if selection is a spatial table
            if self.field("typeSpatial"):
                self.loadGeomCols(item.text())
                
    def syncRowSelection(self, srcList, destList):
        """
        Sync the selection of an srcList item to the corresponding one in
        the destination column list.
        """
        if (srcList.currentRow() + 1) <= destList.count():
            destList.setCurrentRow(srcList.currentRow())
            
    def sourceRowChanged(self):
        #Slot when the source list's current row changes
        self.syncRowSelection(self.lstSrcFields,self.lstTargetFields)
        
    def destRowChanged(self):
        #Slot when the destination list's current row changes
        self.syncRowSelection(self.lstTargetFields, self.lstSrcFields)
                
    def itemUp(self, listWidget):
        #Moves the selected item in the list widget one level up
        curIndex = listWidget.currentRow()
        curItem = listWidget.takeItem(curIndex)
        listWidget.insertItem(curIndex - 1, curItem)
        listWidget.setCurrentRow(curIndex - 1)
        
    def itemDown(self, listWidget):
        #Moves the selected item in the list widget one level down
        curIndex=listWidget.currentRow()
        curItem=listWidget.takeItem(curIndex)
        listWidget.insertItem(curIndex + 1,curItem)
        listWidget.setCurrentRow(curIndex + 1)
        
    def checkAllItems(self, listWidget, state):
        #Checks all items in the list widget
        for l in range(listWidget.count()):
            item=listWidget.item(l)
            if state:
                item.setCheckState(Qt.Checked)
            else:
                item.setCheckState(Qt.Unchecked)
                
    def checkSrcItems(self):
        #Slot for checking all source table columns
        self.checkAllItems(self.lstSrcFields, True)
        
    def uncheckSrcItems(self):
        #Slot for unchecking all source table columns
        self.checkAllItems(self.lstSrcFields, False)
        
    def srcItemUp(self):
        #Slot for moving source list item up
        self.itemUp(self.lstSrcFields)
        
    def srcItemDown(self):
        #Slot for moving source list item down
        self.itemDown(self.lstSrcFields)
    
    def targetItemUp(self):
        #Slot for moving target item up
        self.itemUp(self.lstTargetFields)
        
    def targetItemDown(self):
        #Slot for moving target item down
        self.itemDown(self.lstTargetFields)
         
    def keyPressEvent(self,e):
        """
        Override method for preventing the dialog from
        closing itself when the escape key is hit
        """
        if e.key() == Qt.Key_Escape:
            pass
        
    def InfoMessage(self, message):
        #Information message box        
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText(message)
        msg.exec_()
                  
    def ErrorInfoMessage(self, message):
        #Error Message Box
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Critical)
        msg.setText(message)
        msg.exec_()
    #
    # def drag_drop_handler(self, event):
    #     if event.source() == self:
    #         rows = set([mi.row() for mi in self.selectedIndexes()])
    #         targetRow = self.indexAt(event.pos()).row()
    #         rows.discard(targetRow)
    #         rows = sorted(rows)
    #         if not rows:
    #             return
    #         if targetRow == -1:
    #             targetRow = self.rowCount()
    #         for _ in range(len(rows)):
    #             self.insertRow(targetRow)
    #         rowMapping = dict()  # Src row to target row.
    #         for idx, row in enumerate(rows):
    #             if row < targetRow:
    #                 rowMapping[row] = targetRow + idx
    #             else:
    #                 rowMapping[row + len(rows)] = targetRow + idx
    #         colCount = self.columnCount()
    #         for srcRow, tgtRow in sorted(rowMapping.iteritems()):
    #             for col in range(0, colCount):
    #                 self.setItem(tgtRow, col, self.takeItem(srcRow, col))
    #         for row in reversed(sorted(rowMapping.iterkeys())):
    #             self.removeRow(row)
    #         event.accept()
    #         return


    def drag_move(self, e):
        e.accept()
    def __createToolbarsAndConnect(self):

        actionGroup = QActionGroup(self)
        actionGroup.addAction(self.actionImport)
        actionGroup.addAction(self.actionVyhledavani)
        actionGroup.addAction(self.actionZpracujZmeny)

        # QSignalMapper
        self.signalMapper = QSignalMapper(self)

        # connect to 'clicked' on all buttons
        self.connect(self.actionImport, SIGNAL(
            "triggered()"), self.signalMapper, SLOT("map()"))
        self.connect(self.actionVyhledavani, SIGNAL(
            "triggered()"), self.signalMapper, SLOT("map()"))
        self.connect(self.actionZpracujZmeny, SIGNAL(
            "triggered()"), self.signalMapper, SLOT("map()"))

        # setMapping on each button to the QStackedWidget index we'd like to
        # switch to
        self.signalMapper.setMapping(self.actionImport, 0)
        self.signalMapper.setMapping(self.actionVyhledavani, 2)
        self.signalMapper.setMapping(self.actionZpracujZmeny, 1)

        # connect mapper to stackedWidget
        self.connect(self.signalMapper, SIGNAL("mapped(int)"),
                     self.stackedWidget, SLOT("setCurrentIndex(int)"))
        self.actionImport.trigger()

        self.connect(self.vfkBrowser, SIGNAL(
            "switchToPanelImport"), self.switchToImport)
        self.connect(self.vfkBrowser, SIGNAL(
            "switchToPanelSearch"), self.switchToSearch)
        self.connect(self.vfkBrowser, SIGNAL(
            "switchToPanelChanges"), self.switchToChanges)

        # Browser toolbar
        # ---------------
        self.__mBrowserToolbar = QToolBar(self)
        self.connect(self.actionBack, SIGNAL(
            "triggered()"), self.vfkBrowser.goBack)
        self.connect(self.actionForward, SIGNAL(
            "triggered()"), self.vfkBrowser.goForth)

        self.connect(self.actionSelectBudInMap,
                     SIGNAL("triggered()"), self.selectBudInMap)
        self.connect(self.actionSelectParInMap,
                     SIGNAL("triggered()"), self.selectParInMap)
        self.connect(self.actionCuzkPage,
                     SIGNAL("triggered()"), self.showOnCuzk)

        self.connect(self.actionExportLatex,
                     SIGNAL("triggered()"), self.latexExport)
        self.connect(self.actionExportHtml,
                     SIGNAL("triggered()"), self.htmlExport)

        self.connect(self.actionShowInfoaboutSelection, SIGNAL(
            "toggled(bool)"), self.setSelectionChangedConnected)
        self.connect(self.actionShowHelpPage, SIGNAL(
            "triggered()"), self.vfkBrowser.showHelpPage)

        self.loadVfkButton.clicked.connect(self.loadVfkButton_clicked)

        self.__browseButtons['browseButton_1'] = self.browseButton
        self.__browseButtons['browseButton_1'].clicked.connect(
            lambda: self.browseButton_clicked(int('{}'.format(len(self.__vfkLineEdits)))))

        self.__vfkLineEdits['vfkLineEdit_1'] = self.vfkFileLineEdit

        bt = QToolButton(self.__mBrowserToolbar)
        bt.setPopupMode(QToolButton.InstantPopup)
        bt.setText("Export ")

        menu = QMenu(bt)
        menu.addAction(self.actionExportLatex)
        menu.addAction(self.actionExportHtml)
        bt.setMenu(menu)

        # add actions to toolbar icons
        self.__mBrowserToolbar.addAction(self.actionImport)
        self.__mBrowserToolbar.addAction(self.actionVyhledavani)
        self.__mBrowserToolbar.addAction(self.actionZpracujZmeny)
        self.__mBrowserToolbar.addSeparator()
        self.__mBrowserToolbar.addAction(self.actionBack)
        self.__mBrowserToolbar.addAction(self.actionForward)
        self.__mBrowserToolbar.addAction(self.actionSelectParInMap)
        self.__mBrowserToolbar.addAction(self.actionSelectBudInMap)
        self.__mBrowserToolbar.addAction(self.actionCuzkPage)
        self.__mBrowserToolbar.addSeparator()
        self.__mBrowserToolbar.addAction(self.actionShowInfoaboutSelection)
        self.__mBrowserToolbar.addSeparator()
        self.__mBrowserToolbar.addWidget(bt)
        self.__mBrowserToolbar.addSeparator()
        self.__mBrowserToolbar.addAction(self.actionShowHelpPage)

        self.rightWidgetLayout.insertWidget(0, self.__mBrowserToolbar)

        # connect signals from vfkbrowser when changing history
        self.connect(self.vfkBrowser, SIGNAL(
            "currentParIdsChanged"), self.actionSelectParInMap.setEnabled)
        self.connect(self.vfkBrowser, SIGNAL("currentBudIdsChanged"),
                     self.actionSelectBudInMap.setEnabled)
        self.connect(self.vfkBrowser, SIGNAL(
            "historyBefore"), self.actionBack.setEnabled)
        self.connect(self.vfkBrowser, SIGNAL(
            "historyAfter"), self.actionForward.setEnabled)
        self.connect(self.vfkBrowser, SIGNAL(
            "definitionPointAvailable"), self.actionCuzkPage.setEnabled)

        # add toolTips
        self.pb_nextFile.setToolTip(u'Přidej další soubor VFK')
        self.parCheckBox.setToolTip(u'Načti vrstvu parcel')
        self.budCheckBox.setToolTip(u'Načti vrstvu budov')

        # add new VFK file
        self.pb_nextFile.clicked.connect(self.__addRowToGridLayout)

        # widget apply changes
        self.pb_mainDb.clicked.connect(
            lambda: self.browseDb_clicked('mainDb'))
        self.pb_amendmentDb.clicked.connect(
            lambda: self.browseDb_clicked('amendmentDb'))
        self.pb_exportDb.clicked.connect(
            lambda: self.browseDb_clicked('exportDb'))

        self.pb_applyChanges.clicked.connect(self.applyChanges)
        self.pb_applyChanges.setEnabled(False)

        self.connect(self.changes_instance, SIGNAL("maxRangeProgressBar"), self.__setRangeProgressBarChanges)
        self.connect(self.changes_instance, SIGNAL("updateStatus"), self.__updateProgressBarChanges)
        self.connect(self.changes_instance, SIGNAL("finishedStatus"), self.__changesApplied)
        self.connect(self.changes_instance, SIGNAL("preprocessingDatabase"), self.__changesPreprocessingDatabase)

        # connect radio boxes
        self.rb_file.clicked.connect(self.radioButtonValue)
        self.rb_directory.clicked.connect(self.radioButtonValue)
Beispiel #49
0
    def __init__(self, parent=None):
        super(MainWindow, self).__init__()
        self._csvFilePath = ""
        self.serialport = serial.Serial()
        self.receiver_thread = readerThread(self)
        self.receiver_thread.setPort(self.serialport)
        self._localEcho = None

        self.setupUi(self)
        self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea)
        self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea)
        font = QtGui.QFont()
        font.setFamily(EDITOR_FONT)
        font.setPointSize(10)
        self.txtEdtOutput.setFont(font)
        self.txtEdtInput.setFont(font)
        self.quickSendTable.setFont(font)
        if UI_FONT is not None:
            font = QtGui.QFont()
            font.setFamily(UI_FONT)
            font.setPointSize(9)
            self.dockWidget_PortConfig.setFont(font)
            self.dockWidget_SendHex.setFont(font)
            self.dockWidget_QuickSend.setFont(font)
        self.setupFlatUi()
        self.onEnumPorts()

        icon = QtGui.QIcon(":/icon.ico")
        self.setWindowIcon(icon)
        self.actionAbout.setIcon(icon)

        icon = QtGui.QIcon(":/qt_logo_16.ico")
        self.actionAbout_Qt.setIcon(icon)

        self._viewGroup = QActionGroup(self)
        self._viewGroup.addAction(self.actionAscii)
        self._viewGroup.addAction(self.actionHex_lowercase)
        self._viewGroup.addAction(self.actionHEX_UPPERCASE)
        self._viewGroup.setExclusive(True)

        # bind events
        self.actionOpen_Cmd_File.triggered.connect(self.openCSV)
        self.actionSave_Log.triggered.connect(self.onSaveLog)
        self.actionExit.triggered.connect(self.onExit)

        self.actionOpen.triggered.connect(self.openPort)
        self.actionClose.triggered.connect(self.closePort)

        self.actionPort_Config_Panel.triggered.connect(self.onTogglePrtCfgPnl)
        self.actionQuick_Send_Panel.triggered.connect(self.onToggleQckSndPnl)
        self.actionSend_Hex_Panel.triggered.connect(self.onToggleHexPnl)
        self.dockWidget_PortConfig.visibilityChanged.connect(
            self.onVisiblePrtCfgPnl)
        self.dockWidget_QuickSend.visibilityChanged.connect(
            self.onVisibleQckSndPnl)
        self.dockWidget_SendHex.visibilityChanged.connect(self.onVisibleHexPnl)
        self.actionLocal_Echo.triggered.connect(self.onLocalEcho)
        self.actionAlways_On_Top.triggered.connect(self.onAlwaysOnTop)

        self.actionAscii.triggered.connect(self.onViewChanged)
        self.actionHex_lowercase.triggered.connect(self.onViewChanged)
        self.actionHEX_UPPERCASE.triggered.connect(self.onViewChanged)

        self.actionAbout.triggered.connect(self.onAbout)
        self.actionAbout_Qt.triggered.connect(self.onAboutQt)

        self.btnOpen.clicked.connect(self.onOpen)
        self.btnClear.clicked.connect(self.onClear)
        self.btnSaveLog.clicked.connect(self.onSaveLog)
        self.btnEnumPorts.clicked.connect(self.onEnumPorts)
        self.btnSendHex.clicked.connect(self.sendHex)

        self.receiver_thread.read.connect(self.receive)
        self.receiver_thread.exception.connect(self.readerExcept)
        self._signalMap = QSignalMapper(self)
        self._signalMap.mapped[int].connect(self.tableClick)

        # initial action
        self.actionHEX_UPPERCASE.setChecked(True)
        self.receiver_thread.setViewMode(VIEWMODE_HEX_UPPERCASE)
        self.initQuickSend()
        self.restoreLayout()
        self.moveScreenCenter()
        self.syncMenu()

        if self.isMaximized():
            self.setMaximizeButton("restore")
        else:
            self.setMaximizeButton("maximize")

        self.LoadSettings()
Beispiel #50
0
class MainWindow(QMainWindow, Ui_MainWindow):
    """docstring for MainWindow."""
    def __init__(self, parent=None):
        super(MainWindow, self).__init__()
        self._csvFilePath = ""
        self.serialport = serial.Serial()
        self.receiver_thread = readerThread(self)
        self.receiver_thread.setPort(self.serialport)
        self._localEcho = None

        self.setupUi(self)
        self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea)
        self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea)
        font = QtGui.QFont()
        font.setFamily(EDITOR_FONT)
        font.setPointSize(10)
        self.txtEdtOutput.setFont(font)
        self.txtEdtInput.setFont(font)
        self.quickSendTable.setFont(font)
        if UI_FONT is not None:
            font = QtGui.QFont()
            font.setFamily(UI_FONT)
            font.setPointSize(9)
            self.dockWidget_PortConfig.setFont(font)
            self.dockWidget_SendHex.setFont(font)
            self.dockWidget_QuickSend.setFont(font)
        self.setupFlatUi()
        self.onEnumPorts()

        icon = QtGui.QIcon(":/icon.ico")
        self.setWindowIcon(icon)
        self.actionAbout.setIcon(icon)

        icon = QtGui.QIcon(":/qt_logo_16.ico")
        self.actionAbout_Qt.setIcon(icon)

        self._viewGroup = QActionGroup(self)
        self._viewGroup.addAction(self.actionAscii)
        self._viewGroup.addAction(self.actionHex_lowercase)
        self._viewGroup.addAction(self.actionHEX_UPPERCASE)
        self._viewGroup.setExclusive(True)

        # bind events
        self.actionOpen_Cmd_File.triggered.connect(self.openCSV)
        self.actionSave_Log.triggered.connect(self.onSaveLog)
        self.actionExit.triggered.connect(self.onExit)

        self.actionOpen.triggered.connect(self.openPort)
        self.actionClose.triggered.connect(self.closePort)

        self.actionPort_Config_Panel.triggered.connect(self.onTogglePrtCfgPnl)
        self.actionQuick_Send_Panel.triggered.connect(self.onToggleQckSndPnl)
        self.actionSend_Hex_Panel.triggered.connect(self.onToggleHexPnl)
        self.dockWidget_PortConfig.visibilityChanged.connect(
            self.onVisiblePrtCfgPnl)
        self.dockWidget_QuickSend.visibilityChanged.connect(
            self.onVisibleQckSndPnl)
        self.dockWidget_SendHex.visibilityChanged.connect(self.onVisibleHexPnl)
        self.actionLocal_Echo.triggered.connect(self.onLocalEcho)
        self.actionAlways_On_Top.triggered.connect(self.onAlwaysOnTop)

        self.actionAscii.triggered.connect(self.onViewChanged)
        self.actionHex_lowercase.triggered.connect(self.onViewChanged)
        self.actionHEX_UPPERCASE.triggered.connect(self.onViewChanged)

        self.actionAbout.triggered.connect(self.onAbout)
        self.actionAbout_Qt.triggered.connect(self.onAboutQt)

        self.btnOpen.clicked.connect(self.onOpen)
        self.btnClear.clicked.connect(self.onClear)
        self.btnSaveLog.clicked.connect(self.onSaveLog)
        self.btnEnumPorts.clicked.connect(self.onEnumPorts)
        self.btnSendHex.clicked.connect(self.sendHex)

        self.receiver_thread.read.connect(self.receive)
        self.receiver_thread.exception.connect(self.readerExcept)
        self._signalMap = QSignalMapper(self)
        self._signalMap.mapped[int].connect(self.tableClick)

        # initial action
        self.actionHEX_UPPERCASE.setChecked(True)
        self.receiver_thread.setViewMode(VIEWMODE_HEX_UPPERCASE)
        self.initQuickSend()
        self.restoreLayout()
        self.moveScreenCenter()
        self.syncMenu()

        if self.isMaximized():
            self.setMaximizeButton("restore")
        else:
            self.setMaximizeButton("maximize")

        self.LoadSettings()

    def setupFlatUi(self):
        self._dragPos = self.pos()
        self._isDragging = False
        self.setMouseTracking(True)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setStyleSheet("""
            QWidget {
                background-color:#99d9ea;
                /*background-image: url(:/background.png);*/
                outline: 1px solid #0057ff;
            }
            QLabel {
                color:#202020;
                font-size:13px;
                font-family:Century;
            }
            
            QComboBox {
                color:#202020;
                font-size:13px;
                font-family:Century Schoolbook;
            }
            QComboBox {
                border: none;
                padding: 1px 18px 1px 3px;
            }
            QComboBox:editable {
                background: white;
            }
            QComboBox:!editable, QComboBox::drop-down:editable {
                background: #62c7e0;
            }
            QComboBox:!editable:hover, QComboBox::drop-down:editable:hover {
                background: #c7eaf3;
            }
            QComboBox:!editable:pressed, QComboBox::drop-down:editable:pressed {
                background: #35b6d7;
            }
            QComboBox:on {
                padding-top: 3px;
                padding-left: 4px;
            }
            QComboBox::drop-down {
                subcontrol-origin: padding;
                subcontrol-position: top right;
                width: 16px;
                border: none;
            }
            QComboBox::down-arrow {
                image: url(:/downarrow.png);
            }
            QComboBox::down-arrow:on {
                image: url(:/uparrow.png);
            }
            
            QGroupBox {
                color:#202020;
                font-size:12px;
                font-family:Century Schoolbook;
                border: 1px solid gray;
                margin-top: 15px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top left;
                left:5px;
                top:3px;
            }
            
            QCheckBox {
                color:#202020;
                spacing: 5px;
                font-size:12px;
                font-family:Century Schoolbook;
            }

            QScrollBar:horizontal {
                background-color:#99d9ea;
                border: none;
                height: 15px;
                margin: 0px 20px 0 20px;
            }
            QScrollBar::handle:horizontal {
                background: #61b9e1;
                min-width: 20px;
            }
            QScrollBar::add-line:horizontal {
                image: url(:/rightarrow.png);
                border: none;
                background: #7ecfe4;
                width: 20px;
                subcontrol-position: right;
                subcontrol-origin: margin;
            }
            QScrollBar::sub-line:horizontal {
                image: url(:/leftarrow.png);
                border: none;
                background: #7ecfe4;
                width: 20px;
                subcontrol-position: left;
                subcontrol-origin: margin;
            }
            
            QScrollBar:vertical {
                background-color:#99d9ea;
                border: none;
                width: 15px;
                margin: 20px 0px 20px 0px;
            }
            QScrollBar::handle::vertical {
                background: #61b9e1;
                min-height: 20px;
            }
            QScrollBar::add-line::vertical {
                image: url(:/downarrow.png);
                border: none;
                background: #7ecfe4;
                height: 20px;
                subcontrol-position: bottom;
                subcontrol-origin: margin;
            }
            QScrollBar::sub-line::vertical {
                image: url(:/uparrow.png);
                border: none;
                background: #7ecfe4;
                height: 20px;
                subcontrol-position: top;
                subcontrol-origin: margin;
            }
            
            QTableView {
                background-color: white;
                /*selection-background-color: #FF92BB;*/
                border: 1px solid #eeeeee;
                color: #2f2f2f;
            }
            QTableView::focus {
                /*border: 1px solid #2a7fff;*/
            }
            QTableView QTableCornerButton::section {
                border: none;
                border-right: 1px solid #eeeeee;
                border-bottom: 1px solid #eeeeee;
                background-color: #8ae6d2;
            }
            QTableView QWidget {
                background-color: white;
            }
            QTableView::item:focus {
                border: 1px red;
                background-color: transparent;
                color: #2f2f2f;
            }
            QHeaderView::section {
                border: none;
                border-right: 1px solid #eeeeee;
                border-bottom: 1px solid #eeeeee;
                padding-left: 2px;
                padding-right: 2px;
                color: #444444;
                background-color: #8ae6d2;
            }
            QTextEdit {
                background-color:white;
                color:#2f2f2f;
                border: 1px solid white;
            }
            QTextEdit::focus {
                border: 1px solid #2a7fff;
            }
            
            QPushButton {
                background-color:#30a7b8;
                border:none;
                color:#ffffff;
                font-size:14px;
                font-family:Century Schoolbook;
            }
            QPushButton:hover {
                background-color:#51c0d1;
            }
            QPushButton:pressed {
                background-color:#3a9ecc;
            }
            
            QMenuBar {
                color: #2f2f2f;
            }
            QMenuBar::item {
                background-color: transparent;
                margin: 8px 0px 0px 0px;
                padding: 1px 8px 1px 8px;
                height: 15px;
            }
            QMenuBar::item:selected {
                background: #51c0d1;
            }
            QMenuBar::item:pressed {
                
            }
            QMenu {
                color: #2f2f2f;
            }
            QMenu {
                margin: 2px;
            }
            QMenu::item {
                padding: 2px 25px 2px 21px;
                border: 1px solid transparent;
            }
            QMenu::item:selected {
                background: #51c0d1;
            }
            QMenu::icon {
                background: transparent;
                border: 2px inset transparent;
            }

            QDockWidget {
                font-size:13px;
                font-family:Century;
                color: #202020;
                titlebar-close-icon: none;
                titlebar-normal-icon: none;
            }
            QDockWidget::title {
                margin: 0;
                padding: 2px;
                subcontrol-origin: content;
                subcontrol-position: right top;
                text-align: left;
                background: #67baed;
                
            }
            QDockWidget::float-button {
                max-width: 12px;
                max-height: 12px;
                background-color:transparent;
                border:none;
                image: url(:/restore_inactive.png);
            }
            QDockWidget::float-button:hover {
                background-color:#227582;
                image: url(:/restore_active.png);
            }
            QDockWidget::float-button:pressed {
                padding: 0;
                background-color:#14464e;
                image: url(:/restore_active.png);
            }
            QDockWidget::close-button {
                max-width: 12px;
                max-height: 12px;
                background-color:transparent;
                border:none;
                image: url(:/close_inactive.png);
            }
            QDockWidget::close-button:hover {
                background-color:#ea5e00;
                image: url(:/close_active.png);
            }
            QDockWidget::close-button:pressed {
                background-color:#994005;
                image: url(:/close_active.png);
                padding: 0;
            }
            
        """)
        self.dockWidgetContents.setStyleSheet("""
            QPushButton {
                min-height:23px;
            }
        """)
        self.dockWidget_QuickSend.setStyleSheet("""
            QPushButton {
                background-color:#27b798;
                font-family:Consolas;
                font-size:12px;
                min-width:46px;
            }
            QPushButton:hover {
                background-color:#3bd5b4;
            }
            QPushButton:pressed {
                background-color:#1d8770;
            }
        """)
        self.dockWidgetContents_2.setStyleSheet("""
            QPushButton {
                min-height:23px;
                min-width:50px;
            }
        """)

        w = self.frameGeometry().width()
        self._minBtn = QPushButton(self)
        self._minBtn.setGeometry(w - 103, 0, 28, 24)
        self._minBtn.clicked.connect(self.onMinimize)
        self._minBtn.setStyleSheet("""
            QPushButton {
                background-color:transparent;
                border:none;
                outline: none;
                image: url(:/minimize_inactive.png);
            }
            QPushButton:hover {
                background-color:#227582;
                image: url(:/minimize_active.png);
            }
            QPushButton:pressed {
                background-color:#14464e;
                image: url(:/minimize_active.png);
            }
        """)

        self._maxBtn = QPushButton(self)
        self._maxBtn.setGeometry(w - 74, 0, 28, 24)
        self._maxBtn.clicked.connect(self.onMaximize)
        self.setMaximizeButton("maximize")

        self._closeBtn = QPushButton(self)
        self._closeBtn.setGeometry(w - 45, 0, 36, 24)
        self._closeBtn.clicked.connect(self.onExit)
        self._closeBtn.setStyleSheet("""
            QPushButton {
                background-color:transparent;
                border:none;
                outline: none;
                image: url(:/close_inactive.png);
            }
            QPushButton:hover {
                background-color:#ea5e00;
                image: url(:/close_active.png);
            }
            QPushButton:pressed {
                background-color:#994005;
                image: url(:/close_active.png);
            }
        """)

    def resizeEvent(self, event):
        w = event.size().width()
        self._minBtn.move(w - 103, 0)
        self._maxBtn.move(w - 74, 0)
        self._closeBtn.move(w - 45, 0)

    def onMinimize(self):
        self.showMinimized()

    def isMaximized(self):
        return ((self.windowState() == Qt.WindowMaximized))

    def onMaximize(self):
        if self.isMaximized():
            self.showNormal()
            self.setMaximizeButton("maximize")
        else:
            self.showMaximized()
            self.setMaximizeButton("restore")

    def setMaximizeButton(self, style):
        if "maximize" == style:
            self._maxBtn.setStyleSheet("""
                QPushButton {
                    background-color:transparent;
                    border:none;
                    outline: none;
                    image: url(:/maximize_inactive.png);
                }
                QPushButton:hover {
                    background-color:#227582;
                    image: url(:/maximize_active.png);
                }
                QPushButton:pressed {
                    background-color:#14464e;
                    image: url(:/maximize_active.png);
                }
            """)
        elif "restore" == style:
            self._maxBtn.setStyleSheet("""
                QPushButton {
                    background-color:transparent;
                    border:none;
                    outline: none;
                    image: url(:/restore_inactive.png);
                }
                QPushButton:hover {
                    background-color:#227582;
                    image: url(:/restore_active.png);
                }
                QPushButton:pressed {
                    background-color:#14464e;
                    image: url(:/restore_active.png);
                }
            """)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self._isDragging = True
            self._dragPos = event.globalPos() - self.pos()
        event.accept()

    def mouseMoveEvent(self, event):
        if event.buttons(
        ) and Qt.LeftButton and self._isDragging and not self.isMaximized():
            self.move(event.globalPos() - self._dragPos)
        event.accept()

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

    def SaveSettings(self):
        root = ET.Element("MyTerm")
        GUISettings = ET.SubElement(root, "GUISettings")

        PortCfg = ET.SubElement(GUISettings, "PortConfig")
        ET.SubElement(PortCfg, "port").text = self.cmbPort.currentText()
        ET.SubElement(PortCfg,
                      "baudrate").text = self.cmbBaudRate.currentText()
        ET.SubElement(PortCfg,
                      "databits").text = self.cmbDataBits.currentText()
        ET.SubElement(PortCfg, "parity").text = self.cmbParity.currentText()
        ET.SubElement(PortCfg,
                      "stopbits").text = self.cmbStopBits.currentText()
        ET.SubElement(
            PortCfg,
            "rtscts").text = self.chkRTSCTS.isChecked() and "on" or "off"
        ET.SubElement(
            PortCfg,
            "xonxoff").text = self.chkXonXoff.isChecked() and "on" or "off"

        View = ET.SubElement(GUISettings, "View")
        ET.SubElement(
            View, "LocalEcho"
        ).text = self.actionLocal_Echo.isChecked() and "on" or "off"
        ET.SubElement(
            View, "ReceiveView").text = self._viewGroup.checkedAction().text()

        with open(get_config_path('settings.xml'), 'w') as f:
            f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            f.write(
                ET.tostring(root, encoding='utf-8',
                            pretty_print=True).decode("utf-8"))

    def LoadSettings(self):
        if os.path.isfile(get_config_path("settings.xml")):
            with open(get_config_path("settings.xml"), 'r') as f:
                tree = safeET.parse(f)

            port = tree.findtext('GUISettings/PortConfig/port', default='')
            if port != '':
                self.cmbPort.setCurrentText(port)

            baudrate = tree.findtext('GUISettings/PortConfig/baudrate',
                                     default='38400')
            if baudrate != '':
                self.cmbBaudRate.setCurrentText(baudrate)

            databits = tree.findtext('GUISettings/PortConfig/databits',
                                     default='8')
            id = self.cmbDataBits.findText(databits)
            if id >= 0:
                self.cmbDataBits.setCurrentIndex(id)

            parity = tree.findtext('GUISettings/PortConfig/parity',
                                   default='None')
            id = self.cmbParity.findText(parity)
            if id >= 0:
                self.cmbParity.setCurrentIndex(id)

            stopbits = tree.findtext('GUISettings/PortConfig/stopbits',
                                     default='1')
            id = self.cmbStopBits.findText(stopbits)
            if id >= 0:
                self.cmbStopBits.setCurrentIndex(id)

            rtscts = tree.findtext('GUISettings/PortConfig/rtscts',
                                   default='off')
            if 'on' == rtscts:
                self.chkRTSCTS.setChecked(True)
            else:
                self.chkRTSCTS.setChecked(False)

            xonxoff = tree.findtext('GUISettings/PortConfig/xonxoff',
                                    default='off')
            if 'on' == xonxoff:
                self.chkXonXoff.setChecked(True)
            else:
                self.chkXonXoff.setChecked(False)

            LocalEcho = tree.findtext('GUISettings/View/LocalEcho',
                                      default='off')
            if 'on' == LocalEcho:
                self.actionLocal_Echo.setChecked(True)
                self._localEcho = True
            else:
                self.actionLocal_Echo.setChecked(False)
                self._localEcho = False

            ReceiveView = tree.findtext('GUISettings/View/ReceiveView',
                                        default='HEX(UPPERCASE)')
            if 'Ascii' in ReceiveView:
                self.actionAscii.setChecked(True)
            elif 'lowercase' in ReceiveView:
                self.actionHex_lowercase.setChecked(True)
            elif 'UPPERCASE' in ReceiveView:
                self.actionHEX_UPPERCASE.setChecked(True)

    def closeEvent(self, event):
        self.saveLayout()
        self.saveCSV()
        self.SaveSettings()
        event.accept()

    def tableClick(self, row):
        self.sendTableRow(row)

    def initQuickSend(self):
        #self.quickSendTable.horizontalHeader().setDefaultSectionSize(40)
        #self.quickSendTable.horizontalHeader().setMinimumSectionSize(25)
        self.quickSendTable.setRowCount(50)
        self.quickSendTable.setColumnCount(20)

        for row in range(50):
            item = QPushButton(str("Send"))
            item.clicked.connect(self._signalMap.map)
            self._signalMap.setMapping(item, row)
            self.quickSendTable.setCellWidget(row, 0, item)
            self.quickSendTable.setRowHeight(row, 20)

        if os.path.isfile(get_config_path('QckSndBckup.csv')):
            self.loadCSV(get_config_path('QckSndBckup.csv'))

        self.quickSendTable.resizeColumnsToContents()

    def openCSV(self):
        fileName = QFileDialog.getOpenFileName(self, "Select a file",
                                               os.getcwd(),
                                               "CSV Files (*.csv)")
        if fileName:
            self.loadCSV(fileName, notifyExcept=True)

    def saveCSV(self):
        # scan table
        rows = self.quickSendTable.rowCount()
        cols = self.quickSendTable.columnCount()

        tmp_data = [[
            self.quickSendTable.item(row, col) is not None
            and self.quickSendTable.item(row, col).text() or ''
            for col in range(1, cols)
        ] for row in range(rows)]

        data = []
        # delete trailing blanks
        for row in tmp_data:
            for idx, d in enumerate(row[::-1]):
                if '' != d:
                    break
            new_row = row[:len(row) - idx]
            data.append(new_row)

        #import pprint
        #pprint.pprint(data, width=120, compact=True)

        # write to file
        with open(get_config_path('QckSndBckup.csv'), 'w') as csvfile:
            csvwriter = csv.writer(csvfile, delimiter=',', lineterminator='\n')
            csvwriter.writerows(data)

    def loadCSV(self, path, notifyExcept=False):
        data = []
        set_rows = 0
        set_cols = 0
        try:
            with open(path) as csvfile:
                csvData = csv.reader(csvfile)
                for row in csvData:
                    data.append(row)
                    set_rows = set_rows + 1
                    if len(row) > set_cols:
                        set_cols = len(row)
        except IOError as e:
            print("({})".format(e))
            if notifyExcept:
                QMessageBox.critical(self, "Open failed", str(e),
                                     QMessageBox.Close)
            return

        rows = self.quickSendTable.rowCount()
        cols = self.quickSendTable.columnCount()
        # clear table
        for col in range(cols):
            for row in range(rows):
                self.quickSendTable.setItem(row, col, QTableWidgetItem(""))

        self._csvFilePath = path
        if (cols -
                1) < set_cols:  # first colume is used by the "send" buttons.
            cols = set_cols + 10
            self.quickSendTable.setColumnCount(cols)
        if rows < set_rows:
            rows = set_rows + 20
            self.quickSendTable.setRowCount(rows)

        for row, rowdat in enumerate(data):
            if len(rowdat) > 0:
                for col, cell in enumerate(rowdat, 1):
                    self.quickSendTable.setItem(row, col,
                                                QTableWidgetItem(str(cell)))

        self.quickSendTable.resizeColumnsToContents()
        #self.quickSendTable.resizeRowsToContents()

    def sendTableRow(self, row):
        cols = self.quickSendTable.columnCount()
        try:
            data = [
                '0' + self.quickSendTable.item(row, col).text()
                for col in range(1, cols)
                if self.quickSendTable.item(row, col) is not None
                and self.quickSendTable.item(row, col).text() is not ''
            ]
        except:
            print("Exception in get table data(row = %d)" % (row + 1))
        else:
            tmp = [d[-2] + d[-1] for d in data if len(d) >= 2]
            for t in tmp:
                if not is_hex(t):
                    QMessageBox.critical(self, "Error",
                                         "'%s' is not hexadecimal." % (t),
                                         QMessageBox.Close)
                    return

            h = [int(t, 16) for t in tmp]
            self.transmitHex(h)

    def sendHex(self):
        hexStr = self.txtEdtInput.toPlainText()
        hexStr = ''.join(hexStr.split(" "))

        hexarray = []
        for i in range(0, len(hexStr), 2):
            hexarray.append(int(hexStr[i:i + 2], 16))

        self.transmitHex(hexarray)

    def readerExcept(self, e):
        self.closePort()
        QMessageBox.critical(self, "Read failed", str(e), QMessageBox.Close)

    def timestamp(self):
        return datetime.datetime.now().time().isoformat()[:-3]

    def receive(self, data):
        self.appendOutputText("\n%s R<-:%s" % (self.timestamp(), data))

    def appendOutputText(self, data, color=Qt.black):
        # the qEditText's "append" methon will add a unnecessary newline.
        # self.txtEdtOutput.append(data.decode('utf-8'))

        tc = self.txtEdtOutput.textColor()
        self.txtEdtOutput.moveCursor(QtGui.QTextCursor.End)
        self.txtEdtOutput.setTextColor(QtGui.QColor(color))
        self.txtEdtOutput.insertPlainText(data)
        self.txtEdtOutput.moveCursor(QtGui.QTextCursor.End)
        self.txtEdtOutput.setTextColor(tc)

    def transmitHex(self, hexarray):
        if len(hexarray) > 0:
            byteArray = bytearray(hexarray)
            if self.serialport.isOpen():
                try:
                    self.serialport.write(byteArray)
                except serial.SerialException as e:
                    print("Exception in transmitHex(%s)" % repr(hexarray))
                    QMessageBox.critical(self, "Exception in transmitHex",
                                         str(e), QMessageBox.Close)
                else:
                    # self.txCount += len( b )
                    # self.frame.statusbar.SetStatusText('Tx:%d' % self.txCount, 2)

                    text = ''.join(['%02X ' % i for i in hexarray])
                    self.appendOutputText(
                        "\n%s T->:%s" % (self.timestamp(), text), Qt.blue)

    def GetPort(self):
        return self.cmbPort.currentText()

    def GetDataBits(self):
        s = self.cmbDataBits.currentText()
        if s == '5':
            return serial.FIVEBITS
        elif s == '6':
            return serial.SIXBITS
        elif s == '7':
            return serial.SEVENBITS
        elif s == '8':
            return serial.EIGHTBITS

    def GetParity(self):
        s = self.cmbParity.currentText()
        if s == 'None':
            return serial.PARITY_NONE
        elif s == 'Even':
            return serial.PARITY_EVEN
        elif s == 'Odd':
            return serial.PARITY_ODD
        elif s == 'Mark':
            return serial.PARITY_MARK
        elif s == 'Space':
            return serial.PARITY_SPACE

    def GetStopBits(self):
        s = self.cmbStopBits.currentText()
        if s == '1':
            return serial.STOPBITS_ONE
        elif s == '1.5':
            return serial.STOPBITS_ONE_POINT_FIVE
        elif s == '2':
            return serial.STOPBITS_TWO

    def openPort(self):
        if self.serialport.isOpen():
            return

        _port = self.GetPort()
        if '' == _port:
            QMessageBox.information(self, "Invalid parameters",
                                    "Port is empty.")
            return

        _baudrate = self.cmbBaudRate.currentText()
        if '' == _baudrate:
            QMessageBox.information(self, "Invalid parameters",
                                    "Baudrate is empty.")
            return

        self.serialport.port = _port
        self.serialport.baudrate = _baudrate
        self.serialport.bytesize = self.GetDataBits()
        self.serialport.stopbits = self.GetStopBits()
        self.serialport.parity = self.GetParity()
        self.serialport.rtscts = self.chkRTSCTS.isChecked()
        self.serialport.xonxoff = self.chkXonXoff.isChecked()
        # self.serialport.timeout  = THREAD_TIMEOUT
        # self.serialport.writeTimeout = SERIAL_WRITE_TIMEOUT
        try:
            self.serialport.open()
        except serial.SerialException as e:
            QMessageBox.critical(self, "Could not open serial port", str(e),
                                 QMessageBox.Close)
        else:
            self._start_reader()
            self.setWindowTitle("%s on %s [%s, %s%s%s%s%s]" % (
                appInfo.title,
                self.serialport.portstr,
                self.serialport.baudrate,
                self.serialport.bytesize,
                self.serialport.parity,
                self.serialport.stopbits,
                self.serialport.rtscts and ' RTS/CTS' or '',
                self.serialport.xonxoff and ' Xon/Xoff' or '',
            ))
            pal = self.btnOpen.palette()
            pal.setColor(QtGui.QPalette.Button, QtGui.QColor(0, 0xff, 0x7f))
            self.btnOpen.setAutoFillBackground(True)
            self.btnOpen.setPalette(pal)
            self.btnOpen.setText('Close')
            self.btnOpen.update()

    def closePort(self):
        if self.serialport.isOpen():
            self._stop_reader()
            self.serialport.close()
            self.setWindowTitle(appInfo.title)
            pal = self.btnOpen.style().standardPalette()
            self.btnOpen.setAutoFillBackground(True)
            self.btnOpen.setPalette(pal)
            self.btnOpen.setText('Open')
            self.btnOpen.update()

    def _start_reader(self):
        """Start reader thread"""
        self.receiver_thread.start()

    def _stop_reader(self):
        """Stop reader thread only, wait for clean exit of thread"""
        self.receiver_thread.join()

    def onTogglePrtCfgPnl(self):
        if self.actionPort_Config_Panel.isChecked():
            self.dockWidget_PortConfig.show()
        else:
            self.dockWidget_PortConfig.hide()

    def onToggleQckSndPnl(self):
        if self.actionQuick_Send_Panel.isChecked():
            self.dockWidget_QuickSend.show()
        else:
            self.dockWidget_QuickSend.hide()

    def onToggleHexPnl(self):
        if self.actionSend_Hex_Panel.isChecked():
            self.dockWidget_SendHex.show()
        else:
            self.dockWidget_SendHex.hide()

    def onVisiblePrtCfgPnl(self, visible):
        self.actionPort_Config_Panel.setChecked(visible)

    def onVisibleQckSndPnl(self, visible):
        self.actionQuick_Send_Panel.setChecked(visible)

    def onVisibleHexPnl(self, visible):
        self.actionSend_Hex_Panel.setChecked(visible)

    def onLocalEcho(self):
        self._localEcho = self.actionLocal_Echo.isChecked()

    def onAlwaysOnTop(self):
        if self.actionAlways_On_Top.isChecked():
            style = self.windowFlags()
            self.setWindowFlags(style | Qt.WindowStaysOnTopHint)
            self.show()
        else:
            style = self.windowFlags()
            self.setWindowFlags(style & ~Qt.WindowStaysOnTopHint)
            self.show()

    def onOpen(self):
        if self.serialport.isOpen():
            self.closePort()
        else:
            self.openPort()

    def onClear(self):
        self.txtEdtOutput.clear()

    def onSaveLog(self):
        fileName = QFileDialog.getSaveFileName(
            self, "Save as", os.getcwd(),
            "Log files (*.log);;Text files (*.txt);;All files (*.*)")
        if fileName:
            import codecs
            f = codecs.open(fileName, 'w', 'utf-8')
            f.write(self.txtEdtOutput.toPlainText())
            f.close()

    def moveScreenCenter(self):
        w = self.frameGeometry().width()
        h = self.frameGeometry().height()
        desktop = QDesktopWidget()
        screenW = desktop.screen().width()
        screenH = desktop.screen().height()
        self.setGeometry((screenW - w) / 2, (screenH - h) / 2, w, h)

    def onEnumPorts(self):
        for p in enum_ports():
            self.cmbPort.addItem(p)
        # self.cmbPort.update()

    def onAbout(self):
        q = QWidget()
        icon = QtGui.QIcon(":/icon.ico")
        q.setWindowIcon(icon)
        QMessageBox.about(q, "About MyTerm", appInfo.aboutme)

    def onAboutQt(self):
        QMessageBox.aboutQt(None)

    def onExit(self):
        if self.serialport.isOpen():
            self.closePort()
        self.close()

    def restoreLayout(self):
        if os.path.isfile(get_config_path("layout.dat")):
            try:
                f = open(get_config_path("layout.dat"), 'rb')
                geometry, state = pickle.load(f)
                self.restoreGeometry(geometry)
                self.restoreState(state)
            except Exception as e:
                print("Exception on restoreLayout, {}".format(e))
        else:
            try:
                f = QFile(':/default_layout.dat')
                f.open(QIODevice.ReadOnly)
                geometry, state = pickle.loads(f.readAll())
                self.restoreGeometry(geometry)
                self.restoreState(state)
            except Exception as e:
                print("Exception on restoreLayout, {}".format(e))

    def saveLayout(self):
        with open(get_config_path("layout.dat"), 'wb') as f:
            pickle.dump((self.saveGeometry(), self.saveState()), f)

    def syncMenu(self):
        self.actionPort_Config_Panel.setChecked(
            not self.dockWidget_PortConfig.isHidden())
        self.actionQuick_Send_Panel.setChecked(
            not self.dockWidget_QuickSend.isHidden())
        self.actionSend_Hex_Panel.setChecked(
            not self.dockWidget_SendHex.isHidden())

    def onViewChanged(self):
        checked = self._viewGroup.checkedAction()
        if checked is None:
            self.actionHEX_UPPERCASE.setChecked(True)
            self.receiver_thread.setViewMode(VIEWMODE_HEX_UPPERCASE)
        else:
            if 'Ascii' in checked.text():
                self.receiver_thread.setViewMode(VIEWMODE_ASCII)
            elif 'lowercase' in checked.text():
                self.receiver_thread.setViewMode(VIEWMODE_HEX_LOWERCASE)
            elif 'UPPERCASE' in checked.text():
                self.receiver_thread.setViewMode(VIEWMODE_HEX_UPPERCASE)
Beispiel #51
0
def main(icon_spec):
    app = QApplication(sys.argv)

    main_window = QMainWindow()

    def sigint_handler(*args):
        main_window.close()

    signal.signal(signal.SIGINT, sigint_handler)
    # the timer enables triggering the sigint_handler
    signal_timer = QTimer()
    signal_timer.start(100)
    signal_timer.timeout.connect(lambda: None)

    tool_bar = QToolBar()
    main_window.addToolBar(Qt.TopToolBarArea, tool_bar)

    table_view = QTableView()
    table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
    table_view.setSelectionMode(QAbstractItemView.SingleSelection)
    table_view.setSortingEnabled(True)
    main_window.setCentralWidget(table_view)

    proxy_model = QSortFilterProxyModel()
    proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
    proxy_model.setFilterKeyColumn(1)
    table_view.setModel(proxy_model)
    proxy_model.layoutChanged.connect(table_view.resizeRowsToContents)

    item_model = QStandardItemModel()
    proxy_model.setSourceModel(item_model)

    # get all icons and their available sizes
    QIcon.setThemeName("gnome")
    icons = []
    all_sizes = set([])
    for context, icon_names in icon_spec:
        for icon_name in icon_names:
            icon = QIcon.fromTheme(icon_name)
            sizes = []
            for size in icon.availableSizes():
                size = (size.width(), size.height())
                sizes.append(size)
                all_sizes.add(size)
            sizes.sort()
            icons.append({
                'context': context,
                'icon_name': icon_name,
                'icon': icon,
                'sizes': sizes,
            })
    all_sizes = list(all_sizes)
    all_sizes.sort()

    # input field for filter
    def filter_changed(value):
        proxy_model.setFilterRegExp(value)
        table_view.resizeRowsToContents()

    filter_line_edit = QLineEdit()
    filter_line_edit.setMaximumWidth(200)
    filter_line_edit.setPlaceholderText('Filter name')
    filter_line_edit.setToolTip(
        'Filter name optionally using regular expressions (' +
        QKeySequence(QKeySequence.Find).toString() + ')')
    filter_line_edit.textChanged.connect(filter_changed)
    tool_bar.addWidget(filter_line_edit)

    # actions to toggle visibility of available sizes/columns
    def action_toggled(index):
        column = 2 + index
        table_view.setColumnHidden(column,
                                   not table_view.isColumnHidden(column))
        table_view.resizeColumnsToContents()
        table_view.resizeRowsToContents()

    signal_mapper = QSignalMapper()
    for i, size in enumerate(all_sizes):
        action = QAction('%dx%d' % size, tool_bar)
        action.setCheckable(True)
        action.setChecked(True)
        tool_bar.addAction(action)
        action.toggled.connect(signal_mapper.map)
        signal_mapper.setMapping(action, i)
        # set tool tip and handle key sequence
        tool_tip = 'Toggle visibility of column'
        if i < 10:
            digit = ('%d' % (i + 1))[-1]
            tool_tip += ' (%s)' % QKeySequence('Ctrl+%s' % digit).toString()
        action.setToolTip(tool_tip)
    signal_mapper.mapped.connect(action_toggled)

    # label columns
    header_labels = ['context', 'name']
    for width, height in all_sizes:
        header_labels.append('%dx%d' % (width, height))
    item_model.setColumnCount(len(header_labels))
    item_model.setHorizontalHeaderLabels(header_labels)

    # fill rows
    item_model.setRowCount(len(icons))
    for row, icon_data in enumerate(icons):
        # context
        item = QStandardItem(icon_data['context'])
        item.setFlags(item.flags() ^ Qt.ItemIsEditable)
        item_model.setItem(row, 0, item)
        # icon name
        item = QStandardItem(icon_data['icon_name'])
        item.setFlags(item.flags() ^ Qt.ItemIsEditable)
        item_model.setItem(row, 1, item)
        for index_in_all_sizes, size in enumerate(all_sizes):
            column = 2 + index_in_all_sizes
            if size in icon_data['sizes']:
                # icon as pixmap to keep specific size
                item = QStandardItem('')
                pixmap = icon_data['icon'].pixmap(size[0], size[1])
                item.setData(pixmap, Qt.DecorationRole)
                item.setFlags(item.flags() ^ Qt.ItemIsEditable)
                item_model.setItem(row, column, item)
            else:
                # single space to be sortable against icons
                item = QStandardItem(' ')
                item.setFlags(item.flags() ^ Qt.ItemIsEditable)
                item_model.setItem(row, column, item)

    table_view.resizeColumnsToContents()
    # manually set row heights because resizeRowsToContents is not working properly
    for row, icon_data in enumerate(icons):
        if len(icon_data['sizes']) > 0:
            max_size = icon_data['sizes'][-1]
            table_view.setRowHeight(row, max_size[1])

    # enable focus find (ctrl+f) and toggle columns (ctrl+NUM)
    def main_window_keyPressEvent(self,
                                  event,
                                  old_keyPressEvent=QMainWindow.keyPressEvent):
        if event.matches(QKeySequence.Find):
            filter_line_edit.setFocus()
            return
        if event.modifiers() == Qt.ControlModifier and event.key(
        ) >= Qt.Key_0 and event.key() <= Qt.Key_9:
            index = event.key() - Qt.Key_1
            if event.key() == Qt.Key_0:
                index += 10
            action = signal_mapper.mapping(index)
            if action:
                action.toggle()
                return
        old_keyPressEvent(self, event)

    main_window.keyPressEvent = new.instancemethod(main_window_keyPressEvent,
                                                   table_view, None)

    # enable copy (ctrl+c) name of icon to clipboard
    def table_view_keyPressEvent(self,
                                 event,
                                 old_keyPressEvent=QTableView.keyPressEvent):
        if event.matches(QKeySequence.Copy):
            selection_model = self.selectionModel()
            if selection_model.hasSelection():
                index = selection_model.selectedRows()[0]
                source_index = self.model().mapToSource(index)
                item = self.model().sourceModel().item(source_index.row(), 1)
                icon_name = item.data(Qt.EditRole)
                app.clipboard().setText(icon_name.toString())
                return
        old_keyPressEvent(self, event)

    table_view.keyPressEvent = new.instancemethod(table_view_keyPressEvent,
                                                  table_view, None)
    print 'Icon Theme: ', QIcon.themeName()

    print 'Theme Search Paths:'
    for item in QIcon.themeSearchPaths():
        print item
    main_window.showMaximized()
    return app.exec_()
Beispiel #52
0
class ToolBox(QFrame):
    """
    A tool box widget.
    """
    # Emitted when a tab is toggled.
    tabToogled = Signal(int, bool)

    def setExclusive(self, exclusive):
        """
        Set exclusive tabs (only one tab can be open at a time).
        """
        if self.__exclusive != exclusive:
            self.__exclusive = exclusive
            self.__tabActionGroup.setExclusive(exclusive)
            checked = self.__tabActionGroup.checkedAction()
            if checked is None:
                # The action group can be out of sync with the actions state
                # when switching between exclusive states.
                actions_checked = [
                    page.action for page in self.__pages
                    if page.action.isChecked()
                ]
                if actions_checked:
                    checked = actions_checked[0]

            # Trigger/toggle remaining open pages
            if exclusive and checked is not None:
                for page in self.__pages:
                    if checked != page.action and page.action.isChecked():
                        page.action.trigger()

    def exclusive(self):
        """
        Are the tabs in the toolbox exclusive.
        """
        return self.__exclusive

    exclusive_ = Property(bool,
                          fget=exclusive,
                          fset=setExclusive,
                          designable=True,
                          doc="Exclusive tabs")

    def __init__(self, parent=None, **kwargs):
        QFrame.__init__(self, parent, **kwargs)

        self.__pages = []
        self.__tabButtonHeight = -1
        self.__tabIconSize = QSize()
        self.__exclusive = False
        self.__setupUi()

    def __setupUi(self):
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        # Scroll area for the contents.
        self.__scrollArea = \
                _ToolBoxScrollArea(self, objectName="toolbox-scroll-area")

        self.__scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.__scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.__scrollArea.setSizePolicy(QSizePolicy.MinimumExpanding,
                                        QSizePolicy.MinimumExpanding)
        self.__scrollArea.setFrameStyle(QScrollArea.NoFrame)
        self.__scrollArea.setWidgetResizable(True)

        # A widget with all of the contents.
        # The tabs/contents are placed in the layout inside this widget
        self.__contents = QWidget(self.__scrollArea,
                                  objectName="toolbox-contents")

        # The layout where all the tab/pages are placed
        self.__contentsLayout = QVBoxLayout()
        self.__contentsLayout.setContentsMargins(0, 0, 0, 0)
        self.__contentsLayout.setSizeConstraint(QVBoxLayout.SetMinAndMaxSize)
        self.__contentsLayout.setSpacing(0)

        self.__contents.setLayout(self.__contentsLayout)

        self.__scrollArea.setWidget(self.__contents)

        layout.addWidget(self.__scrollArea)

        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding)

        self.__tabActionGroup = \
                QActionGroup(self, objectName="toolbox-tab-action-group")

        self.__tabActionGroup.setExclusive(self.__exclusive)

        self.__actionMapper = QSignalMapper(self)
        self.__actionMapper.mapped[QObject].connect(self.__onTabActionToogled)

    def setTabButtonHeight(self, height):
        """
        Set the tab button height.
        """
        if self.__tabButtonHeight != height:
            self.__tabButtonHeight = height
            for page in self.__pages:
                page.button.setFixedHeight(height)

    def tabButtonHeight(self):
        """
        Return the tab button height.
        """
        return self.__tabButtonHeight

    def setTabIconSize(self, size):
        """
        Set the tab button icon size.
        """
        if self.__tabIconSize != size:
            self.__tabIconSize = size
            for page in self.__pages:
                page.button.setIconSize(size)

    def tabIconSize(self):
        """
        Return the tab icon size.
        """
        return self.__tabIconSize

    def tabButton(self, index):
        """
        Return the tab button at `index`
        """
        return self.__pages[index].button

    def tabAction(self, index):
        """
        Return open/close action for the tab at `index`.
        """
        return self.__pages[index].action

    def addItem(self, widget, text, icon=None, toolTip=None):
        """
        Append the `widget` in a new tab and return its index.

        Parameters
        ----------
        widget : :class:`QWidget`
            A widget to be inserted. The toolbox takes ownership
            of the widget.

        text : str
            Name/title of the new tab.

        icon : :class:`QIcon`, optional
            An icon for the tab button.

        toolTip : str, optional
            Tool tip for the tab button.

        """
        return self.insertItem(self.count(), widget, text, icon, toolTip)

    def insertItem(self, index, widget, text, icon=None, toolTip=None):
        """
        Insert the `widget` in a new tab at position `index`.

        See also
        --------
        ToolBox.addItem

        """
        button = self.createTabButton(widget, text, icon, toolTip)

        self.__contentsLayout.insertWidget(index * 2, button)
        self.__contentsLayout.insertWidget(index * 2 + 1, widget)

        widget.hide()

        page = _ToolBoxPage(index, widget, button.defaultAction(), button)
        self.__pages.insert(index, page)

        for i in range(index + 1, self.count()):
            self.__pages[i] = self.__pages[i]._replace(index=i)

        self.__updatePositions()

        # Show (open) the first tab.
        if self.count() == 1 and index == 0:
            page.action.trigger()

        self.__updateSelected()

        self.updateGeometry()
        return index

    def removeItem(self, index):
        """
        Remove the widget at `index`.

        .. note:: The widget hidden but is is not deleted.

        """
        self.__contentsLayout.takeAt(2 * index + 1)
        self.__contentsLayout.takeAt(2 * index)
        page = self.__pages.pop(index)

        # Update the page indexes
        for i in range(index, self.count()):
            self.__pages[i] = self.__pages[i]._replace(index=i)

        page.button.deleteLater()

        # Hide the widget and reparent to self
        # This follows QToolBox.removeItem
        page.widget.hide()
        page.widget.setParent(self)

        self.__updatePositions()
        self.__updateSelected()

        self.updateGeometry()

    def count(self):
        """
        Return the number of widgets inserted in the toolbox.
        """
        return len(self.__pages)

    def widget(self, index):
        """
        Return the widget at `index`.
        """
        return self.__pages[index].widget

    def createTabButton(self, widget, text, icon=None, toolTip=None):
        """
        Create the tab button for `widget`.
        """
        action = QAction(text, self)
        action.setCheckable(True)

        if icon:
            action.setIcon(icon)

        if toolTip:
            action.setToolTip(toolTip)
        self.__tabActionGroup.addAction(action)
        self.__actionMapper.setMapping(action, action)
        action.toggled.connect(self.__actionMapper.map)

        button = ToolBoxTabButton(self, objectName="toolbox-tab-button")
        button.setDefaultAction(action)
        button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        if self.__tabIconSize.isValid():
            button.setIconSize(self.__tabIconSize)

        if self.__tabButtonHeight > 0:
            button.setFixedHeight(self.__tabButtonHeight)

        return button

    def ensureWidgetVisible(self, child, xmargin=50, ymargin=50):
        """
        Scroll the contents so child widget instance is visible inside
        the viewport.

        """
        self.__scrollArea.ensureWidgetVisible(child, xmargin, ymargin)

    def sizeHint(self):
        hint = self.__contentsLayout.sizeHint()

        if self.count():
            # Compute max width of hidden widgets also.
            scroll = self.__scrollArea
            scroll_w = scroll.verticalScrollBar().sizeHint().width()
            frame_w = self.frameWidth() * 2 + scroll.frameWidth() * 2
            max_w = max([p.widget.sizeHint().width() for p in self.__pages])
            hint = QSize(
                max(max_w, hint.width()) + scroll_w + frame_w, hint.height())

        return QSize(200, 200).expandedTo(hint)

    def __onTabActionToogled(self, action):
        page = find(self.__pages, action, key=attrgetter("action"))
        on = action.isChecked()
        page.widget.setVisible(on)
        index = page.index

        if index > 0:
            # Update the `previous` tab buttons style hints
            previous = self.__pages[index - 1].button
            flag = QStyleOptionToolBoxV2.NextIsSelected
            if on:
                previous.selected |= flag
            else:
                previous.selected &= ~flag

            previous.update()

        if index < self.count() - 1:
            next = self.__pages[index + 1].button
            flag = QStyleOptionToolBoxV2.PreviousIsSelected
            if on:
                next.selected |= flag
            else:
                next.selected &= ~flag

            next.update()

        self.tabToogled.emit(index, on)

        self.__contentsLayout.invalidate()

    def __updateSelected(self):
        """Update the tab buttons selected style flags.
        """
        if self.count() == 0:
            return

        opt = QStyleOptionToolBoxV2

        def update(button, next_sel, prev_sel):
            if next_sel:
                button.selected |= opt.NextIsSelected
            else:
                button.selected &= ~opt.NextIsSelected

            if prev_sel:
                button.selected |= opt.PreviousIsSelected
            else:
                button.selected &= ~opt.PreviousIsSelected

            button.update()

        if self.count() == 1:
            update(self.__pages[0].button, False, False)
        elif self.count() >= 2:
            pages = self.__pages
            for i in range(1, self.count() - 1):
                update(pages[i].button, pages[i + 1].action.isChecked(),
                       pages[i - 1].action.isChecked())

    def __updatePositions(self):
        """Update the tab buttons position style flags.
        """
        if self.count() == 0:
            return
        elif self.count() == 1:
            self.__pages[0].button.position = QStyleOptionToolBoxV2.OnlyOneTab
        else:
            self.__pages[0].button.position = QStyleOptionToolBoxV2.Beginning
            self.__pages[-1].button.position = QStyleOptionToolBoxV2.End
            for p in self.__pages[1:-1]:
                p.button.position = QStyleOptionToolBoxV2.Middle

        for p in self.__pages:
            p.button.update()
Beispiel #53
0
class ToolGrid(QFrame):
    """
    A widget containing a grid of actions/buttons.

    Actions can be added using standard :func:`QWidget.addAction(QAction)`
    and :func:`QWidget.insertAction(int, QAction)` methods.

    Parameters
    ----------
    parent : :class:`QWidget`
        Parent widget.
    columns : int
        Number of columns in the grid layout.
    buttonSize : :class:`QSize`, optional
        Size of tool buttons in the grid.
    iconSize : :class:`QSize`, optional
        Size of icons in the buttons.
    toolButtonStyle : :class:`Qt.ToolButtonStyle`
        Tool button style.

    """

    actionTriggered = Signal(QAction)
    actionHovered = Signal(QAction)

    def __init__(self,
                 parent=None,
                 columns=4,
                 buttonSize=None,
                 iconSize=None,
                 toolButtonStyle=Qt.ToolButtonTextUnderIcon):
        QFrame.__init__(self, parent)

        if buttonSize is not None:
            buttonSize = QSize(buttonSize)

        if iconSize is not None:
            iconSize = QSize(iconSize)

        self.__columns = columns
        self.__buttonSize = buttonSize or QSize(50, 50)
        self.__iconSize = iconSize or QSize(26, 26)
        self.__toolButtonStyle = toolButtonStyle

        self.__gridSlots = []

        self.__buttonListener = ToolButtonEventListener(self)
        self.__buttonListener.buttonRightClicked.connect(
            self.__onButtonRightClick)

        self.__buttonListener.buttonEnter.connect(self.__onButtonEnter)

        self.__mapper = QSignalMapper()
        self.__mapper.mapped[QObject].connect(self.__onClicked)

        self.__setupUi()

    def __setupUi(self):
        layout = QGridLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.setSizeConstraint(QGridLayout.SetFixedSize)
        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding)

    def setButtonSize(self, size):
        """
        Set the button size.
        """
        if self.__buttonSize != size:
            self.__buttonSize = size
            for slot in self.__gridSlots:
                slot.button.setFixedSize(size)

    def buttonSize(self):
        """
        Return the button size.
        """
        return QSize(self.__buttonSize)

    def setIconSize(self, size):
        """
        Set the button icon size.
        """
        if self.__iconSize != size:
            self.__iconSize = size
            for slot in self.__gridSlots:
                slot.button.setIconSize(size)

    def iconSize(self):
        """
        Return the icon size
        """
        return QSize(self.__iconSize)

    def setToolButtonStyle(self, style):
        """
        Set the tool button style.
        """
        if self.__toolButtonStyle != style:
            self.__toolButtonStyle = style
            for slot in self.__gridSlots:
                slot.button.setToolButtonStyle(style)

    def toolButtonStyle(self):
        """
        Return the tool button style.
        """
        return self.__toolButtonStyle

    def setColumnCount(self, columns):
        """
        Set the number of button/action columns.
        """
        if self.__columns != columns:
            self.__columns = columns
            self.__relayout()

    def columns(self):
        """
        Return the number of columns in the grid.
        """
        return self.__columns

    def clear(self):
        """
        Clear all actions/buttons.
        """
        for slot in reversed(list(self.__gridSlots)):
            self.removeAction(slot.action)
        self.__gridSlots = []

    def insertAction(self, before, action):
        """
        Insert a new action at the position currently occupied
        by `before` (can also be an index).

        Parameters
        ----------
        before : :class:`QAction` or int
            Position where the `action` should be inserted.
        action : :class:`QAction`
            Action to insert

        """
        if isinstance(before, int):
            actions = list(self.actions())
            if len(actions) == 0 or before >= len(actions):
                # Insert as the first action or the last action.
                return self.addAction(action)

            before = actions[before]

        return QFrame.insertAction(self, before, action)

    def setActions(self, actions):
        """
        Clear the grid and add `actions`.
        """
        self.clear()

        for action in actions:
            self.addAction(action)

    def buttonForAction(self, action):
        """
        Return the :class:`QToolButton` instance button for `action`.
        """
        actions = [slot.action for slot in self.__gridSlots]
        index = actions.index(action)
        return self.__gridSlots[index].button

    def createButtonForAction(self, action):
        """
        Create and return a :class:`QToolButton` for action.
        """
        button = _ToolGridButton(self)
        button.setDefaultAction(action)

        if self.__buttonSize.isValid():
            button.setFixedSize(self.__buttonSize)
        if self.__iconSize.isValid():
            button.setIconSize(self.__iconSize)

        button.setToolButtonStyle(self.__toolButtonStyle)
        button.setProperty("tool-grid-button", QVariant(True))
        return button

    def count(self):
        """
        Return the number of buttons/actions in the grid.
        """
        return len(self.__gridSlots)

    def actionEvent(self, event):
        QFrame.actionEvent(self, event)

        if event.type() == QEvent.ActionAdded:
            # Note: the action is already in the self.actions() list.
            actions = list(self.actions())
            index = actions.index(event.action())
            self.__insertActionButton(index, event.action())

        elif event.type() == QEvent.ActionRemoved:
            self.__removeActionButton(event.action())

    def __insertActionButton(self, index, action):
        """Create a button for the action and add it to the layout
        at index.

        """
        self.__shiftGrid(index, 1)
        button = self.createButtonForAction(action)

        row = index / self.__columns
        column = index % self.__columns

        self.layout().addWidget(button, row, column,
                                Qt.AlignLeft | Qt.AlignTop)

        self.__gridSlots.insert(index,
                                _ToolGridSlot(button, action, row, column))

        self.__mapper.setMapping(button, action)
        button.clicked.connect(self.__mapper.map)
        button.installEventFilter(self.__buttonListener)
        button.installEventFilter(self)

    def __removeActionButton(self, action):
        """Remove the button for the action from the layout and delete it.
        """
        actions = [slot.action for slot in self.__gridSlots]
        index = actions.index(action)
        slot = self.__gridSlots.pop(index)

        slot.button.removeEventFilter(self.__buttonListener)
        slot.button.removeEventFilter(self)
        self.__mapper.removeMappings(slot.button)

        self.layout().removeWidget(slot.button)
        self.__shiftGrid(index + 1, -1)

        slot.button.deleteLater()

    def __shiftGrid(self, start, count=1):
        """Shift all buttons starting at index `start` by `count` cells.
        """
        button_count = self.layout().count()
        direction = 1 if count >= 0 else -1
        if direction == 1:
            start, end = button_count - 1, start - 1
        else:
            start, end = start, button_count

        for index in range(start, end, -direction):
            item = self.layout().itemAtPosition(index / self.__columns,
                                                index % self.__columns)
            if item:
                button = item.widget()
                new_index = index + count
                self.layout().addWidget(button, new_index / self.__columns,
                                        new_index % self.__columns,
                                        Qt.AlignLeft | Qt.AlignTop)

    def __relayout(self):
        """Relayout the buttons.
        """
        for i in reversed(range(self.layout().count())):
            self.layout().takeAt(i)

        self.__gridSlots = [
            _ToolGridSlot(slot.button, slot.action, i / self.__columns,
                          i % self.__columns)
            for i, slot in enumerate(self.__gridSlots)
        ]

        for slot in self.__gridSlots:
            self.layout().addWidget(slot.button, slot.row, slot.column,
                                    Qt.AlignLeft | Qt.AlignTop)

    def __indexOf(self, button):
        """Return the index of button widget.
        """
        buttons = [slot.button for slot in self.__gridSlots]
        return buttons.index(button)

    def __onButtonRightClick(self, button):
        pass

    def __onButtonEnter(self, button):
        action = button.defaultAction()
        self.actionHovered.emit(action)

    def __onClicked(self, action):
        self.actionTriggered.emit(action)

    def paintEvent(self, event):
        return utils.StyledWidget_paintEvent(self, event)

    def eventFilter(self, obj, event):
        etype = event.type()
        if etype == QEvent.KeyPress and obj.hasFocus():
            key = event.key()
            if key in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]:
                if self.__focusMove(obj, key):
                    event.accept()
                    return True

        return QFrame.eventFilter(self, obj, event)

    def __focusMove(self, focus, key):
        assert (focus is self.focusWidget())
        try:
            index = self.__indexOf(focus)
        except IndexError:
            return False

        if key == Qt.Key_Down:
            index += self.__columns
        elif key == Qt.Key_Up:
            index -= self.__columns
        elif key == Qt.Key_Left:
            index -= 1
        elif key == Qt.Key_Right:
            index += 1

        if index >= 0 and index < self.count():
            button = self.__gridSlots[index].button
            button.setFocus(Qt.TabFocusReason)
            return True
        else:
            return False
    def __init__(self, parent=None):
        super(MainWindowStart, self).__init__(parent)
        # Mappers for connecting buttons and labels
        self.myMapper = QSignalMapper(self)
        self.myMapper_StyleSheet = QSignalMapper(self)
        # Load UI
        self.setupUi(self)

        self.regex_edits = QRegExp(r"(^[0]+$|^$)")
        self._filter = Filter()
        self.filename = QString()
        self.edit1_delayh.installEventFilter(self._filter)
        self.sizeLabel = QLabel()
        self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.statusBar1.addPermanentWidget(self.sizeLabel)
        self.statusBar1.setSizeGripEnabled(False)

        self.create_connections()
        self.assign_shortcuts()

        self.create_tool_bar()
        self.update_devices_list()
        # self.button_stop.clicked.connect(self.stop_all)
        # List of valve pushbuttons
        self.valve_list = [
            self.valve1, self.valve2, self.valve3, self.valve4, self.valve5,
            self.valve6, self.valve7, self.valve8
        ]

        # GroupBoxes for grouping labels and buttons on each row, used for applying StyleSheets
        self.group_boxes = [
            self.groupbox1, self.groupbox2, self.groupbox3, self.groupbox4,
            self.groupbox5, self.groupbox6, self.groupbox7, self.groupbox8
        ]
        # List of lineEdits
        self.lineEdits_list = [
            (self.edit1_delayh, self.edit1_delaym, self.edit1_delays,
             self.edit1_onh, self.edit1_onm, self.edit1_ons, self.edit1_offh,
             self.edit1_offm, self.edit1_offs, self.edit1_totalh,
             self.edit1_totalm, self.edit1_totals),
            (self.edit2_delayh, self.edit2_delaym, self.edit2_delays,
             self.edit2_onh, self.edit2_onm, self.edit2_ons, self.edit2_offh,
             self.edit2_offm, self.edit2_offs, self.edit2_totalh,
             self.edit2_totalm, self.edit2_totals),
            (self.edit3_delayh, self.edit3_delaym, self.edit3_delays,
             self.edit3_onh, self.edit3_onm, self.edit3_ons, self.edit3_offh,
             self.edit3_offm, self.edit3_offs, self.edit3_totalh,
             self.edit3_totalm, self.edit3_totals),
            (self.edit4_delayh, self.edit4_delaym, self.edit4_delays,
             self.edit4_onh, self.edit4_onm, self.edit4_ons, self.edit4_offh,
             self.edit4_offm, self.edit4_offs, self.edit4_totalh,
             self.edit4_totalm, self.edit4_totals),
            (self.edit5_delayh, self.edit5_delaym, self.edit5_delays,
             self.edit5_onh, self.edit5_onm, self.edit5_ons, self.edit5_offh,
             self.edit5_offm, self.edit5_offs, self.edit5_totalh,
             self.edit5_totalm, self.edit5_totals),
            (self.edit6_delayh, self.edit6_delaym, self.edit6_delays,
             self.edit6_onh, self.edit6_onm, self.edit6_ons, self.edit6_offh,
             self.edit6_offm, self.edit6_offs, self.edit6_totalh,
             self.edit6_totalm, self.edit6_totals),
            (self.edit7_delayh, self.edit7_delaym, self.edit7_delays,
             self.edit7_onh, self.edit7_onm, self.edit7_ons, self.edit7_offh,
             self.edit7_offm, self.edit7_offs, self.edit7_totalh,
             self.edit7_totalm, self.edit7_totals),
            (self.edit8_delayh, self.edit8_delaym, self.edit8_delays,
             self.edit8_onh, self.edit8_onm, self.edit8_ons, self.edit8_offh,
             self.edit8_offm, self.edit8_offs, self.edit8_totalh,
             self.edit8_totalm, self.edit8_totals)
        ]

        for index, editLabels in enumerate(self.lineEdits_list, 1):

            for index2, lineedits in enumerate(editLabels, 0):
                # Apply mapper (GUIObject, objectIndex)
                self.myMapper_StyleSheet.setMapping(
                    self.lineEdits_list[index - 1][index2], index - 1)
                # Connect mapper to signal
                (self.lineEdits_list[index - 1][index2]).textChanged.connect(
                    self.myMapper_StyleSheet.map)
                # Set event Filter, for detecting when Focus changes
                self.lineEdits_list[index - 1][index2].installEventFilter(
                    self._filter)
            # Set Mappers for buttons (1..8)
            self.myMapper.setMapping(self.valve_list[index - 1], index)
            # Connect mapper to signal for detecting clicks on buttons
            (self.valve_list[index - 1]).clicked.connect(self.myMapper.map)
        # Connect to signal for enabling labelEdits
        self.myMapper.mapped['int'].connect(self.enable_fields)
        # Connect to signal for changing color of groupbox used for visual indication
        self.myMapper_StyleSheet.mapped['int'].connect(self.valve_color_status)
    def contextMenuEvent(self, event):
        menu = QtGui.QMenu()
        last_pos = event.pos()
        cursor = self.cursorForPosition(last_pos)
        pos = cursor.positionInBlock()
        line = cursor.blockNumber()

        word = self.error_at_pos(line, pos)

        if not word == None:
            suggestions = self.highlighter.checker.suggest(word[0])

            if len(suggestions) > 0:
                suggestion_mapper = QSignalMapper(self)

                actions = []

                # Generate our suggestions, packing all the data we need to make the replacement.
                for i, suggestion in enumerate(suggestions):
                    if i == MAX_SUGGESTIONS:
                        break

                    actions.append(QtGui.QAction(suggestion, None))

                    # We can only send strings with the signal mapper, so pickle our data.
                    data = pickle.dumps((word[0], line, word[1], suggestion))
                    data = QtCore.QString.fromAscii(data)

                    self.connect(actions[-1], QtCore.SIGNAL("triggered()"),
                                 suggestion_mapper, QtCore.SLOT("map()"))
                    suggestion_mapper.setMapping(actions[-1], data)

                self.connect(suggestion_mapper,
                             QtCore.SIGNAL("mapped(QString)"), self.__replace)
                menu.addActions(actions)
            else:
                action = QtGui.QAction("(No spelling suggestions)", None)
                action.setDisabled(True)
                menu.addAction(action)

            menu.addSeparator()

            add_mapper = QSignalMapper(self)
            ignore_mapper = QSignalMapper(self)
            add_action = QtGui.QAction("Add to Dictionary", None)
            ignore_action = QtGui.QAction("Ignore All", None)

            self.connect(add_action, QtCore.SIGNAL("triggered()"), add_mapper,
                         QtCore.SLOT("map()"))
            add_mapper.setMapping(add_action, word[0])
            self.connect(add_mapper, QtCore.SIGNAL("mapped(QString)"),
                         self.__add)

            self.connect(ignore_action, QtCore.SIGNAL("triggered()"),
                         ignore_mapper, QtCore.SLOT("map()"))
            ignore_mapper.setMapping(ignore_action, word[0])
            self.connect(ignore_mapper, QtCore.SIGNAL("mapped(QString)"),
                         self.__ignore)

            menu.addAction(add_action)
            menu.addAction(ignore_action)
            menu.addSeparator()

        default_menu = self.createStandardContextMenu()
        menu.addActions(default_menu.actions())

        menu.exec_(event.globalPos())
Beispiel #56
0
class K800IRec(QWidget, mfso):
    def __init__(self):
       mfso.__init__(self, "K800i-Recover")
       self.name = "K800i-Recover"
       self.icon = None
       self.__disown__()

    def start(self, args):
        self.vfs = vfs.vfs()
        self.dumpnumber = 1
        try :
          self.nor = args['nor'].value()
          self.nand = args['nand'].value()
        except IndexError:
	  return
        try:
          self.spareSize = args["spare-size"].value()
        except IndexError:
          self.spareSize = 16
        try:
          self.pageSize = args["page-size"].value()
        except IndexError:
	  self.pageSize = 512
        self.k800n = Node("k800-base")
        self.k800n.__disown__()
        self.boot = SEBootBlock(self.nor, self.pageSize) 
        self.blockSize = self.boot.blockSize
        self.nandClean = SpareNode(self,  self.nand, "nandfs", self.pageSize, self.spareSize, self.k800n)
        self.norFs = NorFs(self, self.k800n,  self.nor, "norfs", self.boot)
        self.fullFs = FullFs(self, self.k800n, self.norFs, self.nandClean, "fullfs", self.boot)
        self.gdfs = GDFS(self, self.k800n, self.nor, "gdfs", self.boot)
        self.firmware = Firmware(self, self.k800n,  self.nor, "firmware", self.boot.norfsoffset)

        self.tables = Tables(self.fullFs, self.blockSize)
        self.registerTree(self.nand, self.k800n)
 
    def createDump(self):
       text, ok = QInputDialog.getText(self, "Create dump", "dump name:", QLineEdit.Normal, "k800-restore-" + str(self.dumpnumber)) 
       if ok and text != "":
         if  (self.vfs.getnode(self.nand.absolute() + "/" + str(text)) == None):  
           self.dumpnumber += 1
           newroot = Node(str(text))
	   newroot.__disown__()
	   for id in range(0, len(self.tables.tablesIdWriteMap) - 1):
             write = int(str(self.gtable.cellWidget(id, 0).currentText()), 16)
             self.tables.map[id] = self.tables.tablesIdWriteMap[id][write]
           virtual = VirtualMap(self, newroot, self.fullFs, self.tables, "virtual", self.blockSize)
           separt = SEPartitionBlock(virtual, self.boot.partitionblock, self.blockSize)
           self.createPart(separt, newroot, virtual)
           self.registerTree(self.nand, newroot) 
         else :
          box = QMessageBox(QMessageBox.Warning, "Error", "Error node already exists", QMessageBox.NoButton, self)
          box.exec_()
          self.createDump()

    def createPart(self, separt, newroot, virtual):
      for part in separt.partTable:
       if part.start > 0:
         p = Partition(self, newroot, virtual, part, self.blockSize)

    def g_display(self):
      QWidget.__init__(self, None)
      self.layout = QVBoxLayout(self)
      self.hlayout = QSplitter(self)
      self.layout.insertWidget(0, self.hlayout)
      self.layout.setStretchFactor(self.hlayout, 1)
      self.gTable()
      self.viewTable()

      self.button = QPushButton("&Create dump")
      self.connect(self.button, SIGNAL("clicked()"), self.createDump)
      self.layout.addWidget(self.button)
     	

    def viewTable(self):
      self.vtable = QTableWidget() 
      self.vtable.setColumnCount(20)	
      self.vtable.setRowCount(48)
      self.hlayout.addWidget(self.vtable)
 
    def viewTableUpdate(self, id):
      write = int(str(self.gtable.cellWidget(id, 0).currentText()), 16) 
      t = self.tables.tablesIdWriteMap[id][write]
      l = t.blockList
      for x in xrange(0, len(t.blockList[0])):
        block = t.blockList[0][x]
        c = ((x) % 20) 
        r = ((x) / 20) 
        item = QTableWidgetItem(QString(hex(block))) 
        tipBlock = (id * 960) + x
        item.setToolTip(QString(hex(tipBlock)))
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.vtable.setItem(r ,c,  item)
     

    def gTable(self):
      self.gtable = QTableWidget()
      self.gtable.setColumnCount(1)	
      self.gtable.setRowCount(len(self.tables.tablesIdWriteMap))
      self.gtable.setHorizontalHeaderItem(0, QTableWidgetItem(QString("version")))
      self.hlayout.addWidget(self.gtable)
      self.sigMapper = QSignalMapper(self)
      for id in self.tables.tablesIdWriteMap:
         wlist = self.tables.tablesIdWriteMap[id]
         cbox = QComboBox(self.gtable)
         self.connect(cbox, SIGNAL("activated(QString)"), self.sigMapper, SLOT("map()"))
         self.sigMapper.setMapping(cbox, id)
         l = [] 
         for write in wlist:
           l.append(write)
         l.sort()
         l.reverse()
         for write in l:
	   cbox.addItem(QString(hex(write))) 
	 self.gtable.setCellWidget(id, 0, cbox)
	 self.gtable.setVerticalHeaderItem(id, QTableWidgetItem(QString(hex(id))))
      self.connect(self.sigMapper, SIGNAL("mapped(int)"),  self.viewTableUpdate) 
      self.gtable.setMaximumWidth(self.gtable.columnWidth(0) + self.gtable.verticalHeader().sectionSize(0) + 30)  
 
    def updateWidget(self):
       pass 
class CaseSelectionWidget(QWidget):

    caseSelectionChanged = pyqtSignal()

    def __init__(self, current_case):
        QWidget.__init__(self)

        self.__model = PlotCaseModel()

        self.__signal_mapper = QSignalMapper(self)
        self.__case_selectors = {}
        self.__case_selectors_order = []

        layout = QVBoxLayout()

        add_button_layout = QHBoxLayout()
        self.__add_case_button = QToolButton()
        self.__add_case_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.__add_case_button.setText("Add case to plot")
        self.__add_case_button.setIcon(resourceIcon("ide/small/add"))
        self.__add_case_button.clicked.connect(self.addCaseSelector)

        add_button_layout.addStretch()
        add_button_layout.addWidget(self.__add_case_button)
        add_button_layout.addStretch()

        layout.addLayout(add_button_layout)

        self.__case_layout = QVBoxLayout()
        self.__case_layout.setMargin(0)
        layout.addLayout(self.__case_layout)

        self.addCaseSelector(disabled=True, current_case=current_case)
        layout.addStretch()

        self.setLayout(layout)

        self.__signal_mapper.mapped[QWidget].connect(self.removeWidget)

    def __caseName(self, widget):
        """ @rtype: str """
        return str(self.__case_selectors[widget].currentText())

    def getPlotCaseNames(self):
        if self.__model.rowCount() == 0:
            return []

        return [
            self.__caseName(widget) for widget in self.__case_selectors_order
        ]

    def checkCaseCount(self):
        state = True
        if len(self.__case_selectors_order) == 5:
            state = False

        self.__add_case_button.setEnabled(state)

    def addCaseSelector(self, disabled=False, current_case=None):
        widget = QWidget()

        layout = QHBoxLayout()
        layout.setMargin(0)
        widget.setLayout(layout)

        combo = QComboBox()
        combo.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLengthWithIcon)
        combo.setMinimumContentsLength(20)
        combo.setModel(self.__model)

        if current_case is not None:
            index = 0
            for item in self.__model:
                if item == current_case:
                    combo.setCurrentIndex(index)
                    break
                index += 1

        combo.currentIndexChanged.connect(self.caseSelectionChanged.emit)

        layout.addWidget(combo, 1)

        button = QToolButton()
        button.setAutoRaise(True)
        button.setDisabled(disabled)
        button.setIcon(resourceIcon("ide/small/delete"))
        button.clicked.connect(self.__signal_mapper.map)

        layout.addWidget(button)

        self.__case_selectors[widget] = combo
        self.__case_selectors_order.append(widget)
        self.__signal_mapper.setMapping(button, widget)

        self.__case_layout.addWidget(widget)

        self.checkCaseCount()
        self.caseSelectionChanged.emit()

    def removeWidget(self, widget):
        self.__case_layout.removeWidget(widget)
        del self.__case_selectors[widget]
        self.__case_selectors_order.remove(widget)
        widget.setParent(None)
        self.caseSelectionChanged.emit()

        self.checkCaseCount()