예제 #1
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()
예제 #2
0
    def __init__(self):
        super(MainWindow, self).__init__()

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)
        self.mdiArea.setDocumentMode(True)
        self.mdiArea.setTabsClosable(True)
        self.mdiArea.setTabsMovable(True)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("MDI")
예제 #3
0
    def __init__(self, currentApp):
        '''
        Constructor
        '''
        self.app = currentApp
        QtWidgets.QMainWindow.__init__(self)
        self.setupUi(self)
        central.CoreCentral.__init__(self)
        atexit.register(self.sessionClosed)

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

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.setWindowTitle("PyOne")

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()
        self.startupActivity()
        self.reloadedModules = []
예제 #4
0
    def __init__(self):
        super(RDFNavigator, self).__init__()

        self.lastDir = '.'

        self.settingsManager = RDFNavigatorSettignsManager()
        self.resourceRefManager = RDFNavigatorResourceReferenceManager()
        self.childrenFactory = RDFNavigatorChildrenFactory(self)

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()
        self.createDockWidgets()
        self.readSettings()

        self.setWindowTitle("RDF Navigator")
        self.global_data = {}

        self.analyzeSystemData()
예제 #5
0
    def updatePlotPersoButton(self):
        menu = QMenu(self.mw)

        menus = []
        for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
            m = QMenu(i, menu)
            menus.append(m)
            menu.addMenu(m)

        mpr = QSignalMapper(menu)
        for i in range(self.mw.mdlCharacter.rowCount()):
            a = QAction(self.mw.mdlCharacter.name(i), menu)
            a.setIcon(self.mw.mdlCharacter.icon(i))
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(self.mw.mdlCharacter.ID(i)))

            imp = toInt(self.mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        # Disabling empty menus
        for m in menus:
            if not m.actions():
                m.setEnabled(False)

        mpr.mapped.connect(self.addPlotPerso)
        self.mw.btnAddPlotPerso.setMenu(menu)
예제 #6
0
    def on_view_horizontalHeader_sectionClicked(self, logicalIndex):
        self.logicalIndex   = logicalIndex
        self.menuValues     = QMenu(self)
        self.signalMapper   = QSignalMapper(self)

        self.columnComboBox.blockSignals(True)
        self.columnComboBox.setCurrentIndex(self.logicalIndex)
        self.columnComboBox.blockSignals(True)

        valuesUnique = [    self.model.item(row, self.logicalIndex).text()
                            for row in range(self.model.rowCount())
                            ]

        actionAll = QAction("All", self)
        actionAll.triggered.connect(self.on_actionAll_triggered)
        self.menuValues.addAction(actionAll)
        self.menuValues.addSeparator()

        for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))):
            action = QAction(actionName, self)
            self.signalMapper.setMapping(action, actionNumber)
            action.triggered.connect(self.signalMapper.map)
            self.menuValues.addAction(action)

        self.signalMapper.mapped.connect(self.on_signalMapper_mapped)

        headerPos = self.tableView.mapToGlobal(self.horizontalHeader.pos())

        posY = headerPos.y() + self.horizontalHeader.height()
        posX = headerPos.x() + self.horizontalHeader.sectionPosition(self.logicalIndex)

        self.menuValues.exec_(QPoint(posX, posY))
예제 #7
0
 def initDialog(self):
     """Creates buttons for each sequence option and add them to the dialog.
     Maps the clicked signal of those buttons to keep track of what sequence
     gets selected.
     """
     ui_dlg = Ui_AddSeqDialog()
     ui_dlg.setupUi(self.dialog)
     self.signal_mapper = QSignalMapper(self)
     # set up the radio buttons
     for i, name in enumerate(['Abstract', 'Custom'] +
                              sorted(sequences.keys())):
         radio_button = QRadioButton(ui_dlg.group_box)
         radio_button.setObjectName(name + "Button")
         radio_button.setText(name)
         self.buttons.append(radio_button)
         ui_dlg.horizontalLayout.addWidget(radio_button)
         self.signal_mapper.setMapping(radio_button, i)
         radio_button.clicked.connect(self.signal_mapper.map)
         if name in sequences:
             self.sequence_radio_button_id[sequences[name]] = i
     self.signal_mapper.mapped.connect(self.sequenceOptionChangedSlot)
     # disable apply until valid option or custom sequence is chosen
     self.apply_button = ui_dlg.custom_button_box.button(
         QDialogButtonBox.Apply)
     self.apply_button.setEnabled(False)
     # watch sequence textedit box to validate custom sequences
     self.seq_box = ui_dlg.seq_text_edit
     self.seq_box.textChanged.connect(self.validateCustomSequence)
     self.highlighter = DNAHighlighter(self.seq_box)
     # finally, pre-click the first radio button
     self.buttons[0].click()
예제 #8
0
    def updatePlotPersoButton(self):
        menu = QMenu(self.mw)

        menus = []
        for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
            m = QMenu(i, menu)
            menus.append(m)
            menu.addMenu(m)

        mpr = QSignalMapper(menu)
        for i in range(self.mw.mdlCharacter.rowCount()):
            a = QAction(self.mw.mdlCharacter.name(i), menu)
            a.setIcon(self.mw.mdlCharacter.icon(i))
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(self.mw.mdlCharacter.ID(i)))

            imp = toInt(self.mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        # Disabling empty menus
        for m in menus:
            if not m.actions():
                m.setEnabled(False)

        mpr.mapped.connect(self.addPlotPerso)
        self.mw.btnAddPlotPerso.setMenu(menu)
예제 #9
0
    def __init__(self):
        """

        Initializes the main game's window and sets its attributes to their
        default values.

        """
        super(RagingSeasWindow, self).__init__()
        self.ui = Ui_RagingSeasWindow()
        self.ui.setupUi(self)
        self.ui.menuFile.menuAction().setStatusTip(self.tr("File"))
        self.ui.menuHelp.menuAction().setStatusTip(self.tr("Help"))
        self.ui.playerOneLabel.hide()
        self.ui.playerTwoLabel.hide()
        self.leftGridMapper = QSignalMapper(self)
        self.rightGridMapper = QSignalMapper(self)
        self.statusLabel = QLabel(self)
        self.statusLabel.setObjectName("StatusLabel")
        self.ui.statusBar.setSizeGripEnabled(False)
        self.ui.statusBar.addPermanentWidget(self.statusLabel)
        self.setStyleSheet(style.INITIAL_MAIN_WINDOW_STYLE)
        self.setFixedSize(self.size())
        self.setWindowFlags(
            self.windowFlags() ^
            (QtCore.Qt.WindowMinimizeButtonHint |
             QtCore.Qt.WindowMaximizeButtonHint)
        )

        self._session = None
        self._grid_size = None
        self._previous_grid_size = None
        self._is_new_game = False
        self._has_game_been_started = False
        self._current_ship_index = 0
        self._current_orientation = ShipOrientation.horizontal
예제 #10
0
 def __init__(self, dataTab=None, parent=None):
     super(processManagerDialog, self).__init__(parent=parent)
     self.installDir = GENERAL.get_value('INSTALL_DIR')
     self.mainLayout = QVBoxLayout(self)
     self.upperLayout = QVBoxLayout(self)
     self.lowerLayout = QVBoxLayout(self)
     self.menuBar = QMenuBar(self)
     self.toolBar = QToolBar(self)
     self.processTable = QTableView(self)
     self.tableModel = functionModel(self)
     self.processTablePopMenu = QMenu(self)
     self.importMenu = QMenu(self)
     self.signalMapper = QSignalMapper(self)
     # self.MLProject = MLProject
     self.openedData = GENERAL.get_value('OPENED_DATA')
     self.MainTabWindow = GENERAL.get_value('TABWINDOW')
     # tool bar
     self.addProcessAction = None
     self.importProcessAction = None
     # data
     self.processList = []
     self.processDict = set()
     self.dataTab = dataTab
     self.targetDataset = dataTab.filename if dataTab else None
     # self.curDir = GENERAL.get_value('INSTALL_DIR')
     self.initUI()
     self.initRightClickMenu()
예제 #11
0
 def createUI(self):
     self.vblayout = QVBoxLayout(self)
     self.layoutWidget = pg.LayoutWidget()
     self.vblayout.addWidget(self.layoutWidget)
     self.labels = {}
     self.inputFields = {}
     for key, value in self.inputs.items():
         self.labels[key] = QLabel(key)
         self.layoutWidget.addWidget(self.labels[key])
         if type(value) == int:
             self.signalMapper1 = QSignalMapper(self)
             self.inputFields[key] = QLineEdit(str(value))
             self.inputFields[key].setValidator(self.intValidator)
             self.inputFields[key].textChanged.connect(
                 self.signalMapper1.map)
             self.signalMapper1.setMapping(self.inputFields[key], key)
             self.signalMapper1.mapped[str].connect(self.inputChanged)
         elif type(value) == float:
             self.signalMapper2 = QSignalMapper(self)
             self.inputFields[key] = QLineEdit(str(value))
             self.inputFields[key].setValidator(self.floatValidator)
             self.inputFields[key].textChanged.connect(
                 self.signalMapper2.map)
             self.signalMapper2.setMapping(self.inputFields[key], key)
             self.signalMapper2.mapped[str].connect(self.inputChanged)
         elif type(value) == bool:
             self.signalMapper3 = QSignalMapper(self)
             self.inputFields[key] = QCheckBox()
             self.inputFields[key].setTristate(False)
             self.inputFields[key].stateChanged.connect(
                 self.signalMapper3.map)
             self.signalMapper3.setMapping(self.inputFields[key], key)
             self.signalMapper3.mapped[str].connect(self.inputStateChanged)
         elif type(value) == str:
             self.signalMapper4 = QSignalMapper(self)
             self.inputFields[key] = QLineEdit(value)
             self.inputFields[key].textChanged.connect(
                 self.signalMapper4.map)
             self.signalMapper4.setMapping(self.inputFields[key], key)
             self.signalMapper4.mapped[str].connect(self.inputChanged)
         elif type(value) == list:
             self.signalMapper5 = QSignalMapper(self)
             self.inputFields[key] = QComboBox()
             self.inputFields[key].addItems(value)
             self.inputFields[key].currentTextChanged.connect(
                 self.signalMapper5.map)
             self.signalMapper5.setMapping(self.inputFields[key], key)
             self.signalMapper5.mapped[str].connect(self.inputTextChanged)
         self.layoutWidget.addWidget(self.inputFields[key])
         self.layoutWidget.nextRow()
     self.layoutWidget.nextRow()
     self.cancelButton = QPushButton('Cancel')
     self.cancelButton.clicked.connect(self.cancelandClose)
     self.layoutWidget.addWidget(self.cancelButton, col=0)
     self.okButton = QPushButton('OK')
     self.okButton.clicked.connect(self.okandClose)
     self.layoutWidget.addWidget(self.okButton, col=1)
     self.okButton.setDefault(True)
예제 #12
0
    def __init__(self, **kwargs):
        super(Monitor, self).__init__(**kwargs)

        self.watched = WeakValueDictionary()
        self.delMapper = QSignalMapper(self)
        self.delMapper.mapped[str].connect(self.unmonitorFile)

        self.watcher = MonitorWithRename(parent=self)
        self.watcher.fileChanged.connect(self._onFileChanged)
예제 #13
0
class Monitor(QObject):
	"""File monitor

	This monitor can be used to track single files
	"""

	def __init__(self, **kwargs):
		super(Monitor, self).__init__(**kwargs)

		self.watched = WeakValueDictionary()
		self.delMapper = QSignalMapper(self)
		self.delMapper.mapped[str].connect(self.unmonitorFile)

		self.watcher = MonitorWithRename(parent=self)
		self.watcher.fileChanged.connect(self._onFileChanged)

	def monitorFile(self, path):
		"""Monitor a file and return an object that tracks only `path`

		:rtype: SingleFileWatcher
		:return: an object tracking `path`, the same object is returned if the method is called
		         with the same path.
		"""
		path = os.path.abspath(path)

		self.watcher.addPath(path)

		proxy = self.watched.get(path)
		if not proxy:
			proxy = SingleFileWatcher(path)
			proxy.destroyed.connect(self.delMapper.map)
			self.delMapper.setMapping(proxy, path)
			self.watched[path] = proxy

		return proxy

	@Slot(str)
	def unmonitorFile(self, path):
		"""Stop monitoring a file

		Since there is only one :any:`SingleFileWatcher` object per path, all objects monitoring
		`path` will not receive notifications anymore.
		To let only one object stop monitoring the file, simply disconnect its `modified` signal.
		When the :any:`SingleFileWatcher` object returned by method :any:`monitorFile` is
		destroyed, the file is automatically un-monitored.
		"""
		path = os.path.abspath(path)

		self.watcher.removePath(path)
		self.watched.pop(path, None)

	@Slot(str)
	def _onFileChanged(self, path):
		proxy = self.watched.get(path)
		if proxy:
			proxy.modified.emit()
예제 #14
0
    def refresh_accounts(self):
        self.menu_change_account.clear()
        signal_mapper = QSignalMapper(self)

        for account_name in sorted(self.app.accounts.keys()):
            action = QAction(account_name, self)
            self.menu_change_account.addAction(action)
            signal_mapper.setMapping(action, account_name)
            action.triggered.connect(signal_mapper.map)
            signal_mapper.mapped[str].connect(self.action_change_account)
    def __init__(self, columns: int = 9, rows: int = 9, mines: int = 10):
        """Initialize a game of Minesweeper

        This will create the game board and hide the specified number of mines on the board.

        :param columns: The number of columns on the game board (the width). Default is 9.
        :param rows: The number of rows on the game board (the height). Default is 9.
        :param mines: The number of mines to hide on the game board. There cannot be more mines on the game board than
            there are fields. Default is 10.
        """
        super().__init__(parent=None)

        # These attributes will be initialized in __new_game()
        self.columns = 0
        self.rows = 0
        self.mines = 0
        self.game_running = False

        # Initialize the GUI
        self.view = Ui_MainWindow()
        self.view.setupUi(self)

        # Connect the signals of the "New game" buttons
        self.view.new_game_easy.triggered.connect(self.easy_game)
        self.view.new_game_medium.triggered.connect(self.medium_game)
        self.view.new_game_difficult.triggered.connect(self.difficult_game)
        self.view.new_game_custom.triggered.connect(self.custom_game_dialog)

        # The model will be initialized in __new_game()
        self.model = None

        # A dialog window for starting a custom game
        self.dialog = CustomGameDialog()
        self.dialog.accepted.connect(self.__custom_game)

        # Initialize a QSignalMapper to enable mapping all button clicks to a single method
        self.mapper = QSignalMapper(self.view.centralwidget)
        self.mapper.mapped.connect(self.button_clicked)

        # Initialize another QSignalMapper to enable mapping of right-clicks
        self.rc_mapper = QSignalMapper(self.view.centralwidget)
        self.rc_mapper.mapped.connect(self.button_right_clicked)

        # Create a QGridLayout for the buttons
        self.grid = QGridLayout()
        self.view.main_layout.addLayout(self.grid)
        self.grid.setSpacing(5)

        # This is the only efficient way to keep a reference to all buttons on the board, since buttons are
        # "re-parented" to the main window after being added to a layout
        self.buttons = []

        self.grid.setSizeConstraint(QGridLayout.SetFixedSize)

        self.__new_game(columns=columns, rows=rows, mines=mines)
예제 #16
0
class Monitor(QObject):
    """File monitor

	This monitor can be used to track single files
	"""
    def __init__(self, **kwargs):
        super(Monitor, self).__init__(**kwargs)

        self.watched = WeakValueDictionary()
        self.delMapper = QSignalMapper(self)
        self.delMapper.mapped[str].connect(self.unmonitorFile)

        self.watcher = MonitorWithRename(parent=self)
        self.watcher.fileChanged.connect(self._onFileChanged)

    def monitorFile(self, path):
        """Monitor a file and return an object that tracks only `path`

		:rtype: SingleFileWatcher
		:return: an object tracking `path`, the same object is returned if the method is called
		         with the same path.
		"""
        path = os.path.abspath(path)

        self.watcher.addPath(path)

        proxy = self.watched.get(path)
        if not proxy:
            proxy = SingleFileWatcher(path)
            proxy.destroyed.connect(self.delMapper.map)
            self.delMapper.setMapping(proxy, path)
            self.watched[path] = proxy

        return proxy

    @Slot(str)
    def unmonitorFile(self, path):
        """Stop monitoring a file

		Since there is only one :any:`SingleFileWatcher` object per path, all objects monitoring
		`path` will not receive notifications anymore.
		To let only one object stop monitoring the file, simply disconnect its `modified` signal.
		When the :any:`SingleFileWatcher` object returned by method :any:`monitorFile` is
		destroyed, the file is automatically un-monitored.
		"""
        path = os.path.abspath(path)

        self.watcher.removePath(path)
        self.watched.pop(path, None)

    @Slot(str)
    def _onFileChanged(self, path):
        proxy = self.watched.get(path)
        if proxy:
            proxy.modified.emit()
예제 #17
0
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.mgr = WordMgr(auto_shuffle=False)
        self.setupUi(self)

        self.signal_map_list_checkbox = QSignalMapper()
        self.signal_map_list_checkbox.mapped[int].connect(
            self.onListCheckboxChanged)
        self.map_li_checkbox = {}

        self.initUI()
예제 #18
0
파일: main_window.py 프로젝트: PrVrSs/tng
 def setup_ui(self, main_window):
     self.main_window = main_window
     main_window.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
     red, green, blue = 11, 7, 11
     main_window.setPalette(QPalette(QColor(red, green, blue)))
     self.mdiArea = QMdiArea()
     self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
     self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
     self.create_menu(main_window)
     self.create_tool_bars(main_window)
     main_window.setCentralWidget(self.mdiArea)
     self.windowMapper = QSignalMapper(main_window)
예제 #19
0
    def init_menu(self):
        # menu_bar
        _menu_bar = self.menuBar()
        self.init_file_menu(_menu_bar)
        self.init_edditing_menu(_menu_bar)
        self.init_view_menu(_menu_bar)
        self.init_last_toolbar()
        self.init_file_toolbar()
        self.init_adding_toolbar()
        self.init_formattin_toolbar()

        # mapper for recent files
        self.mapper = QSignalMapper(self)
예제 #20
0
    def initUI(self):
        """UI is composed with """

        # variable for QSettings
        self.name_company = 'Copey'
        self.name_product = 'DataViz NodeEditor'
        self.setWindowIcon(QIcon('icons/main-icon.png'))

        # Load filesheets
        # TODO Review style
        # self.stylesheet_filenames = (os.path.join(os.path.dirname(__file__), 'qss/nodeeditor.qss'),
        #                              os.path.join(os.path.dirname(__file__), 'qss/nodeeditor-dark.qss'))
        self.stylesheet_filenames = (os.path.join(os.path.dirname(__file__), 'icons/nodeeditor.qss'))
        print(self.stylesheet_filenames)
        loadStylessheets(*self.stylesheet_filenames)
        #
        self.empty_icon = QIcon(".")

        if DEBUG:
            print('Registered Node')
            pp(NodeFactory.get_nodes())

        # Instantiate the MultiDocument Area
        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)
        self.mdiArea.setTabsClosable(True)
        self.setCentralWidget(self.mdiArea)

        # Connect subWindowActivate to updateMenu
        # Activate the items on the file_menu and the edit_menu
        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        # from mdi example...
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        # instantiate various elements
        self.createNodesDock()
        self.createPropertiesDock()
        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("DataViz NodeEditor")
예제 #21
0
	def _add_widgets(self,vbox,apps):
		row=int(len(self.appsWidgets)/self.maxCol)
		col=(self.maxCol*(row+1))-len(self.appsWidgets)
		sigmap_run=QSignalMapper(self)
		sigmap_run.mapped[QString].connect(self._launch)
		for appName,data in apps.items():
			appIcon=data['Icon']
			appDesc=data['Name']
			if QtGui.QIcon.hasThemeIcon(appIcon):
				icnApp=QtGui.QIcon.fromTheme(appIcon)
			elif os.path.isfile(appIcon):
					iconPixmap=QtGui.QPixmap(appIcon)
					scaledIcon=iconPixmap.scaled(QSize(BTN_SIZE*1.2,BTN_SIZE*1.2))
					icnApp=QtGui.QIcon(scaledIcon)
			elif appIcon.startswith("http"):
				if not os.path.isdir("%s/icons"%self.cache):
					os.makedirs("%s/icons"%self.cache)
				tmpfile=os.path.join("%s/icons"%self.cache,appIcon.split("/")[2].split(".")[0])
				if not os.path.isfile(tmpfile):
					try:
						urlretrieve(appIcon,tmpfile)
					except:
						tmpfile=QtGui.QIcon.fromTheme("shell")
				iconPixmap=QtGui.QPixmap(tmpfile)
				scaledIcon=iconPixmap.scaled(QSize(BTN_SIZE*1.2,BTN_SIZE*1.2))
				icnApp=QtGui.QIcon(scaledIcon)
				appIcon=tmpfile
			else:
				continue
			if not appName:
				continue
			self.app_icons[appName]=appIcon
			self._debug("Adding %s"%appName)
			btnApp=navButton(self)
			btnApp.setIcon(icnApp)
			btnApp.setIconSize(QSize(BTN_SIZE,BTN_SIZE))
			btnApp.setToolTip(appDesc)
			btnApp.setFocusPolicy(Qt.NoFocus)
			btnApp.keypress.connect(self._set_focus)
			btnApp.focusIn.connect(self._get_focus)
			self.focusWidgets.append(btnApp)
			self.appsWidgets.append(appName)
			sigmap_run.setMapping(btnApp,appName)
			btnApp.clicked.connect(sigmap_run.map)
			vbox.addWidget(btnApp,row,col,Qt.Alignment(-1))
			col+=1
			if col==self.maxCol:
				col=0
				row+=1
    def setup_board(self):
        gridLayout = QGridLayout()
        mapper = QSignalMapper(self)
        for row in range(3):
            for column in range(3):
                button = QPushButton()
                button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
                button.setText(" ")
                gridLayout.addWidget(button, row, column)
                self.board.append(button)
                mapper.setMapping(button, len(self.board) - 1)
                button.clicked.connect(mapper.map)

        mapper.mapped.connect(self.handle_button_click)
        self.setLayout(gridLayout)
예제 #23
0
   def on_header_sectionClicked(self, logicalIndex):
       """opens a dialog to choose between all unique values for this column,
       or revert to 'All'
       """
       self.log.debug("Header clicked: column {}".format(logicalIndex))
       self.logicalIndex = logicalIndex
       menuValues = QMenu(self)
       self.signalMapper = QSignalMapper(self)  
 
       self.filter_cb.setCurrentIndex(self.logicalIndex)
       self.filter_cb.blockSignals(True)
       self.proxy.setFilterKeyColumn(self.logicalIndex)
       
       valuesUnique = [str(self.model.index(row, self.logicalIndex).data())
                       for row in range(self.model.rowCount())
                       ]
       
       actionAll = QAction("All", self)
       actionAll.triggered.connect(self.on_actionAll_triggered)
       menuValues.addAction(actionAll)
       menuValues.addSeparator()
       
       for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))):              
           action = QAction(actionName, self)
           self.signalMapper.setMapping(action, actionNumber)  
           action.triggered.connect(self.signalMapper.map)  
           menuValues.addAction(action)
 
       self.signalMapper.mapped.connect(self.on_signalMapper_mapped)  
 
       headerPos = self.table.mapToGlobal(self.header.pos())        
       posY = headerPos.y() + self.header.height()
       posX = headerPos.x() + self.header.sectionViewportPosition(self.logicalIndex)
 
       menuValues.exec_(QPoint(posX, posY))
예제 #24
0
 def initDialog(self):
     """Creates buttons for each sequence option and add them to the dialog.
     Maps the clicked signal of those buttons to keep track of what sequence
     gets selected.
     """
     ui_dlg = Ui_AddSeqDialog()
     ui_dlg.setupUi(self.dialog)
     self.signal_mapper = QSignalMapper(self)
     # set up the radio buttons
     for i, name in enumerate(['Abstract', 'Custom'] + sorted(sequences.keys())):
         radio_button = QRadioButton(ui_dlg.group_box)
         radio_button.setObjectName(name + "Button")
         radio_button.setText(name)
         self.buttons.append(radio_button)
         ui_dlg.horizontalLayout.addWidget(radio_button)
         self.signal_mapper.setMapping(radio_button, i)
         radio_button.clicked.connect(self.signal_mapper.map)
         if name in sequences:
             self.sequence_radio_button_id[sequences[name]] = i
     self.signal_mapper.mapped.connect(self.sequenceOptionChangedSlot)
     # disable apply until valid option or custom sequence is chosen
     self.apply_button = ui_dlg.custom_button_box.button(QDialogButtonBox.Apply)
     self.apply_button.setEnabled(False)
     # watch sequence textedit box to validate custom sequences
     self.seq_box = ui_dlg.seq_text_edit
     self.seq_box.textChanged.connect(self.validateCustomSequence)
     self.highlighter = DNAHighlighter(self.seq_box)
     # finally, pre-click the first radio button
     self.buttons[0].click()
예제 #25
0
    def home(self):

        self.folderLoader = FolderLoader()

        self.saved = True

        #Parameters
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        self.createMainMenu()

        self.canvas = Canvas(parent=self)

        self.scrollArea = QScrollArea()
        self.scrollArea.setWidget(self.canvas)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setStyleSheet(STYLE_SHEET)

        self.labelCoordinates = QLabel('')
        self.statusBar.addPermanentWidget(self.labelCoordinates)

        self.toolbar = QToolBar(TOOLBAR_NAME, self)
        self.toolbar.setStyleSheet(STYLE_SHEET)
        self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.addToolBar(Qt.LeftToolBarArea, self.toolbar)

        self.mapper = QSignalMapper()
        self.createColorComboBox()
        self.createToolbarActions()
        self.createFileDock()

        self.setCentralWidget(self.scrollArea)
        self.update()
        self.showMaximized()
예제 #26
0
    def initUI(self):
        """UI is composed with """

        # variable for QSettings
        self.name_company = 'Michelin'
        self.name_product = 'Calculator NodeEditor'

        # Load filesheets
        self.stylesheet_filename = os.path.join(os.path.dirname(__file__),
                                                'qss/nodeeditor.qss')
        loadStylessheets(
            os.path.join(os.path.dirname(__file__), 'qss/nodeeditor-dark.qss'),
            self.stylesheet_filename)

        self.empty_icon = QIcon(".")

        if DEBUG:
            print('Registered Node')
            pp(CALC_NODES)

        # Instantiate the MultiDocument Area
        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)
        self.mdiArea.setTabsClosable(True)
        self.setCentralWidget(self.mdiArea)

        # Connect subWindowActivate to updateMenu
        # Activate the items on the file_menu and the edit_menu
        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        # from mdi example...
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        # instantiate various elements
        self.createNodesDock()
        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("Calculator NodeEditor Example")
예제 #27
0
	def _set_keymapping(self):
		#Disable meta association within plasma. I've no eggs to capture and block this event in kde
		for key,value in vars(Qt).items():
			if isinstance(value, Qt.Key):
				self.keymap[value]=key.partition('_')[2]
		self.modmap={
					Qt.ControlModifier: self.keymap[Qt.Key_Control],
					Qt.AltModifier: self.keymap[Qt.Key_Alt],
					Qt.ShiftModifier: self.keymap[Qt.Key_Shift],
					Qt.MetaModifier: self.keymap[Qt.Key_Meta],
					Qt.GroupSwitchModifier: self.keymap[Qt.Key_AltGr],
					Qt.KeypadModifier: self.keymap[Qt.Key_NumLock]
					}
		self.sigmap_tabSelect=QSignalMapper(self)
		self.sigmap_tabSelect.mapped[QInt].connect(self._on_tabSelect)
		self.sigmap_tabRemove=QSignalMapper(self)
		self.sigmap_tabRemove.mapped[QInt].connect(self._on_tabRemove)
예제 #28
0
    def refreshTilesetMenu(self):
        self.mTilesetMenu.clear()
        if (self.mTilesetMenuMapper):
            self.mTabBar.disconnect(self.mTilesetMenuMapper)
            del self.mTilesetMenuMapper

        self.mTilesetMenuMapper = QSignalMapper(self)
        self.mTilesetMenuMapper.mapped.connect(self.mTabBar.setCurrentIndex)
        currentIndex = self.mTabBar.currentIndex()
        for i in range(self.mTabBar.count()):
            action = QAction(self.mTabBar.tabText(i), self)
            action.setCheckable(True)
            self.mTilesetActionGroup.addAction(action)
            if (i == currentIndex):
                action.setChecked(True)
            self.mTilesetMenu.addAction(action)
            action.triggered.connect(self.mTilesetMenuMapper.map)
            self.mTilesetMenuMapper.setMapping(action, i)
예제 #29
0
	def onSelectionMenuClicked ( self ):
		signalMapper = QSignalMapper ( self )
		acts = self.tabSelectionMenu.actions ()
		activeAction = self.currentIndex ()

		for i in range ( 0, acts.size () ):
			self.tabSelectionMenu.removeAction ( acts[ i ] )

		for i in range ( 0, self.count () ):
			action = self.tabSelectionMenu.addAction ( self.tabText ( i ) )
			action.triggered.connect ( signalMapper.map )
			signalMapper.setMapping ( action, i )

		if activeAction >= 0:
			acts = self.tabSelectionMenu.actions ()
			acts[ activeAction ].setIcon ( QIcon ( "./resources/general_tick.ico" ) )  # TODO: CryIcon

		signalMapper.mapped.connect ( self.setCurrentIndex )
예제 #30
0
	def __init__(self, **kwargs):
		super(Monitor, self).__init__(**kwargs)

		self.watched = WeakValueDictionary()
		self.delMapper = QSignalMapper(self)
		self.delMapper.mapped[str].connect(self.unmonitorFile)

		self.watcher = MonitorWithRename(parent=self)
		self.watcher.fileChanged.connect(self._onFileChanged)
예제 #31
0
    def __init__(self):
        super(MainWindow, self).__init__()

        self.ports = serial.listports()
        self.port = None

        # remove close & maximize window buttons
        #self.setWindowFlags(Qt.CustomizeWindowHint|Qt.WindowMinimizeButtonHint)
        self.setMinimumSize(850, 450)

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)

        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.child = None

        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.updateMenus()
        self.readSettings()
        self.setWindowTitle("VISCAM")

        mytoolbar = QToolBar()
        ports_menu = QComboBox()
        ports_menu.addItem('Output Port')
        ports_menu.insertSeparator(1)
        for port in self.ports:
            ports_menu.addItem(port)
        self.ports_menu = ports_menu
        ports_menu.currentTextChanged.connect(self.setActivePort)
        mytoolbar.addWidget(ports_menu)
        mytoolbar.addSeparator()
        mytoolbar.setMovable(False)
        mytoolbar.setFixedHeight(60)
        self.addToolBar(Qt.TopToolBarArea, mytoolbar)
예제 #32
0
 def __init__(self):
     super().__init__()
     grid = QGridLayout(self)
     mapper = QSignalMapper(self)
     btns = (('1', '2', '3', '+'),
             ('4', '5', '6', '-'),
             ('7', '8', '9', '*'),
             ('0', '.', '=', '/'),
             )
     self.line = QLineEdit()
     self.flag = False
     grid.addWidget(self.line, 0, 0, 1, 4)
     for row in range(4):
         for col in range(4):
             button = QPushButton(btns[row][col])
             grid.addWidget(button, row + 1, col)
             button.clicked.connect(mapper.map)
             mapper.setMapping(button, button.text())
     mapper.mapped[str].connect(self.on_mapped)
예제 #33
0
class MyWindow(QWidget):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setGeometry(100, 100, 600, 400)
        self.setWindowTitle("Send to Player")

        self.list = MyListWidget(self)
        self.uploader = Uploader(self.list, self)

        layout = QHBoxLayout(self)
        layout.addWidget(self.list)

        self.browserMapper = QSignalMapper()
        self.openSourceButton = QPushButton('&Open Music Archive')
        self.openSourceButton.released.connect(self.browserMapper.map)
        self.browserMapper.setMapping(self.openSourceButton,
                                      config.mediaSource)
        self.openTargetButton = QPushButton('Open &Player')
        self.openTargetButton.released.connect(self.browserMapper.map)
        self.browserMapper.setMapping(self.openTargetButton,
                                      config.mediaTarget)
        self.browserMapper.mapped[str].connect(
            lambda b: QDesktopServices.openUrl(QUrl(b)))

        self.submitButton = QPushButton('&Send to Player')
        self.submitButton.released.connect(self.uploader.uploadMedia)
        self.deleteSelectedButton = QPushButton('&Delete\nSelected')
        self.deleteSelectedButton.released.connect(self.list.deleteSelected)

        controls = QVBoxLayout()
        controls.addWidget(QLabel('Filesystem Browsers'))
        controls.addWidget(self.openSourceButton)
        controls.addWidget(self.openTargetButton)
        controls.addWidget(Separator(self))
        controls.addWidget(self.deleteSelectedButton)
        controls.addWidget(Separator(self))
        controls.addStretch()
        controls.addWidget(self.submitButton)

        layout.addLayout(controls)

        self.setLayout(layout)
예제 #34
0
    def initDialog(self):
        """
        1. Create buttons according to available scaffold sequences and
        add them to the dialog.
        2. Map the clicked signal of those buttons to keep track of what
        sequence gets selected.
        3. Watch the tab_widget change signal to determine whether a
        standard or custom sequence should be applied.
        """
        ui_dlg = Ui_AddSeqDialog()
        ui_dlg.setupUi(self.dialog)
        self.signal_mapper = QSignalMapper(self)
        # set up the radio buttons
        for i, name in enumerate(sorted(sequences.keys())):
            radio_button = QRadioButton(ui_dlg.group_box)
            radio_button.setObjectName(name + "Button")
            radio_button.setText(name)
            self.buttons.append(radio_button)
            ui_dlg.verticalLayout.addWidget(radio_button)
            self.signal_mapper.setMapping(radio_button, i)
            radio_button.clicked.connect(self.signal_mapper.map)
        self.signal_mapper.mapped.connect(self.standardSequenceChangedSlot)
        ui_dlg.tab_widget.currentChanged.connect(self.tabWidgetChangedSlot)
        # disable apply until valid option or custom sequence is chosen
        self.apply_button = ui_dlg.custom_button_box.button(
            QDialogButtonBox.Apply)
        self.apply_button.setEnabled(False)
        # watch sequence textedit box to validate custom sequences
        self.seq_box = ui_dlg.seq_text_edit
        self.seq_box.textChanged.connect(self.validateCustomSequence)
        self.highlighter = DNAHighlighter(self.seq_box)
        # finally, pre-click the M13mp18 radio button
        self.buttons[0].click()
        buttons = self.buttons

        self.dialog.setFocusProxy(ui_dlg.group_box)
        self.dialog.setFocusPolicy(Qt.TabFocus)
        ui_dlg.group_box.setFocusPolicy(Qt.TabFocus)
        for i in range(len(buttons) - 1):
            ui_dlg.group_box.setTabOrder(buttons[i], buttons[i + 1])
예제 #35
0
    def updatePlotPersoButton(self):
        menu = QMenu(self.mw)

        menus = []
        for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
            m = QMenu(i, menu)
            menus.append(m)
            menu.addMenu(m)

        mpr = QSignalMapper(menu)
        for i in range(self.mw.mdlPersos.rowCount()):
            a = QAction(self.mw.mdlPersos.name(i), menu)
            a.setIcon(self.mw.mdlPersos.icon(i))
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(self.mw.mdlPersos.ID(i)))

            imp = toInt(self.mw.mdlPersos.importance(i))

            menus[2 - imp].addAction(a)

        mpr.mapped.connect(self.addPlotPerso)
        self.mw.btnAddPlotPerso.setMenu(menu)
예제 #36
0
 def __init__(self):
     super(NetMainWindow, self).__init__()
     self.mdiArea = QMdiArea()
     self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
     self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
     self.setCentralWidget(self.mdiArea)
     self.windowMapper = QSignalMapper(self)
     self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)
     self.createActions()
     self.createMenus()
     self.createStatusBar()
     self.readSettings()
     self.setWindowTitle('Net')
    def onHeaderClicked(self, logicalIndex):
        if logicalIndex != 0:
            return  # allow filter on first column only for now

        self.logicalIndex = logicalIndex
        self.menuValues = QMenu(self)
        self.signalMapper = QSignalMapper(self)

        # get unique values from (unfiltered) model
        valuesUnique = set([
            self.table_model.index(row, self.logicalIndex).data()
            for row in range(
                self.table_model.rowCount(
                    self.table_model.index(-1, self.logicalIndex)))
        ])

        if len(valuesUnique) == 1:
            return  # no need to select anything

        actionAll = QAction("Show All", self)
        actionAll.triggered.connect(self.onShowAllRows)
        self.menuValues.addAction(actionAll)
        self.menuValues.addSeparator()
        """se_comment: hard-refactoring to comply to pep8"""
        l: enumerate = enumerate(sorted(list(set(valuesUnique))))
        for actionNumber, actionName in l:
            action = QAction(actionName, self)
            self.signalMapper.setMapping(action, actionNumber)
            action.triggered.connect(self.signalMapper.map)
            self.menuValues.addAction(action)

        self.signalMapper.mapped.connect(self.onSignalMapper)

        # get screen position of table header and open menu
        headerPos = self.table_view.mapToGlobal(self.horizontalHeader.pos())
        posY = headerPos.y() + self.horizontalHeader.height()
        posX = headerPos.x() + \
            self.horizontalHeader.sectionPosition(self.logicalIndex)
        self.menuValues.exec_(QPoint(posX, posY))
예제 #38
0
파일: input.py 프로젝트: MrLeeh/qthmi.main
    def __init__(self, parent: QWidget=None, text: str="") -> None:

        super(NumPad, self).__init__(parent)
        self.setupUi(self)  # type: ignore

        try:
            suffixIndex = text.index(" ")
        except ValueError:
            self.outputLineEdit.setText(text)
        else:
            self.outputLineEdit.setText(text[:suffixIndex])

        self.outputLineEdit.setSelection(0, len(self.outputLineEdit.text()))
        self.outputLineEdit.setFocus()

        self.signal_mapper = QSignalMapper(self)
        self.signal_mapper.setMapping(self.button0, "0")
        self.signal_mapper.setMapping(self.button1, "1")
        self.signal_mapper.setMapping(self.button2, "2")
        self.signal_mapper.setMapping(self.button3, "3")
        self.signal_mapper.setMapping(self.button4, "4")
        self.signal_mapper.setMapping(self.button5, "5")
        self.signal_mapper.setMapping(self.button6, "6")
        self.signal_mapper.setMapping(self.button7, "7")
        self.signal_mapper.setMapping(self.button8, "8")
        self.signal_mapper.setMapping(self.button9, "9")
        self.signal_mapper.setMapping(self.buttonDecimal, DECIMAL_SEPARATOR)
        self.signal_mapper.setMapping(self.buttonDel, "DEL")

        self.button0.pressed.connect(self.signal_mapper.map)
        self.button1.pressed.connect(self.signal_mapper.map)
        self.button2.pressed.connect(self.signal_mapper.map)
        self.button3.pressed.connect(self.signal_mapper.map)
        self.button4.pressed.connect(self.signal_mapper.map)
        self.button5.pressed.connect(self.signal_mapper.map)
        self.button6.pressed.connect(self.signal_mapper.map)
        self.button7.pressed.connect(self.signal_mapper.map)
        self.button8.pressed.connect(self.signal_mapper.map)
        self.button9.pressed.connect(self.signal_mapper.map)
        self.buttonDecimal.pressed.connect(self.signal_mapper.map)
        self.buttonDel.pressed.connect(self.signal_mapper.map)

        self.signal_mapper.mapped[str].connect(self.button_pressed)  # type: ignore
        self.buttonOK.pressed.connect(self.accept)
        self.buttonCancel.pressed.connect(self.close)
        self.outputLineEdit.focusOutEvent = self.focusOutEvent

        doubleValidator = QDoubleValidator()
        self.outputLineEdit.setValidator(doubleValidator)
예제 #39
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)
예제 #40
0
파일: main.py 프로젝트: skyballoon/PyQtTest
    def __init__(self):
        super(MainWindow, self).__init__()

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("MDI")
예제 #41
0
    def __init__(self):
        super(MainWindow, self).__init__()
        # remove close & maximize window buttons
        #self.setWindowFlags(Qt.CustomizeWindowHint|Qt.WindowMinimizeButtonHint)
        self.setMinimumSize(500, 666)
        #self.setMaximumSize(1000,666)
        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)

        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.child = None

        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.updateMenus()
        self.readSettings()
        self.setWindowTitle("LEKTURE")

        mytoolbar = QToolBar()
        #self.toolbar = self.addToolBar()
        mytoolbar.addAction(self.newAct)
        mytoolbar.addAction(self.openAct)
        mytoolbar.addAction(self.saveAct)
        mytoolbar.addAction(self.saveAsAct)
        mytoolbar.addSeparator()
        mytoolbar.addAction(self.outputsAct)
        mytoolbar.addAction(self.scenarioAct)
        self.scenarioAct.setVisible(False)
        mytoolbar.setMovable(False)
        mytoolbar.setFixedWidth(60)
        self.addToolBar(Qt.LeftToolBarArea, mytoolbar)
예제 #42
0
    def initDialog(self):
        """
        1. Create buttons according to available scaffold sequences and
        add them to the dialog.
        2. Map the clicked signal of those buttons to keep track of what
        sequence gets selected.
        3. Watch the tabWidget change signal to determine whether a
        standard or custom sequence should be applied.
        """
        uiDlg = Ui_AddSeqDialog()
        uiDlg.setupUi(self.dialog)
        self.signalMapper = QSignalMapper(self)
        # set up the radio buttons
        for i, name in enumerate(sorted(sequences.keys())):
            radioButton = QRadioButton(uiDlg.groupBox)
            radioButton.setObjectName(name + "Button")
            radioButton.setText(name)
            self.buttons.append(radioButton)
            uiDlg.verticalLayout.addWidget(radioButton)
            self.signalMapper.setMapping(radioButton, i)
            radioButton.clicked.connect(self.signalMapper.map)
        self.signalMapper.mapped.connect(self.standardSequenceChangedSlot)
        uiDlg.tabWidget.currentChanged.connect(self.tabWidgetChangedSlot)
        # disable apply until valid option or custom sequence is chosen
        self.applyButton = uiDlg.customButtonBox.button(QDialogButtonBox.Apply)
        self.applyButton.setEnabled(False)
        # watch sequence textedit box to validate custom sequences
        self.seqBox = uiDlg.seqTextEdit
        self.seqBox.textChanged.connect(self.validateCustomSequence)
        self.highlighter = DNAHighlighter(self.seqBox)
        # finally, pre-click the M13mp18 radio button
        self.buttons[0].click()
        buttons = self.buttons

        self.dialog.setFocusProxy(uiDlg.groupBox)
        self.dialog.setFocusPolicy(Qt.TabFocus)
        uiDlg.groupBox.setFocusPolicy(Qt.TabFocus)
        for i in range(len(buttons)-1):
            uiDlg.groupBox.setTabOrder(buttons[i], buttons[i+1])
예제 #43
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
    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 = MethodType(main_window_keyPressEvent, table_view)

    # 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 = MethodType(table_view_keyPressEvent, table_view)

    main_window.showMaximized()
    return app.exec_()
예제 #44
0
파일: main.py 프로젝트: skyballoon/PyQtTest
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.createActions()
        self.createMenus()
        self.createToolBars()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle("MDI")

    def closeEvent(self, event):
        self.mdiArea.closeAllSubWindows()
        if self.mdiArea.currentSubWindow():
            event.ignore()
        else:
            self.writeSettings()
            event.accept()

    def newFile(self):
        child = self.createMdiChild()
        child.newFile()
        child.show()

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self)
        if fileName:
            existing = self.findMdiChild(fileName)
            if existing:
                self.mdiArea.setActiveSubWindow(existing)
                return

            child = self.createMdiChild()
            if child.loadFile(fileName):
                self.statusBar().showMessage("File loaded", 2000)
                child.show()
            else:
                child.close()

    def save(self):
        if self.activeMdiChild() and self.activeMdiChild().save():
            self.statusBar().showMessage("File saved", 2000)

    def saveAs(self):
        if self.activeMdiChild() and self.activeMdiChild().saveAs():
            self.statusBar().showMessage("File saved", 2000)

    def cut(self):
        if self.activeMdiChild():
            self.activeMdiChild().cut()

    def copy(self):
        if self.activeMdiChild():
            self.activeMdiChild().copy()

    def paste(self):
        if self.activeMdiChild():
            self.activeMdiChild().paste()

    def about(self):
        QMessageBox.about(self, "About MDI",
                "The <b>MDI</b> example demonstrates how to write multiple "
                "document interface applications using Qt.")

    def updateMenus(self):
        hasMdiChild = (self.activeMdiChild() is not None)
        self.saveAct.setEnabled(hasMdiChild)
        self.saveAsAct.setEnabled(hasMdiChild)
        self.pasteAct.setEnabled(hasMdiChild)
        self.closeAct.setEnabled(hasMdiChild)
        self.closeAllAct.setEnabled(hasMdiChild)
        self.tileAct.setEnabled(hasMdiChild)
        self.cascadeAct.setEnabled(hasMdiChild)
        self.nextAct.setEnabled(hasMdiChild)
        self.previousAct.setEnabled(hasMdiChild)
        self.separatorAct.setVisible(hasMdiChild)

        hasSelection = (self.activeMdiChild() is not None and
                        self.activeMdiChild().textCursor().hasSelection())
        self.cutAct.setEnabled(hasSelection)
        self.copyAct.setEnabled(hasSelection)

    def updateWindowMenu(self):
        self.windowMenu.clear()
        self.windowMenu.addAction(self.closeAct)
        self.windowMenu.addAction(self.closeAllAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.tileAct)
        self.windowMenu.addAction(self.cascadeAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.nextAct)
        self.windowMenu.addAction(self.previousAct)
        self.windowMenu.addAction(self.separatorAct)

        windows = self.mdiArea.subWindowList()
        self.separatorAct.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            child = window.widget()

            text = "%d %s" % (i + 1, child.userFriendlyCurrentFile())
            if i < 9:
                text = '&' + text

            action = self.windowMenu.addAction(text)
            action.setCheckable(True)
            action.setChecked(child is self.activeMdiChild())
            action.triggered.connect(self.windowMapper.map)
            self.windowMapper.setMapping(action, window)

    def createMdiChild(self):
        child = MdiChild()
        self.mdiArea.addSubWindow(child)

        child.copyAvailable.connect(self.cutAct.setEnabled)
        child.copyAvailable.connect(self.copyAct.setEnabled)

        return child

    def createActions(self):
        self.newAct = QAction(QIcon(':/images/new.png'), "&New", self,
                shortcut=QKeySequence.New, statusTip="Create a new file",
                triggered=self.newFile)

        self.openAct = QAction(QIcon(':/images/open.png'), "&Open...", self,
                shortcut=QKeySequence.Open, statusTip="Open an existing file",
                triggered=self.open)

        self.saveAct = QAction(QIcon(':/images/save.png'), "&Save", self,
                shortcut=QKeySequence.Save,
                statusTip="Save the document to disk", triggered=self.save)

        self.saveAsAct = QAction("Save &As...", self,
                shortcut=QKeySequence.SaveAs,
                statusTip="Save the document under a new name",
                triggered=self.saveAs)

        self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit,
                statusTip="Exit the application",
                triggered=QApplication.instance().closeAllWindows)

        self.cutAct = QAction(QIcon(':/images/cut.png'), "Cu&t", self,
                shortcut=QKeySequence.Cut,
                statusTip="Cut the current selection's contents to the clipboard",
                triggered=self.cut)

        self.copyAct = QAction(QIcon(':/images/copy.png'), "&Copy", self,
                shortcut=QKeySequence.Copy,
                statusTip="Copy the current selection's contents to the clipboard",
                triggered=self.copy)

        self.pasteAct = QAction(QIcon(':/images/paste.png'), "&Paste", self,
                shortcut=QKeySequence.Paste,
                statusTip="Paste the clipboard's contents into the current selection",
                triggered=self.paste)

        self.closeAct = QAction("Cl&ose", self,
                statusTip="Close the active window",
                triggered=self.mdiArea.closeActiveSubWindow)

        self.closeAllAct = QAction("Close &All", self,
                statusTip="Close all the windows",
                triggered=self.mdiArea.closeAllSubWindows)

        self.tileAct = QAction("&Tile", self, statusTip="Tile the windows",
                triggered=self.mdiArea.tileSubWindows)

        self.cascadeAct = QAction("&Cascade", self,
                statusTip="Cascade the windows",
                triggered=self.mdiArea.cascadeSubWindows)

        self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild,
                statusTip="Move the focus to the next window",
                triggered=self.mdiArea.activateNextSubWindow)

        self.previousAct = QAction("Pre&vious", self,
                shortcut=QKeySequence.PreviousChild,
                statusTip="Move the focus to the previous window",
                triggered=self.mdiArea.activatePreviousSubWindow)

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

        self.aboutAct = QAction("&About", self,
                statusTip="Show the application's About box",
                triggered=self.about)

        self.aboutQtAct = QAction("About &Qt", self,
                statusTip="Show the Qt library's About box",
                triggered=QApplication.instance().aboutQt)

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addSeparator()
        action = self.fileMenu.addAction("Switch layout direction")
        action.triggered.connect(self.switchLayoutDirection)
        self.fileMenu.addAction(self.exitAct)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.addAction(self.cutAct)
        self.editMenu.addAction(self.copyAct)
        self.editMenu.addAction(self.pasteAct)

        self.windowMenu = self.menuBar().addMenu("&Window")
        self.updateWindowMenu()
        self.windowMenu.aboutToShow.connect(self.updateWindowMenu)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)
        self.helpMenu.addAction(self.aboutQtAct)

    def createToolBars(self):
        self.fileToolBar = self.addToolBar("File")
        self.fileToolBar.addAction(self.newAct)
        self.fileToolBar.addAction(self.openAct)
        self.fileToolBar.addAction(self.saveAct)

        self.editToolBar = self.addToolBar("Edit")
        self.editToolBar.addAction(self.cutAct)
        self.editToolBar.addAction(self.copyAct)
        self.editToolBar.addAction(self.pasteAct)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(400, 400))
        self.move(pos)
        self.resize(size)

    def writeSettings(self):
        settings = QSettings('Trolltech', 'MDI Example')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())

    def activeMdiChild(self):
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        return None

    def findMdiChild(self, fileName):
        canonicalFilePath = QFileInfo(fileName).canonicalFilePath()

        for window in self.mdiArea.subWindowList():
            if window.widget().currentFile() == canonicalFilePath:
                return window
        return None

    def switchLayoutDirection(self):
        if self.layoutDirection() == Qt.LeftToRight:
            QApplication.setLayoutDirection(Qt.RightToLeft)
        else:
            QApplication.setLayoutDirection(Qt.LeftToRight)

    def setActiveSubWindow(self, window):
        if window:
            self.mdiArea.setActiveSubWindow(window)
예제 #45
0
    def makePopupMenu(self):
        index = self.currentIndex()
        sel = self.getSelection()
        clipboard = qApp.clipboard()

        menu = QMenu(self)

        # Get index under cursor
        pos = self.viewport().mapFromGlobal(QCursor.pos())
        mouseIndex = self.indexAt(pos)

        # Get index's title
        if mouseIndex.isValid():
            title = mouseIndex.internalPointer().title()

        elif self.rootIndex().parent().isValid():
            # mouseIndex is the background of an item, so we check the parent
            mouseIndex = self.rootIndex().parent()
            title = mouseIndex.internalPointer().title()

        else:
            title = qApp.translate("outlineBasics", "Root")

        if len(title) > 25:
            title = title[:25] + "…"

        # Open Item action
        self.actOpen = QAction(QIcon.fromTheme("go-right"),
                               qApp.translate("outlineBasics", "Open {}".format(title)),
                               menu)
        self.actOpen.triggered.connect(self.openItem)
        menu.addAction(self.actOpen)

        # Open item(s) in new tab
        if mouseIndex in sel and len(sel) > 1:
            actionTitle = qApp.translate("outlineBasics", "Open {} items in new tabs").format(len(sel))
            self._indexesToOpen = sel
        else:
            actionTitle = qApp.translate("outlineBasics", "Open {} in a new tab").format(title)
            self._indexesToOpen = [mouseIndex]

        self.actNewTab = QAction(QIcon.fromTheme("go-right"), actionTitle, menu)
        self.actNewTab.triggered.connect(self.openItemsInNewTabs)
        menu.addAction(self.actNewTab)

        menu.addSeparator()

        # Add text / folder
        self.actAddFolder = QAction(QIcon.fromTheme("folder-new"),
                                    qApp.translate("outlineBasics", "New &Folder"),
                                    menu)
        self.actAddFolder.triggered.connect(self.addFolder)
        menu.addAction(self.actAddFolder)

        self.actAddText = QAction(QIcon.fromTheme("document-new"),
                                  qApp.translate("outlineBasics", "New &Text"),
                                  menu)
        self.actAddText.triggered.connect(self.addText)
        menu.addAction(self.actAddText)

        menu.addSeparator()

        # Copy, cut, paste, duplicate
        self.actCut = QAction(QIcon.fromTheme("edit-cut"),
                              qApp.translate("outlineBasics", "C&ut"), menu)
        self.actCut.triggered.connect(self.cut)
        menu.addAction(self.actCut)

        self.actCopy = QAction(QIcon.fromTheme("edit-copy"),
                               qApp.translate("outlineBasics", "&Copy"), menu)
        self.actCopy.triggered.connect(self.copy)
        menu.addAction(self.actCopy)

        self.actPaste = QAction(QIcon.fromTheme("edit-paste"),
                                qApp.translate("outlineBasics", "&Paste"), menu)
        self.actPaste.triggered.connect(self.paste)
        menu.addAction(self.actPaste)

        # Rename / duplicate / remove items
        self.actDelete = QAction(QIcon.fromTheme("edit-delete"),
                                 qApp.translate("outlineBasics", "&Delete"),
                                 menu)
        self.actDelete.triggered.connect(self.delete)
        menu.addAction(self.actDelete)

        self.actRename = QAction(QIcon.fromTheme("edit-rename"),
                                 qApp.translate("outlineBasics", "&Rename"),
                                 menu)
        self.actRename.triggered.connect(self.rename)
        menu.addAction(self.actRename)

        menu.addSeparator()

        # POV
        self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu)
        mw = mainWindow()
        a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuPOV)
        a.triggered.connect(lambda: self.setPOV(""))
        self.menuPOV.addAction(a)
        self.menuPOV.addSeparator()

        menus = []
        for i in [qApp.translate("outlineBasics", "Main"),
                  qApp.translate("outlineBasics", "Secondary"),
                  qApp.translate("outlineBasics", "Minor")]:
            m = QMenu(i, self.menuPOV)
            menus.append(m)
            self.menuPOV.addMenu(m)

        mpr = QSignalMapper(self.menuPOV)
        for i in range(mw.mdlCharacter.rowCount()):
            a = QAction(mw.mdlCharacter.icon(i), mw.mdlCharacter.name(i), self.menuPOV)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(mw.mdlCharacter.ID(i)))

            imp = toInt(mw.mdlCharacter.importance(i))

            menus[2 - imp].addAction(a)

        mpr.mapped.connect(self.setPOV)
        menu.addMenu(self.menuPOV)

        # Status
        self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"), menu)
        # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
        # a.triggered.connect(lambda: self.setStatus(""))
        # self.menuStatus.addAction(a)
        # self.menuStatus.addSeparator()

        mpr = QSignalMapper(self.menuStatus)
        for i in range(mw.mdlStatus.rowCount()):
            a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuStatus.addAction(a)
        mpr.mapped.connect(self.setStatus)
        menu.addMenu(self.menuStatus)

        # Labels
        self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"), menu)
        mpr = QSignalMapper(self.menuLabel)
        for i in range(mw.mdlLabels.rowCount()):
            a = QAction(mw.mdlLabels.item(i, 0).icon(),
                        mw.mdlLabels.item(i, 0).text(),
                        self.menuLabel)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuLabel.addAction(a)
        mpr.mapped.connect(self.setLabel)
        menu.addMenu(self.menuLabel)

        menu.addSeparator()

        # Custom icons
        if self.menuCustomIcons:
            menu.addMenu(self.menuCustomIcons)
        else:
            self.menuCustomIcons = QMenu(qApp.translate("outlineBasics", "Set Custom Icon"), menu)
            a = QAction(qApp.translate("outlineBasics", "Restore to default"), self.menuCustomIcons)
            a.triggered.connect(lambda: self.setCustomIcon(""))
            self.menuCustomIcons.addAction(a)
            self.menuCustomIcons.addSeparator()

            txt = QLineEdit()
            txt.textChanged.connect(self.filterLstIcons)
            txt.setPlaceholderText("Filter icons")
            txt.setStyleSheet("QLineEdit { background: transparent; border: none; }")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(txt)
            self.menuCustomIcons.addAction(act)

            self.lstIcons = QListWidget()
            for i in customIcons():
                item = QListWidgetItem()
                item.setIcon(QIcon.fromTheme(i))
                item.setData(Qt.UserRole, i)
                item.setToolTip(i)
                self.lstIcons.addItem(item)
            self.lstIcons.itemClicked.connect(self.setCustomIconFromItem)
            self.lstIcons.setViewMode(self.lstIcons.IconMode)
            self.lstIcons.setUniformItemSizes(True)
            self.lstIcons.setResizeMode(self.lstIcons.Adjust)
            self.lstIcons.setMovement(self.lstIcons.Static)
            self.lstIcons.setStyleSheet("background: transparent; background: none;")
            self.filterLstIcons("")
            act = QWidgetAction(self.menuCustomIcons)
            act.setDefaultWidget(self.lstIcons)
            self.menuCustomIcons.addAction(act)

            menu.addMenu(self.menuCustomIcons)

        # Disabling stuff
        if not clipboard.mimeData().hasFormat("application/xml"):
            self.actPaste.setEnabled(False)

        if len(sel) == 0:
            self.actCopy.setEnabled(False)
            self.actCut.setEnabled(False)
            self.actRename.setEnabled(False)
            self.actDelete.setEnabled(False)
            self.menuPOV.setEnabled(False)
            self.menuStatus.setEnabled(False)
            self.menuLabel.setEnabled(False)
            self.menuCustomIcons.setEnabled(False)

        if len(sel) > 1:
            self.actRename.setEnabled(False)

        return menu
예제 #46
0
파일: input.py 프로젝트: MrLeeh/qthmi.main
class NumPad(QDialog, Ui_numPad):
    """Numpad for user input.

    Enables the user to insert numbers on a touchscreen.

    """

    def __init__(self, parent: QWidget=None, text: str="") -> None:

        super(NumPad, self).__init__(parent)
        self.setupUi(self)  # type: ignore

        try:
            suffixIndex = text.index(" ")
        except ValueError:
            self.outputLineEdit.setText(text)
        else:
            self.outputLineEdit.setText(text[:suffixIndex])

        self.outputLineEdit.setSelection(0, len(self.outputLineEdit.text()))
        self.outputLineEdit.setFocus()

        self.signal_mapper = QSignalMapper(self)
        self.signal_mapper.setMapping(self.button0, "0")
        self.signal_mapper.setMapping(self.button1, "1")
        self.signal_mapper.setMapping(self.button2, "2")
        self.signal_mapper.setMapping(self.button3, "3")
        self.signal_mapper.setMapping(self.button4, "4")
        self.signal_mapper.setMapping(self.button5, "5")
        self.signal_mapper.setMapping(self.button6, "6")
        self.signal_mapper.setMapping(self.button7, "7")
        self.signal_mapper.setMapping(self.button8, "8")
        self.signal_mapper.setMapping(self.button9, "9")
        self.signal_mapper.setMapping(self.buttonDecimal, DECIMAL_SEPARATOR)
        self.signal_mapper.setMapping(self.buttonDel, "DEL")

        self.button0.pressed.connect(self.signal_mapper.map)
        self.button1.pressed.connect(self.signal_mapper.map)
        self.button2.pressed.connect(self.signal_mapper.map)
        self.button3.pressed.connect(self.signal_mapper.map)
        self.button4.pressed.connect(self.signal_mapper.map)
        self.button5.pressed.connect(self.signal_mapper.map)
        self.button6.pressed.connect(self.signal_mapper.map)
        self.button7.pressed.connect(self.signal_mapper.map)
        self.button8.pressed.connect(self.signal_mapper.map)
        self.button9.pressed.connect(self.signal_mapper.map)
        self.buttonDecimal.pressed.connect(self.signal_mapper.map)
        self.buttonDel.pressed.connect(self.signal_mapper.map)

        self.signal_mapper.mapped[str].connect(self.button_pressed)  # type: ignore
        self.buttonOK.pressed.connect(self.accept)
        self.buttonCancel.pressed.connect(self.close)
        self.outputLineEdit.focusOutEvent = self.focusOutEvent

        doubleValidator = QDoubleValidator()
        self.outputLineEdit.setValidator(doubleValidator)

    @pyqtSlot(str)
    def button_pressed(self, value: str) -> None:
        """Handle a pressed button."""
        cursor_position = self.outputLineEdit.cursorPosition()

        # Bei markierten Zeichen diese löschen
        if len(self.outputLineEdit.selectedText()) > 0:

            cursor_position = self.outputLineEdit.selectionStart()
            selection_length = len(self.outputLineEdit.selectedText())

            self.outputLineEdit.setText(
                string_remove_by_index(
                    self.outputLineEdit.text(),
                    start_index=cursor_position,
                    length=selection_length
                )
            )

        # Bei DEL letztes Zeichen löschen
        elif value == "DEL":
            # self.outputLineEdit.setText(self.outputLineEdit.text().remove(
            #    self.outputLineEdit.cursorPosition() - 1, 1))

            self.outputLineEdit.setText(
                string_remove_by_index(
                    self.outputLineEdit.text(),
                    start_index=self.outputLineEdit.cursorPosition() - 1,
                    length=1)
            )

        # Wenn nicht DEL, dann Zeichen schreiben
        if not value == "DEL":
            if value == DECIMAL_SEPARATOR:
                if DECIMAL_SEPARATOR not in self.outputLineEdit.text():
                    self.outputLineEdit.setText(
                        string_insert(self.outputLineEdit.text(),
                                      str(value), cursor_position)
                    )
            else:
                self.outputLineEdit.setText(
                    string_insert(self.outputLineEdit.text(), str(value),
                                  cursor_position)
                )
예제 #47
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._viewMode = None
        self._quickSendOptRow = 1

        self.setupUi(self)
        self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea)
        self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea)
        font = QtGui.QFont()
        font.setFamily(EDITOR_FONT)
        font.setPointSize(9)
        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.setupMenu()
        self.setupFlatUi()
        self.onEnumPorts()

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

        self.defaultStyleWidget = QWidget()
        self.defaultStyleWidget.setWindowIcon(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.openQuickSend)
        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.onSend)

        self.receiver_thread.read.connect(self.onReceive)
        self.receiver_thread.exception.connect(self.onReaderExcept)
        self._signalMapQuickSendOpt = QSignalMapper(self)
        self._signalMapQuickSendOpt.mapped[int].connect(self.onQuickSendOptions)
        self._signalMapQuickSend = QSignalMapper(self)
        self._signalMapQuickSend.mapped[int].connect(self.onQuickSend)

        # 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 setupMenu(self):
        self.menuMenu = QtWidgets.QMenu()
        self.menuMenu.setTitle("&File")
        self.menuMenu.setObjectName("menuMenu")
        self.menuView = QtWidgets.QMenu(self.menuMenu)
        self.menuView.setTitle("&View")
        self.menuView.setObjectName("menuView")

        self.menuView.addAction(self.actionAscii)
        self.menuView.addAction(self.actionHex_lowercase)
        self.menuView.addAction(self.actionHEX_UPPERCASE)
        self.menuMenu.addAction(self.actionOpen_Cmd_File)
        self.menuMenu.addAction(self.actionSave_Log)
        self.menuMenu.addSeparator()
        self.menuMenu.addAction(self.actionPort_Config_Panel)
        self.menuMenu.addAction(self.actionQuick_Send_Panel)
        self.menuMenu.addAction(self.actionSend_Hex_Panel)
        self.menuMenu.addAction(self.menuView.menuAction())
        self.menuMenu.addAction(self.actionLocal_Echo)
        self.menuMenu.addAction(self.actionAlways_On_Top)
        self.menuMenu.addSeparator()
        self.menuMenu.addAction(self.actionAbout)
        self.menuMenu.addAction(self.actionAbout_Qt)
        self.menuMenu.addSeparator()
        self.menuMenu.addAction(self.actionExit)

        self.sendOptMenu = QtWidgets.QMenu()
        self.actionSend_Hex = QtWidgets.QAction(self)
        self.actionSend_Hex.setText("Send &Hex")
        self.actionSend_Hex.setStatusTip("Send Hex (e.g. 31 32 FF)")

        self.actionSend_Asc = QtWidgets.QAction(self)
        self.actionSend_Asc.setText("Send &Asc")
        self.actionSend_Asc.setStatusTip("Send Asc (e.g. abc123)")

        self.actionSend_TFH = QtWidgets.QAction(self)
        self.actionSend_TFH.setText("Send &Text file as hex")
        self.actionSend_TFH.setStatusTip('Send text file as hex (e.g. strings "31 32 FF" in the file)')

        self.actionSend_TFA = QtWidgets.QAction(self)
        self.actionSend_TFA.setText("Send t&Ext file as asc")
        self.actionSend_TFA.setStatusTip('Send text file as asc (e.g. strings "abc123" in the file)')

        self.actionSend_FB = QtWidgets.QAction(self)
        self.actionSend_FB.setText("Send &Bin/Hex file")
        self.actionSend_FB.setStatusTip("Send a bin file or a hex file")

        self.sendOptMenu.addAction(self.actionSend_Hex)
        self.sendOptMenu.addAction(self.actionSend_Asc)
        self.sendOptMenu.addAction(self.actionSend_TFH)
        self.sendOptMenu.addAction(self.actionSend_TFA)
        self.sendOptMenu.addAction(self.actionSend_FB)

        self.actionSend_Hex.triggered.connect(self.onSetSendHex)
        self.actionSend_Asc.triggered.connect(self.onSetSendAsc)
        self.actionSend_TFH.triggered.connect(self.onSetSendTFH)
        self.actionSend_TFA.triggered.connect(self.onSetSendTFA)
        self.actionSend_FB.triggered.connect(self.onSetSendFB)

    def setupFlatUi(self):
        self._dragPos = self.pos()
        self._isDragging = False
        self.setMouseTracking(True)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setStyleSheet("""
            QWidget {
                background-color: %(BackgroundColor)s;
                /*background-image: url(:/background.png);*/
                outline: none;
            }
            QLabel {
                color:%(TextColor)s;
                font-size:12px;
                /*font-family:Century;*/
            }
            
            QComboBox {
                color:%(TextColor)s;
                font-size:12px;
                /*font-family:Century;*/
            }
            QComboBox {
                border: none;
                padding: 1px 1px 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:%(TextColor)s;
                font-size:12px;
                /*font-family:Century;*/
                border: 1px solid gray;
                margin-top: 15px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top left;
                left:5px;
                top:3px;
            }
            
            QCheckBox {
                color:%(TextColor)s;
                spacing: 5px;
                font-size:12px;
                /*font-family:Century;*/
            }
            QCheckBox::indicator:unchecked {
                image: url(:/checkbox_unchecked.png);
            }

            QCheckBox::indicator:unchecked:hover {
                image: url(:/checkbox_unchecked_hover.png);
            }

            QCheckBox::indicator:unchecked:pressed {
                image: url(:/checkbox_unchecked_pressed.png);
            }

            QCheckBox::indicator:checked {
                image: url(:/checkbox_checked.png);
            }

            QCheckBox::indicator:checked:hover {
                image: url(:/checkbox_checked_hover.png);
            }

            QCheckBox::indicator:checked:pressed {
                image: url(:/checkbox_checked_pressed.png);
            }
            
            QScrollBar:horizontal {
                background-color:%(BackgroundColor)s;
                border: none;
                height: 15px;
                margin: 0px 20px 0 20px;
            }
            QScrollBar::handle:horizontal {
                background: %(ScrollBar_Handle)s;
                min-width: 20px;
            }
            QScrollBar::add-line:horizontal {
                image: url(:/rightarrow.png);
                border: none;
                background: %(ScrollBar_Line)s;
                width: 20px;
                subcontrol-position: right;
                subcontrol-origin: margin;
            }
            QScrollBar::sub-line:horizontal {
                image: url(:/leftarrow.png);
                border: none;
                background: %(ScrollBar_Line)s;
                width: 20px;
                subcontrol-position: left;
                subcontrol-origin: margin;
            }
            
            QScrollBar:vertical {
                background-color:%(BackgroundColor)s;
                border: none;
                width: 15px;
                margin: 20px 0px 20px 0px;
            }
            QScrollBar::handle::vertical {
                background: %(ScrollBar_Handle)s;
                min-height: 20px;
            }
            QScrollBar::add-line::vertical {
                image: url(:/downarrow.png);
                border: none;
                background: %(ScrollBar_Line)s;
                height: 20px;
                subcontrol-position: bottom;
                subcontrol-origin: margin;
            }
            QScrollBar::sub-line::vertical {
                image: url(:/uparrow.png);
                border: none;
                background: %(ScrollBar_Line)s;
                height: 20px;
                subcontrol-position: top;
                subcontrol-origin: margin;
            }
            
            QTableView {
                background-color: white;
                /*selection-background-color: #FF92BB;*/
                border: 1px solid %(TableView_Border)s;
                color: %(TextColor)s;
            }
            QTableView::focus {
                /*border: 1px solid #2a7fff;*/
            }
            QTableView QTableCornerButton::section {
                border: none;
                border-right: 1px solid %(TableView_Border)s;
                border-bottom: 1px solid %(TableView_Border)s;
                background-color: %(TableView_Corner)s;
            }
            QTableView QWidget {
                background-color: white;
            }
            QTableView::item:focus {
                border: 1px red;
                background-color: transparent;
                color: %(TextColor)s;
            }
            QHeaderView::section {
                border: none;
                border-right: 1px solid %(TableView_Border)s;
                border-bottom: 1px solid %(TableView_Border)s;
                padding-left: 2px;
                padding-right: 2px;
                color: #444444;
                background-color: %(TableView_Header)s;
            }
            QTextEdit {
                background-color:white;
                color:%(TextColor)s;
                border-top: none;
                border-bottom: none;
                border-left: 2px solid %(BackgroundColor)s;
                border-right: 2px solid %(BackgroundColor)s;
            }
            QTextEdit::focus {
            }
            
            QToolButton, QPushButton {
                background-color:#30a7b8;
                border:none;
                color:#ffffff;
                font-size:12px;
                /*font-family:Century;*/
            }
            QToolButton:hover, QPushButton:hover {
                background-color:#51c0d1;
            }
            QToolButton:pressed, QPushButton:pressed {
                background-color:#3a9ecc;
            }
            
            QMenuBar {
                color: %(TextColor)s;
                height: 24px;
            }
            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: %(TextColor)s;
                background: #ffffff;
            }
            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:12px;
                /*font-family:Century;*/
                color: %(TextColor)s;
                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;
            }
            
        """ % dict(
            BackgroundColor =  '#99d9ea',
            TextColor =        '#202020',
            ScrollBar_Handle = '#61b9e1',
            ScrollBar_Line =   '#7ecfe4',
            TableView_Corner = '#8ae6d2',
            TableView_Header = '#8ae6d2',
            TableView_Border = '#eeeeee'
        ))
        self.dockWidgetContents.setStyleSheet("""
            QPushButton {
                min-height:23px;
            }
        """)
        self.dockWidget_QuickSend.setStyleSheet("""
            QToolButton, QPushButton {
                background-color:#27b798;
                /*font-family:Consolas;*/
                /*font-size:12px;*/
                /*min-width:46px;*/
            }
            QToolButton:hover, QPushButton:hover {
                background-color:#3bd5b4;
            }
            QToolButton:pressed, 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);
            }
        """)
        
        self.btnMenu = QtWidgets.QToolButton(self)
        self.btnMenu.setEnabled(True)
        self.btnMenu.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
        self.btnMenu.setIcon(QtGui.QIcon(':/MyTerm.ico'))
        self.btnMenu.setText('Myterm  ')
        self.btnMenu.setGeometry(3,3,80,18)
        self.btnMenu.setMenu(self.menuMenu)
        self.btnMenu.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        
        self.btnRefresh = QtWidgets.QToolButton(self)
        self.btnRefresh.setEnabled(True)
        self.btnRefresh.setIcon(QtGui.QIcon(':/refresh.ico'))
        self.btnRefresh.setGeometry(110,3,18,18)
        self.btnRefresh.clicked.connect(self.onEnumPorts)
        
        self.verticalLayout_1.removeWidget(self.cmbPort)
        self.cmbPort.setParent(self)
        self.cmbPort.setGeometry(128,3,60,18)
        
        self.verticalLayout_1.removeWidget(self.btnOpen)
        self.btnOpen.setParent(self)
        self.btnOpen.setGeometry(210,3,60,18)
        
    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() == 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('MyTerm.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("MyTerm.xml")):
            with open(get_config_path("MyTerm.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)
                self._viewMode = VIEWMODE_ASCII
            elif 'lowercase' in ReceiveView:
                self.actionHex_lowercase.setChecked(True)
                self._viewMode = VIEWMODE_HEX_LOWERCASE
            elif 'UPPERCASE' in ReceiveView:
                self.actionHEX_UPPERCASE.setChecked(True)
                self._viewMode = VIEWMODE_HEX_UPPERCASE
            self.receiver_thread.setViewMode(self._viewMode)

    def closeEvent(self, event):
        self.saveLayout()
        self.saveQuickSend()
        self.saveSettings()
        event.accept()

    def initQuickSend(self):
        #self.quickSendTable.horizontalHeader().setDefaultSectionSize(40)
        #self.quickSendTable.horizontalHeader().setMinimumSectionSize(25)
        self.quickSendTable.setRowCount(50)
        self.quickSendTable.setColumnCount(3)
        self.quickSendTable.verticalHeader().setSectionsClickable(True)

        for row in range(50):
            self.initQuickSendButton(row)

        if os.path.isfile(get_config_path('QuickSend.csv')):
            self.loadQuickSend(get_config_path('QuickSend.csv'))

        self.quickSendTable.resizeColumnsToContents()

    def initQuickSendButton(self, row, cmd = 'cmd', opt = 'H', dat = ''):
        if self.quickSendTable.cellWidget(row, 0) is None:
            item = QToolButton(self)
            item.setText(cmd)
            item.clicked.connect(self._signalMapQuickSend.map)
            self._signalMapQuickSend.setMapping(item, row)
            self.quickSendTable.setCellWidget(row, 0, item)
        else:
            self.quickSendTable.cellWidget(row, 0).setText(cmd)

        if self.quickSendTable.cellWidget(row, 1) is None:
            item = QToolButton(self)
            item.setText(opt)
            #item.setMaximumSize(QtCore.QSize(16, 16))
            item.clicked.connect(self._signalMapQuickSendOpt.map)
            self._signalMapQuickSendOpt.setMapping(item, row)
            self.quickSendTable.setCellWidget(row, 1, item)
        else:
            self.quickSendTable.cellWidget(row, 1).setText(opt)

        if self.quickSendTable.item(row, 2) is None:
            self.quickSendTable.setItem(row, 2, QTableWidgetItem(dat))
        else:
            self.quickSendTable.item(row, 2).setText(dat)

        self.quickSendTable.setRowHeight(row, 16)

    def onSetSendHex(self):
        item = self.quickSendTable.cellWidget(self._quickSendOptRow, 1)
        item.setText('H')

    def onSetSendAsc(self):
        item = self.quickSendTable.cellWidget(self._quickSendOptRow, 1)
        item.setText('A')

    def onSetSendTFH(self):
        item = self.quickSendTable.cellWidget(self._quickSendOptRow, 1)
        item.setText('FH')

    def onSetSendTFA(self):
        item = self.quickSendTable.cellWidget(self._quickSendOptRow, 1)
        item.setText('FA')

    def onSetSendFB(self):
        item = self.quickSendTable.cellWidget(self._quickSendOptRow, 1)
        item.setText('FB')

    def onQuickSendOptions(self, row):
        self._quickSendOptRow = row
        item = self.quickSendTable.cellWidget(row, 1)
        self.sendOptMenu.popup(item.mapToGlobal(QPoint(item.size().width(), item.size().height())))

    def openQuickSend(self):
        fileName = QFileDialog.getOpenFileName(self, "Select a file",
            os.getcwd(), "CSV Files (*.csv)")[0]
        if fileName:
            self.loadQuickSend(fileName, notifyExcept = True)

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

        save_data = [[self.quickSendTable.cellWidget(row, 0).text(),
                      self.quickSendTable.cellWidget(row, 1).text(),
                      self.quickSendTable.item(row, 2) is not None
                      and self.quickSendTable.item(row, 2).text() or ''] for row in range(rows)]

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

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

    def loadQuickSend(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.defaultStyleWidget, "Open failed",
                    str(e), QMessageBox.Close)
            return

        rows = self.quickSendTable.rowCount()
        cols = self.quickSendTable.columnCount()

        if rows < set_rows:
            rows = set_rows + 10
            self.quickSendTable.setRowCount(rows)

        for row, rowdat in enumerate(data):
            if len(rowdat) >= 3:
                cmd, opt, dat = rowdat[0:3]
                self.initQuickSendButton(row, cmd, opt, dat)
#                self.quickSendTable.cellWidget(row, 0).setText(cmd)
#                self.quickSendTable.cellWidget(row, 1).setText(opt)
#                self.quickSendTable.setItem(row, 2, QTableWidgetItem(dat))

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

    def onQuickSend(self, row):
        if self.quickSendTable.item(row, 2) is not None:
            tablestring = self.quickSendTable.item(row, 2).text()
            format = self.quickSendTable.cellWidget(row, 1).text()
            if 'H' == format:
                self.transmitHex(tablestring)
            elif 'A' == format:
                self.transmitAsc(tablestring)
            elif 'FB' == format:
                try:
                    with open(tablestring, 'rb') as f:
                        bytes = f.read()
                        self.transmitBytearray(bytes)
                except IOError as e:
                    print("({})".format(e))
                    QMessageBox.critical(self.defaultStyleWidget, "Open failed",
                        str(e), QMessageBox.Close)
            else:
                try:
                    with open(tablestring, 'rt') as f:
                        filestring = f.read()
                        if 'FH' == format:
                            self.transmitHex(filestring)
                        elif 'FA' == format:
                            self.transmitAsc(filestring)
                except IOError as e:
                    print("({})".format(e))
                    QMessageBox.critical(self.defaultStyleWidget, "Open failed",
                        str(e), QMessageBox.Close)

    def onSend(self):
        sendstring = self.txtEdtInput.toPlainText()
        self.transmitHex(sendstring)

    def transmitHex(self, hexstring):
        if len(hexstring) > 0:
            hexarray = []
            _hexstring = hexstring.replace(' ', '')
            _hexstring = _hexstring.replace('\r', '')
            _hexstring = _hexstring.replace('\n', '')
            for i in range(0, len(_hexstring), 2):
                word = _hexstring[i:i+2]
                if is_hex(word):
                    hexarray.append(int(word, 16))
                else:
                    QMessageBox.critical(self.defaultStyleWidget, "Error",
                        "'%s' is not hexadecimal." % (word), QMessageBox.Close)
                    return

            self.transmitBytearray(bytearray(hexarray))

    def transmitAsc(self, text):
        if len(text) > 0:
            byteArray = [ord(char) for char in text]
            self.transmitBytearray(bytearray(byteArray))

    def transmitBytearray(self, byteArray):
        if self.serialport.isOpen():
            try:
                self.serialport.write(byteArray)
            except Exception as e:
                QMessageBox.critical(self.defaultStyleWidget,
                    "Exception in transmit", str(e), QMessageBox.Close)
                print("Exception in transmitBytearray(%s)" % text)
            else:
                if self._viewMode == VIEWMODE_ASCII:
                    text = byteArray.decode('unicode_escape')
                elif self._viewMode == VIEWMODE_HEX_LOWERCASE:
                    text = ''.join('%02x ' % t for t in byteArray)
                elif self._viewMode == VIEWMODE_HEX_UPPERCASE:
                    text = ''.join('%02X ' % t for t in byteArray)
                self.appendOutputText("\n%s T->:%s" % (self.timestamp(), text), Qt.blue)

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

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

    def onReceive(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 getPort(self):
        return self.cmbPort.currentText()

    def getDataBits(self):
        return {'5':serial.FIVEBITS,
                '6':serial.SIXBITS,
                '7':serial.SEVENBITS, 
                '8':serial.EIGHTBITS}[self.cmbDataBits.currentText()]

    def getParity(self):
        return {'None' :serial.PARITY_NONE,
                'Even' :serial.PARITY_EVEN,
                'Odd'  :serial.PARITY_ODD,
                'Mark' :serial.PARITY_MARK,
                'Space':serial.PARITY_SPACE}[self.cmbParity.currentText()]

    def getStopBits(self):
        return {'1'  :serial.STOPBITS_ONE,
                '1.5':serial.STOPBITS_ONE_POINT_FIVE,
                '2'  :serial.STOPBITS_TWO}[self.cmbStopBits.currentText()]

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

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

        _baudrate = self.cmbBaudRate.currentText()
        if '' == _baudrate:
            QMessageBox.information(self.defaultStyleWidget, "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 Exception as e:
            QMessageBox.critical(self.defaultStyleWidget, 
                "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 (*.*)")[0]
        if fileName:
            import codecs
            with codecs.open(fileName, 'w', 'utf-8') as f:
                f.write(self.txtEdtOutput.toPlainText())

    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):
        self.cmbPort.clear()
        for p in enum_ports():
            self.cmbPort.addItem(p)

    def onAbout(self):
        QMessageBox.about(self.defaultStyleWidget, "About MyTerm", appInfo.aboutme)

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

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

    def restoreLayout(self):
        if os.path.isfile(get_config_path("UILayout.dat")):
            try:
                f=open(get_config_path("UILayout.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_qt5.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("UILayout.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._viewMode = VIEWMODE_HEX_UPPERCASE
            self.actionHEX_UPPERCASE.setChecked(True)
        else:
            if 'Ascii' in checked.text():
                self._viewMode = VIEWMODE_ASCII
            elif 'lowercase' in checked.text():
                self._viewMode = VIEWMODE_HEX_LOWERCASE
            elif 'UPPERCASE' in checked.text():
                self._viewMode = VIEWMODE_HEX_UPPERCASE

        self.receiver_thread.setViewMode(self._viewMode)
예제 #48
0
class AddSeqTool(AbstractPathTool):
    def __init__(self, controller, parent=None):
        AbstractPathTool.__init__(self, controller, parent)
        self.dialog = QDialog()
        self.buttons = []
        self.seqBox = None
        self.chosenStandardSequence = None  # state for tab switching
        self.customSequenceIsValid = False  # state for tab switching
        self.useCustomSequence = False  # for applying sequence
        self.validatedSequenceToApply = None
        self.initDialog()

    def __repr__(self):
        return "add_seq_tool"  # first letter should be lowercase

    def methodPrefix(self):
        return "addSeqTool"  # first letter should be lowercase

    def initDialog(self):
        """
        1. Create buttons according to available scaffold sequences and
        add them to the dialog.
        2. Map the clicked signal of those buttons to keep track of what
        sequence gets selected.
        3. Watch the tabWidget change signal to determine whether a
        standard or custom sequence should be applied.
        """
        uiDlg = Ui_AddSeqDialog()
        uiDlg.setupUi(self.dialog)
        self.signalMapper = QSignalMapper(self)
        # set up the radio buttons
        for i, name in enumerate(sorted(sequences.keys())):
            radioButton = QRadioButton(uiDlg.groupBox)
            radioButton.setObjectName(name + "Button")
            radioButton.setText(name)
            self.buttons.append(radioButton)
            uiDlg.verticalLayout.addWidget(radioButton)
            self.signalMapper.setMapping(radioButton, i)
            radioButton.clicked.connect(self.signalMapper.map)
        self.signalMapper.mapped.connect(self.standardSequenceChangedSlot)
        uiDlg.tabWidget.currentChanged.connect(self.tabWidgetChangedSlot)
        # disable apply until valid option or custom sequence is chosen
        self.applyButton = uiDlg.customButtonBox.button(QDialogButtonBox.Apply)
        self.applyButton.setEnabled(False)
        # watch sequence textedit box to validate custom sequences
        self.seqBox = uiDlg.seqTextEdit
        self.seqBox.textChanged.connect(self.validateCustomSequence)
        self.highlighter = DNAHighlighter(self.seqBox)
        # finally, pre-click the M13mp18 radio button
        self.buttons[0].click()
        buttons = self.buttons

        self.dialog.setFocusProxy(uiDlg.groupBox)
        self.dialog.setFocusPolicy(Qt.TabFocus)
        uiDlg.groupBox.setFocusPolicy(Qt.TabFocus)
        for i in range(len(buttons)-1):
            uiDlg.groupBox.setTabOrder(buttons[i], buttons[i+1])

    def tabWidgetChangedSlot(self, index):
        applyEnabled = False
        if index == 1:  # Custom Sequence
            self.validateCustomSequence()
            if self.customSequenceIsValid:
                applyEnabled = True
        else:  # Standard Sequence
            self.useCustomSequence = False
            if self.chosenStandardSequence != None:
                # Overwrite sequence in case custom has been applied
                activeButton = self.buttons[self.chosenStandardSequence]
                sequenceName = str(activeButton.text())
                self.validatedSequenceToApply = sequences.get(sequenceName, None)
                applyEnabled = True
        self.applyButton.setEnabled(applyEnabled)

    def standardSequenceChangedSlot(self, optionChosen):
        """
        Connected to signalMapper to receive a signal whenever user selects
        a different sequence in the standard tab.
        """
        sequenceName = str(self.buttons[optionChosen].text())
        self.validatedSequenceToApply = sequences.get(sequenceName, None)
        self.chosenStandardSequence = optionChosen
        self.applyButton.setEnabled(True)

    def validateCustomSequence(self):
        """
        Called when:
        1. User enters custom sequence (i.e. seqBox emits textChanged signal)
        2. tabWidgetChangedSlot sees the user has switched to custom tab.

        When the sequence is valid, make the applyButton active for clicking.
        Otherwise
        """
        userSequence = self.seqBox.toPlainText()
        if len(userSequence) == 0:
            self.customSequenceIsValid = False
            return  # tabWidgetChangedSlot will disable applyButton
        if dnapattern.indexIn(userSequence) == -1:  # no invalid characters
            self.useCustomSequence = True
            self.customSequenceIsValid = True
            self.applyButton.setEnabled(True)
        else:
            self.customSequenceIsValid = False
            self.applyButton.setEnabled(False)

    def applySequence(self, oligo):
        self.dialog.setFocus()
        if self.dialog.exec_():  # apply the sequence if accept was clicked
            if self.useCustomSequence:
                self.validatedSequenceToApply = str(self.seqBox.toPlainText().toUpper())
            oligo.applySequence(self.validatedSequenceToApply)
            return oligo.length(), len(self.validatedSequenceToApply)
        return (None, None)
예제 #49
0
class Panel(QDialog):
    # A list of two-sized tuples (QWidget's name, model field name).
    FIELDS = []
    # Name to use for serialization of persistent data about this panel (geometry).
    # XXX At the time of this writing (ticket #364), there's already a separate system in Cocoa
    # to persist dialog frames. A "clean" implementation would do like we do with the main window
    # and implement frame save/restore in core, but I fear that I'll needlessly complicate things
    # doing so, so for now, I limit myself to a qt-only solution. Later, we should re-evaluate
    # whether it could be a good idea to push this implementation to the core.
    PERSISTENT_NAME = None

    def __init__(self, mainwindow):
        # The flags we pass are that so we don't get the "What's this" button in the title bar
        QDialog.__init__(self, mainwindow, Qt.WindowTitleHint | Qt.WindowSystemMenuHint)
        self._widget2ModelAttr = {}
        self.mainwindow = mainwindow

    def _changeComboBoxItems(self, comboBox, newItems):
        # When a combo box's items are changed, its currentIndex changed with a currentIndexChanged
        # signal, and if that signal results in the model being updated, it messes the model.
        # We thus have to disconnect the combo box's signal before changing the items.
        if comboBox in self._widget2ModelAttr:
            comboBox.currentIndexChanged.disconnect(self.comboBoxCurrentIndexChanged)
        index = comboBox.currentIndex()
        comboBox.clear()
        comboBox.addItems(newItems)
        comboBox.setCurrentIndex(index)
        if comboBox in self._widget2ModelAttr:
            comboBox.currentIndexChanged.connect(self.comboBoxCurrentIndexChanged)

    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)

    def _loadFields(self):
        for widgetName, modelAttr in self.FIELDS:
            widget = getattr(self, widgetName)
            value = getattr(self.model, modelAttr)
            if isinstance(widget, QComboBox):
                widget.setCurrentIndex(value)
            elif isinstance(widget, QSpinBox):
                widget.setValue(value)
            elif isinstance(widget, QLineEdit):
                widget.setText(value)
            elif isinstance(widget, QPlainTextEdit):
                widget.setPlainText(value)
            elif isinstance(widget, QCheckBox):
                widget.setChecked(value)

    def _saveFields(self):
        pass

    def _loadGeometry(self):
        if self.PERSISTENT_NAME:
            self.mainwindow.app.prefs.restoreGeometry('%sGeometry' % self.PERSISTENT_NAME, self)

    def _saveGeometry(self):
        if self.PERSISTENT_NAME:
            self.mainwindow.app.prefs.saveGeometry('%sGeometry' % self.PERSISTENT_NAME, self)

    def accept(self):
        # The setFocus() call is to force the last edited field to "commit". When the save button
        # is clicked, accept() is called before the last field to have focus has a chance to emit
        # its edition signal.
        self.setFocus()
        self.model.save()
        self._saveGeometry()
        QDialog.accept(self)

    def reject(self):
        self._saveGeometry()
        super().reject()

    #--- Event Handlers
    def widgetChanged(self, sender):
        modelAttr = self._widget2ModelAttr[sender]
        if isinstance(sender, QComboBox):
            newvalue = sender.currentIndex()
        elif isinstance(sender, QSpinBox):
            newvalue = sender.value()
        elif isinstance(sender, QLineEdit):
            newvalue = sender.text()
        elif isinstance(sender, QPlainTextEdit):
            newvalue = sender.toPlainText()
        elif isinstance(sender, QCheckBox):
            newvalue = sender.isChecked()
        setattr(self.model, modelAttr, newvalue)

    #--- model --> view
    def pre_load(self):
        self._loadGeometry()

    def pre_save(self):
        self._saveFields()

    def post_load(self):
        if not self._widget2ModelAttr: # signal not connected yet
            self._connectSignals()
        self._loadFields()
        self.show()
        # For initial text edits to have their text selected, we *have to* first select the dialog,
        # then setFocus on it with qt.TabFocusReason. Don't ask, I don't know why either...
        self.setFocus()
        focus = self.nextInFocusChain()
        while focus.focusPolicy() == Qt.NoFocus:
            focus = focus.nextInFocusChain()
        focus.setFocus(Qt.TabFocusReason)
예제 #50
0
class MainWindow(QMainWindow, Ui_MainWindow):
    dictChanged = pyqtSignal(str)

    # Tab indexes
    TabInfos = 0
    TabSummary = 1
    TabPersos = 2
    TabPlots = 3
    TabWorld = 4
    TabOutline = 5
    TabRedac = 6

    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)
        self.currentProject = None

        self.readSettings()

        # UI
        self.setupMoreUi()

        # Welcome
        self.welcome.updateValues()
        # self.welcome.btnCreate.clicked.connect
        self.stack.setCurrentIndex(0)

        # Word count
        self.mprWordCount = QSignalMapper(self)
        for t, i in [
            (self.txtSummarySentence, 0),
            (self.txtSummaryPara, 1),
            (self.txtSummaryPage, 2),
            (self.txtSummaryFull, 3)
        ]:
            t.textChanged.connect(self.mprWordCount.map)
            self.mprWordCount.setMapping(t, i)
        self.mprWordCount.mapped.connect(self.wordCount)

        # Snowflake Method Cycle
        self.mapperCycle = QSignalMapper(self)
        for t, i in [
            (self.btnStepTwo, 0),
            (self.btnStepThree, 1),
            (self.btnStepFour, 2),
            (self.btnStepFive, 3),
            (self.btnStepSix, 4),
            (self.btnStepSeven, 5),
            (self.btnStepEight, 6)
        ]:
            t.clicked.connect(self.mapperCycle.map)
            self.mapperCycle.setMapping(t, i)

        self.mapperCycle.mapped.connect(self.clickCycle)
        self.cmbSummary.currentIndexChanged.connect(self.summaryPageChanged)
        self.cmbSummary.setCurrentIndex(0)
        self.cmbSummary.currentIndexChanged.emit(0)

        # Main Menu
        for i in [self.actSave, self.actSaveAs, self.actCloseProject,
                  self.menuEdit, self.menuMode, self.menuView, self.menuTools,
                  self.menuHelp]:
            i.setEnabled(False)

        self.actOpen.triggered.connect(self.welcome.openFile)
        self.actSave.triggered.connect(self.saveDatas)
        self.actSaveAs.triggered.connect(self.welcome.saveAsFile)
        self.actCompile.triggered.connect(self.doCompile)
        self.actLabels.triggered.connect(self.settingsLabel)
        self.actStatus.triggered.connect(self.settingsStatus)
        self.actSettings.triggered.connect(self.settingsWindow)
        self.actCloseProject.triggered.connect(self.closeProject)
        self.actQuit.triggered.connect(self.close)
        self.actToolFrequency.triggered.connect(self.frequencyAnalyzer)
        self.generateViewMenu()

        self.makeUIConnections()

        # self.loadProject(os.path.join(appPath(), "test_project.zip"))

    ###############################################################################
    # SUMMARY
    ###############################################################################

    def summaryPageChanged(self, index):
        fractalButtons = [
            self.btnStepTwo,
            self.btnStepThree,
            self.btnStepFive,
            self.btnStepSeven,
        ]
        for b in fractalButtons:
            b.setVisible(fractalButtons.index(b) == index)

    ###############################################################################
    # OUTLINE
    ###############################################################################

    def outlineRemoveItemsRedac(self):
        self.treeRedacOutline.delete()

    def outlineRemoveItemsOutline(self):
        self.treeOutlineOutline.delete()

    ###############################################################################
    # PERSOS
    ###############################################################################

    def changeCurrentPerso(self, trash=None):

        index = self.lstPersos.currentPersoIndex()

        if not index.isValid():
            self.tabPlot.setEnabled(False)
            return

        self.tabPersos.setEnabled(True)

        for w in [
            self.txtPersoName,
            self.sldPersoImportance,
            self.txtPersoMotivation,
            self.txtPersoGoal,
            self.txtPersoConflict,
            self.txtPersoEpiphany,
            self.txtPersoSummarySentence,
            self.txtPersoSummaryPara,
            self.txtPersoSummaryFull,
            self.txtPersoNotes,
        ]:
            w.setCurrentModelIndex(index)

        # Button color
        self.mdlPersos.updatePersoColor(index)

        # Perso Infos
        self.tblPersoInfos.setRootIndex(index)

        if self.mdlPersos.rowCount(index):
            self.updatePersoInfoView()

    def updatePersoInfoView(self):
        # Hide columns
        for i in range(self.mdlPersos.columnCount()):
            self.tblPersoInfos.hideColumn(i)
        self.tblPersoInfos.showColumn(Perso.infoName.value)
        self.tblPersoInfos.showColumn(Perso.infoData.value)

        self.tblPersoInfos.horizontalHeader().setSectionResizeMode(
                Perso.infoName.value, QHeaderView.ResizeToContents)
        self.tblPersoInfos.horizontalHeader().setSectionResizeMode(
                Perso.infoData.value, QHeaderView.Stretch)
        self.tblPersoInfos.verticalHeader().hide()

    ###############################################################################
    # PLOTS
    ###############################################################################

    def changeCurrentPlot(self):
        index = self.lstPlots.currentPlotIndex()

        if not index.isValid():
            self.tabPlot.setEnabled(False)
            return

        self.tabPlot.setEnabled(True)
        self.txtPlotName.setCurrentModelIndex(index)
        self.txtPlotDescription.setCurrentModelIndex(index)
        self.txtPlotResult.setCurrentModelIndex(index)
        self.sldPlotImportance.setCurrentModelIndex(index)
        self.lstPlotPerso.setRootIndex(index.sibling(index.row(),
                                                     Plot.persos.value))
        subplotindex = index.sibling(index.row(), Plot.subplots.value)
        self.lstSubPlots.setRootIndex(subplotindex)
        if self.mdlPlots.rowCount(subplotindex):
            self.updateSubPlotView()

        # self.txtSubPlotSummary.setCurrentModelIndex(QModelIndex())
        self.txtSubPlotSummary.setEnabled(False)
        self._updatingSubPlot = True
        self.txtSubPlotSummary.setPlainText("")
        self._updatingSubPlot = False
        self.lstPlotPerso.selectionModel().clear()

    def updateSubPlotView(self):
        # Hide columns
        for i in range(self.mdlPlots.columnCount()):
            self.lstSubPlots.hideColumn(i)
        self.lstSubPlots.showColumn(Subplot.name.value)
        self.lstSubPlots.showColumn(Subplot.meta.value)

        self.lstSubPlots.horizontalHeader().setSectionResizeMode(
                Subplot.name.value, QHeaderView.Stretch)
        self.lstSubPlots.horizontalHeader().setSectionResizeMode(
                Subplot.meta.value, QHeaderView.ResizeToContents)
        self.lstSubPlots.verticalHeader().hide()

    def changeCurrentSubPlot(self, index):
        # Got segfaults when using textEditView model system, so ad hoc stuff.
        index = index.sibling(index.row(), Subplot.summary.value)
        item = self.mdlPlots.itemFromIndex(index)
        if not item:
            self.txtSubPlotSummary.setEnabled(False)
            return
        self.txtSubPlotSummary.setEnabled(True)
        txt = item.text()
        self._updatingSubPlot = True
        self.txtSubPlotSummary.setPlainText(txt)
        self._updatingSubPlot = False

    def updateSubPlotSummary(self):
        if self._updatingSubPlot:
            return

        index = self.lstSubPlots.currentIndex()
        if not index.isValid():
            return
        index = index.sibling(index.row(), Subplot.summary.value)
        item = self.mdlPlots.itemFromIndex(index)

        self._updatingSubPlot = True
        item.setText(self.txtSubPlotSummary.toPlainText())
        self._updatingSubPlot = False

    def plotPersoSelectionChanged(self):
        "Enables or disables remove plot perso button."
        self.btnRmPlotPerso.setEnabled(
                len(self.lstPlotPerso.selectedIndexes()) != 0)

    ###############################################################################
    # WORLD
    ###############################################################################

    def changeCurrentWorld(self):
        index = self.mdlWorld.selectedIndex()

        if not index.isValid():
            self.tabWorld.setEnabled(False)
            return

        self.tabWorld.setEnabled(True)
        self.txtWorldName.setCurrentModelIndex(index)
        self.txtWorldDescription.setCurrentModelIndex(index)
        self.txtWorldPassion.setCurrentModelIndex(index)
        self.txtWorldConflict.setCurrentModelIndex(index)

    ###############################################################################
    # LOAD AND SAVE
    ###############################################################################

    def loadProject(self, project, loadFromFile=True):
        """Loads the project ``project``.

        If ``loadFromFile`` is False, then it does not load datas from file.
        It assumes that the datas have been populated in a different way."""
        if loadFromFile and not os.path.exists(project):
            print(self.tr("The file {} does not exist. Try again.").format(project))
            self.statusBar().showMessage(
                    self.tr("The file {} does not exist. Try again.").format(project),
                    5000)
            return

        if loadFromFile:
            # Load empty settings
            imp.reload(settings)

            # Load data
            self.loadEmptyDatas()
            self.loadDatas(project)

        self.makeConnections()

        # Load settings
        for i in settings.openIndexes:
            idx = self.mdlOutline.indexFromPath(i)
            self.mainEditor.setCurrentModelIndex(idx, newTab=True)
        self.generateViewMenu()
        self.mainEditor.sldCorkSizeFactor.setValue(settings.corkSizeFactor)
        self.actSpellcheck.setChecked(settings.spellcheck)
        self.toggleSpellcheck(settings.spellcheck)
        self.updateMenuDict()
        self.setDictionary()

        self.mainEditor.setFolderView(settings.folderView)
        self.mainEditor.updateFolderViewButtons(settings.folderView)
        self.tabMain.setCurrentIndex(settings.lastTab)
        # We force to emit even if it opens on the current tab
        self.tabMain.currentChanged.emit(settings.lastTab)
        self.mainEditor.updateCorkBackground()

        # Set autosave
        self.saveTimer = QTimer()
        self.saveTimer.setInterval(settings.autoSaveDelay * 60 * 1000)
        self.saveTimer.setSingleShot(False)
        self.saveTimer.timeout.connect(self.saveDatas)
        if settings.autoSave:
            self.saveTimer.start()

        # Set autosave if no changes
        self.saveTimerNoChanges = QTimer()
        self.saveTimerNoChanges.setInterval(settings.autoSaveNoChangesDelay * 1000)
        self.saveTimerNoChanges.setSingleShot(True)
        self.mdlFlatData.dataChanged.connect(self.startTimerNoChanges)
        self.mdlOutline.dataChanged.connect(self.startTimerNoChanges)
        self.mdlPersos.dataChanged.connect(self.startTimerNoChanges)
        self.mdlPlots.dataChanged.connect(self.startTimerNoChanges)
        self.mdlWorld.dataChanged.connect(self.startTimerNoChanges)
        # self.mdlPersosInfos.dataChanged.connect(self.startTimerNoChanges)
        self.mdlStatus.dataChanged.connect(self.startTimerNoChanges)
        self.mdlLabels.dataChanged.connect(self.startTimerNoChanges)

        self.saveTimerNoChanges.timeout.connect(self.saveDatas)
        self.saveTimerNoChanges.stop()

        # UI
        for i in [self.actSave, self.actSaveAs, self.actCloseProject,
                  self.menuEdit, self.menuMode, self.menuView, self.menuTools,
                  self.menuHelp]:
            i.setEnabled(True)
        # FIXME: set Window's name: project name

        # Stuff
        # self.checkPersosID()  # Should'n be necessary any longer

        self.currentProject = project
        QSettings().setValue("lastProject", project)

        # Show main Window
        self.stack.setCurrentIndex(1)

    def closeProject(self):
        # Save datas
        self.saveDatas()

        self.currentProject = None
        QSettings().setValue("lastProject", "")

        # FIXME: close all opened tabs in mainEditor

        # Clear datas
        self.loadEmptyDatas()

        self.saveTimer.stop()

        # UI
        for i in [self.actSave, self.actSaveAs, self.actCloseProject,
                  self.menuEdit, self.menuMode, self.menuView, self.menuTools,
                  self.menuHelp]:
            i.setEnabled(False)

        # Reload recent files
        self.welcome.updateValues()

        # Show welcome dialog
        self.stack.setCurrentIndex(0)

    def readSettings(self):
        # Load State and geometry
        sttgns = QSettings(qApp.organizationName(), qApp.applicationName())
        if sttgns.contains("geometry"):
            self.restoreGeometry(sttgns.value("geometry"))
        if sttgns.contains("windowState"):
            self.restoreState(sttgns.value("windowState"))
        else:
            self.dckCheatSheet.hide()
            self.dckSearch.hide()
        if sttgns.contains("metadataState"):
            state = [False if v == "false" else True for v in sttgns.value("metadataState")]
            self.redacMetadata.restoreState(state)
        if sttgns.contains("revisionsState"):
            state = [False if v == "false" else True for v in sttgns.value("revisionsState")]
            self.redacMetadata.revisions.restoreState(state)
        if sttgns.contains("splitterRedacH"):
            self.splitterRedacH.restoreState(sttgns.value("splitterRedacH"))
        if sttgns.contains("splitterRedacV"):
            self.splitterRedacV.restoreState(sttgns.value("splitterRedacV"))
        if sttgns.contains("toolbar"):
            # self.toolbar is not initialized yet, so we just store balue
            self._toolbarState = sttgns.value("toolbar")
        else:
            self._toolbarState = ""


    def closeEvent(self, event):
        # Save State and geometry and other things
        sttgns = QSettings(qApp.organizationName(), qApp.applicationName())
        sttgns.setValue("geometry", self.saveGeometry())
        sttgns.setValue("windowState", self.saveState())
        sttgns.setValue("metadataState", self.redacMetadata.saveState())
        sttgns.setValue("revisionsState", self.redacMetadata.revisions.saveState())
        sttgns.setValue("splitterRedacH", self.splitterRedacH.saveState())
        sttgns.setValue("splitterRedacV", self.splitterRedacV.saveState())
        sttgns.setValue("toolbar", self.toolbar.saveState())

        # Specific settings to save before quitting
        settings.lastTab = self.tabMain.currentIndex()

        if self.currentProject:
            # Remembering the current items
            sel = []
            for i in range(self.mainEditor.tab.count()):
                sel.append(self.mdlOutline.pathToIndex(self.mainEditor.tab.widget(i).currentIndex))
            settings.openIndexes = sel

        # Save data from models
        if self.currentProject and settings.saveOnQuit:
            self.saveDatas()

            # closeEvent
            # QMainWindow.closeEvent(self, event)  # Causin segfaults?

    def startTimerNoChanges(self):
        if settings.autoSaveNoChanges:
            self.saveTimerNoChanges.start()

    def saveDatas(self, projectName=None):
        """Saves the current project (in self.currentProject).

        If ``projectName`` is given, currentProject becomes projectName.
        In other words, it "saves as...".
        """

        if projectName:
            self.currentProject = projectName
            QSettings().setValue("lastProject", projectName)

        # Saving
        files = []

        files.append((saveStandardItemModelXML(self.mdlFlatData),
                      "flatModel.xml"))
        files.append((saveStandardItemModelXML(self.mdlPersos),
                      "perso.xml"))
        files.append((saveStandardItemModelXML(self.mdlWorld),
                      "world.xml"))
        files.append((saveStandardItemModelXML(self.mdlLabels),
                      "labels.xml"))
        files.append((saveStandardItemModelXML(self.mdlStatus),
                      "status.xml"))
        files.append((saveStandardItemModelXML(self.mdlPlots),
                      "plots.xml"))
        files.append((self.mdlOutline.saveToXML(),
                      "outline.xml"))
        files.append((settings.save(),
                      "settings.pickle"))

        saveFilesToZip(files, self.currentProject)

        # Giving some feedback
        print(self.tr("Project {} saved.").format(self.currentProject))
        self.statusBar().showMessage(
                self.tr("Project {} saved.").format(self.currentProject), 5000)

    def loadEmptyDatas(self):
        self.mdlFlatData = QStandardItemModel(self)
        self.mdlPersos = persosModel(self)
        # self.mdlPersosProxy = persosProxyModel(self)
        # self.mdlPersosInfos = QStandardItemModel(self)
        self.mdlLabels = QStandardItemModel(self)
        self.mdlStatus = QStandardItemModel(self)
        self.mdlPlots = plotModel(self)
        self.mdlOutline = outlineModel(self)
        self.mdlWorld = worldModel(self)

    def loadDatas(self, project):
        # Loading
        files = loadFilesFromZip(project)

        errors = []

        if "flatModel.xml" in files:
            loadStandardItemModelXML(self.mdlFlatData,
                                     files["flatModel.xml"], fromString=True)
        else:
            errors.append("flatModel.xml")

        if "perso.xml" in files:
            loadStandardItemModelXML(self.mdlPersos,
                                     files["perso.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "world.xml" in files:
            loadStandardItemModelXML(self.mdlWorld,
                                     files["world.xml"], fromString=True)
        else:
            errors.append("world.xml")

        if "labels.xml" in files:
            loadStandardItemModelXML(self.mdlLabels,
                                     files["labels.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "status.xml" in files:
            loadStandardItemModelXML(self.mdlStatus,
                                     files["status.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "plots.xml" in files:
            loadStandardItemModelXML(self.mdlPlots,
                                     files["plots.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "outline.xml" in files:
            self.mdlOutline.loadFromXML(files["outline.xml"], fromString=True)
        else:
            errors.append("perso.xml")

        if "settings.pickle" in files:
            settings.load(files["settings.pickle"], fromString=True)
        else:
            errors.append("perso.xml")

        # Giving some feedback
        if not errors:
            print(self.tr("Project {} loaded.").format(project))
            self.statusBar().showMessage(
                    self.tr("Project {} loaded.").format(project), 5000)
        else:
            print(self.tr("Project {} loaded with some errors:").format(project))
            for e in errors:
                print(self.tr(" * {} wasn't found in project file.").format(e))
            self.statusBar().showMessage(
                    self.tr("Project {} loaded with some errors.").format(project), 5000)

    ###############################################################################
    # MAIN CONNECTIONS
    ###############################################################################

    def makeUIConnections(self):
        "Connections that have to be made once only, event when new project is loaded."
        self.lstPersos.currentItemChanged.connect(self.changeCurrentPerso, AUC)

        self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter, AUC)
        self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot, AUC)
        self.txtSubPlotSummary.document().contentsChanged.connect(
                self.updateSubPlotSummary, AUC)
        self.lstSubPlots.activated.connect(self.changeCurrentSubPlot, AUC)

        self.btnRedacAddFolder.clicked.connect(self.treeRedacOutline.addFolder, AUC)
        self.btnOutlineAddFolder.clicked.connect(self.treeOutlineOutline.addFolder, AUC)
        self.btnRedacAddText.clicked.connect(self.treeRedacOutline.addText, AUC)
        self.btnOutlineAddText.clicked.connect(self.treeOutlineOutline.addText, AUC)
        self.btnRedacRemoveItem.clicked.connect(self.outlineRemoveItemsRedac, AUC)
        self.btnOutlineRemoveItem.clicked.connect(self.outlineRemoveItemsOutline, AUC)

        self.tabMain.currentChanged.connect(self.toolbar.setCurrentGroup)

    def makeConnections(self):

        # Flat datas (Summary and general infos)
        for widget, col in [
            (self.txtSummarySituation, 0),
            (self.txtSummarySentence, 1),
            (self.txtSummarySentence_2, 1),
            (self.txtSummaryPara, 2),
            (self.txtSummaryPara_2, 2),
            (self.txtPlotSummaryPara, 2),
            (self.txtSummaryPage, 3),
            (self.txtSummaryPage_2, 3),
            (self.txtPlotSummaryPage, 3),
            (self.txtSummaryFull, 4),
            (self.txtPlotSummaryFull, 4),
        ]:
            widget.setModel(self.mdlFlatData)
            widget.setColumn(col)
            widget.setCurrentModelIndex(self.mdlFlatData.index(1, col))

        for widget, col in [
            (self.txtGeneralTitle, 0),
            (self.txtGeneralSubtitle, 1),
            (self.txtGeneralSerie, 2),
            (self.txtGeneralVolume, 3),
            (self.txtGeneralGenre, 4),
            (self.txtGeneralLicense, 5),
            (self.txtGeneralAuthor, 6),
            (self.txtGeneralEmail, 7),
        ]:
            widget.setModel(self.mdlFlatData)
            widget.setColumn(col)
            widget.setCurrentModelIndex(self.mdlFlatData.index(0, col))

        # Persos
        self.lstPersos.setPersosModel(self.mdlPersos)
        self.tblPersoInfos.setModel(self.mdlPersos)

        self.btnAddPerso.clicked.connect(self.mdlPersos.addPerso, AUC)
        self.btnRmPerso.clicked.connect(self.mdlPersos.removePerso, AUC)
        self.btnPersoColor.clicked.connect(self.mdlPersos.chosePersoColor, AUC)

        self.btnPersoAddInfo.clicked.connect(self.mdlPersos.addPersoInfo, AUC)
        self.btnPersoRmInfo.clicked.connect(self.mdlPersos.removePersoInfo, AUC)

        for w, c in [
            (self.txtPersoName, Perso.name.value),
            (self.sldPersoImportance, Perso.importance.value),
            (self.txtPersoMotivation, Perso.motivation.value),
            (self.txtPersoGoal, Perso.goal.value),
            (self.txtPersoConflict, Perso.conflict.value),
            (self.txtPersoEpiphany, Perso.epiphany.value),
            (self.txtPersoSummarySentence, Perso.summarySentence.value),
            (self.txtPersoSummaryPara, Perso.summaryPara.value),
            (self.txtPersoSummaryFull, Perso.summaryFull.value),
            (self.txtPersoNotes, Perso.notes.value)
        ]:
            w.setModel(self.mdlPersos)
            w.setColumn(c)
        self.tabPersos.setEnabled(False)

        # Plots
        self.lstPlots.setPlotModel(self.mdlPlots)
        self.lstPlotPerso.setModel(self.mdlPlots)
        self.lstSubPlots.setModel(self.mdlPlots)
        self._updatingSubPlot = False
        self.btnAddPlot.clicked.connect(self.mdlPlots.addPlot, AUC)
        self.btnRmPlot.clicked.connect(lambda:
                                       self.mdlPlots.removePlot(self.lstPlots.currentPlotIndex()), AUC)
        self.btnAddSubPlot.clicked.connect(self.mdlPlots.addSubPlot, AUC)
        self.btnRmSubPlot.clicked.connect(self.mdlPlots.removeSubPlot, AUC)
        self.lstPlotPerso.selectionModel().selectionChanged.connect(self.plotPersoSelectionChanged)
        self.btnRmPlotPerso.clicked.connect(self.mdlPlots.removePlotPerso, AUC)

        for w, c in [
            (self.txtPlotName, Plot.name.value),
            (self.txtPlotDescription, Plot.description.value),
            (self.txtPlotResult, Plot.result.value),
            (self.sldPlotImportance, Plot.importance.value),
        ]:
            w.setModel(self.mdlPlots)
            w.setColumn(c)

        self.tabPlot.setEnabled(False)
        self.mdlPlots.updatePlotPersoButton()
        self.mdlPersos.dataChanged.connect(self.mdlPlots.updatePlotPersoButton)
        self.lstOutlinePlots.setPlotModel(self.mdlPlots)
        self.lstOutlinePlots.setShowSubPlot(True)
        self.plotPersoDelegate = outlinePersoDelegate(self.mdlPersos, self)
        self.lstPlotPerso.setItemDelegate(self.plotPersoDelegate)
        self.plotDelegate = plotDelegate(self)
        self.lstSubPlots.setItemDelegateForColumn(Subplot.meta.value, self.plotDelegate)

        # World
        self.treeWorld.setModel(self.mdlWorld)
        for i in range(self.mdlWorld.columnCount()):
            self.treeWorld.hideColumn(i)
        self.treeWorld.showColumn(0)
        self.btnWorldEmptyData.setMenu(self.mdlWorld.emptyDataMenu())
        self.treeWorld.selectionModel().selectionChanged.connect(self.changeCurrentWorld, AUC)
        self.btnAddWorld.clicked.connect(self.mdlWorld.addItem, AUC)
        self.btnRmWorld.clicked.connect(self.mdlWorld.removeItem, AUC)
        for w, c in [
            (self.txtWorldName, World.name.value),
            (self.txtWorldDescription, World.description.value),
            (self.txtWorldPassion, World.passion.value),
            (self.txtWorldConflict, World.conflict.value),
        ]:
            w.setModel(self.mdlWorld)
            w.setColumn(c)
        self.tabWorld.setEnabled(False)
        self.treeWorld.expandAll()

        # Outline
        self.treeRedacOutline.setModel(self.mdlOutline)
        self.treeOutlineOutline.setModelPersos(self.mdlPersos)
        self.treeOutlineOutline.setModelLabels(self.mdlLabels)
        self.treeOutlineOutline.setModelStatus(self.mdlStatus)

        self.redacMetadata.setModels(self.mdlOutline, self.mdlPersos,
                                     self.mdlLabels, self.mdlStatus)
        self.outlineItemEditor.setModels(self.mdlOutline, self.mdlPersos,
                                         self.mdlLabels, self.mdlStatus)

        self.treeOutlineOutline.setModel(self.mdlOutline)
        # self.redacEditor.setModel(self.mdlOutline)
        self.storylineView.setModels(self.mdlOutline, self.mdlPersos, self.mdlPlots)

        self.treeOutlineOutline.selectionModel().selectionChanged.connect(lambda:
                                                                          self.outlineItemEditor.selectionChanged(
                                                                                  self.treeOutlineOutline), AUC)
        self.treeOutlineOutline.clicked.connect(lambda:
                                                self.outlineItemEditor.selectionChanged(self.treeOutlineOutline), AUC)

        # Sync selection
        self.treeRedacOutline.selectionModel().selectionChanged.connect(
                lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline), AUC)
        self.treeRedacOutline.clicked.connect(
                lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline), AUC)

        self.treeRedacOutline.selectionModel().selectionChanged.connect(self.mainEditor.selectionChanged, AUC)

        # Cheat Sheet
        self.cheatSheet.setModels()

        # Debug
        self.mdlFlatData.setVerticalHeaderLabels(["Infos générales", "Summary"])
        self.tblDebugFlatData.setModel(self.mdlFlatData)
        self.tblDebugPersos.setModel(self.mdlPersos)
        self.tblDebugPersosInfos.setModel(self.mdlPersos)
        self.tblDebugPersos.selectionModel().currentChanged.connect(
                lambda: self.tblDebugPersosInfos.setRootIndex(self.mdlPersos.index(
                        self.tblDebugPersos.selectionModel().currentIndex().row(),
                        Perso.name.value)), AUC)

        self.tblDebugPlots.setModel(self.mdlPlots)
        self.tblDebugPlotsPersos.setModel(self.mdlPlots)
        self.tblDebugSubPlots.setModel(self.mdlPlots)
        self.tblDebugPlots.selectionModel().currentChanged.connect(
                lambda: self.tblDebugPlotsPersos.setRootIndex(self.mdlPlots.index(
                        self.tblDebugPlots.selectionModel().currentIndex().row(),
                        Plot.persos.value)), AUC)
        self.tblDebugPlots.selectionModel().currentChanged.connect(
                lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index(
                        self.tblDebugPlots.selectionModel().currentIndex().row(),
                        Plot.subplots.value)), AUC)
        self.treeDebugWorld.setModel(self.mdlWorld)
        self.treeDebugOutline.setModel(self.mdlOutline)
        self.lstDebugLabels.setModel(self.mdlLabels)
        self.lstDebugStatus.setModel(self.mdlStatus)

    ###############################################################################
    # GENERAL AKA UNSORTED
    ###############################################################################

    def clickCycle(self, i):
        if i == 0:  # step 2 - paragraph summary
            self.tabMain.setCurrentIndex(self.TabSummary)
            self.tabSummary.setCurrentIndex(1)
        if i == 1:  # step 3 - characters summary
            self.tabMain.setCurrentIndex(self.TabPersos)
            self.tabPersos.setCurrentIndex(0)
        if i == 2:  # step 4 - page summary
            self.tabMain.setCurrentIndex(self.TabSummary)
            self.tabSummary.setCurrentIndex(2)
        if i == 3:  # step 5 - characters description
            self.tabMain.setCurrentIndex(self.TabPersos)
            self.tabPersos.setCurrentIndex(1)
        if i == 4:  # step 6 - four page synopsis
            self.tabMain.setCurrentIndex(self.TabSummary)
            self.tabSummary.setCurrentIndex(3)
        if i == 5:  # step 7 - full character charts
            self.tabMain.setCurrentIndex(self.TabPersos)
            self.tabPersos.setCurrentIndex(2)
        if i == 6:  # step 8 - scene list
            self.tabMain.setCurrentIndex(self.TabPlots)

    def wordCount(self, i):

        src = {
            0: self.txtSummarySentence,
            1: self.txtSummaryPara,
            2: self.txtSummaryPage,
            3: self.txtSummaryFull
        }[i]

        lbl = {
            0: self.lblSummaryWCSentence,
            1: self.lblSummaryWCPara,
            2: self.lblSummaryWCPage,
            3: self.lblSummaryWCFull
        }[i]

        wc = wordCount(src.toPlainText())
        if i in [2, 3]:
            pages = self.tr(" (~{} pages)").format(int(wc / 25) / 10.)
        else:
            pages = ""
        lbl.setText(self.tr("Words: {}{}").format(wc, pages))

    def setupMoreUi(self):

        # Tool bar on the right
        self.toolbar = collapsibleDockWidgets(Qt.RightDockWidgetArea, self)
        self.toolbar.addCustomWidget(self.tr("Book summary"), self.grpPlotSummary, self.TabPlots)
        self.toolbar.addCustomWidget(self.tr("Project tree"), self.treeRedacWidget, self.TabRedac)
        self.toolbar.addCustomWidget(self.tr("Metadata"), self.redacMetadata, self.TabRedac)
        self.toolbar.addCustomWidget(self.tr("Story line"), self.storylineView, self.TabRedac)
        if self._toolbarState:
            self.toolbar.restoreState(self._toolbarState)

        # Custom "tab" bar on the left
        self.lstTabs.setIconSize(QSize(48, 48))
        for i in range(self.tabMain.count()):
            icons = ["general-128px.png",
                     "summary-128px.png",
                     "characters-128px.png",
                     "plot-128px.png",
                     "world-128px.png",
                     "outline-128px.png",
                     "redaction-128px.png",
                     ""
                     ]
            self.tabMain.setTabIcon(i, QIcon(appPath("icons/Custom/Tabs/{}".format(icons[i]))))
            item = QListWidgetItem(self.tabMain.tabIcon(i),
                                   self.tabMain.tabText(i))
            item.setSizeHint(QSize(item.sizeHint().width(), 64))
            item.setTextAlignment(Qt.AlignCenter)
            self.lstTabs.addItem(item)
        self.tabMain.tabBar().hide()
        self.lstTabs.currentRowChanged.connect(self.tabMain.setCurrentIndex)
        self.tabMain.currentChanged.connect(self.lstTabs.setCurrentRow)

        # Splitters
        self.splitterPersos.setStretchFactor(0, 25)
        self.splitterPersos.setStretchFactor(1, 75)

        self.splitterPlot.setStretchFactor(0, 20)
        self.splitterPlot.setStretchFactor(1, 60)
        self.splitterPlot.setStretchFactor(2, 30)

        self.splitterWorld.setStretchFactor(0, 25)
        self.splitterWorld.setStretchFactor(1, 75)

        self.splitterOutlineH.setStretchFactor(0, 25)
        self.splitterOutlineH.setStretchFactor(1, 75)
        self.splitterOutlineV.setStretchFactor(0, 75)
        self.splitterOutlineV.setStretchFactor(1, 25)

        self.splitterRedacV.setStretchFactor(0, 75)
        self.splitterRedacV.setStretchFactor(1, 25)

        self.splitterRedacH.setStretchFactor(0, 30)
        self.splitterRedacH.setStretchFactor(1, 40)
        self.splitterRedacH.setStretchFactor(2, 30)

        # QFormLayout stretch
        for w in [self.txtWorldDescription, self.txtWorldPassion, self.txtWorldConflict]:
            s = w.sizePolicy()
            s.setVerticalStretch(1)
            w.setSizePolicy(s)

        # Help box
        references = [
            (self.lytTabOverview,
             self.tr("Enter infos about your book, and yourself."),
             0),
            (self.lytSituation,
             self.tr(
                     """The basic situation, in the form of a 'What if...?' question. Ex: 'What if the most dangerous
                     evil wizard could wasn't abled to kill a baby?' (Harry Potter)"""),
             1),
            (self.lytSummary,
             self.tr(
                     """Take time to think about a one sentence (~50 words) summary of your book. Then expand it to
                     a paragraph, then to a page, then to a full summary."""),
             1),
            (self.lytTabPersos,
             self.tr("Create your characters."),
             0),
            (self.lytTabPlot,
             self.tr("Develop plots."),
             0),
            (self.lytTabOutline,
             self.tr("Create the outline of your masterpiece."),
             0),
            (self.lytTabRedac,
             self.tr("Write."),
             0),
            (self.lytTabDebug,
             self.tr("Debug infos. Sometimes useful."),
             0)
        ]

        for widget, text, pos in references:
            label = helpLabel(text, self)
            self.actShowHelp.toggled.connect(label.setVisible, AUC)
            widget.layout().insertWidget(pos, label)

        self.actShowHelp.setChecked(False)

        # Spellcheck
        if enchant:
            self.menuDict = QMenu(self.tr("Dictionary"))
            self.menuDictGroup = QActionGroup(self)
            self.updateMenuDict()
            self.menuTools.addMenu(self.menuDict)

            self.actSpellcheck.toggled.connect(self.toggleSpellcheck, AUC)
            self.dictChanged.connect(self.mainEditor.setDict, AUC)
            self.dictChanged.connect(self.redacMetadata.setDict, AUC)
            self.dictChanged.connect(self.outlineItemEditor.setDict, AUC)

        else:
            # No Spell check support
            self.actSpellcheck.setVisible(False)
            a = QAction(self.tr("Install PyEnchant to use spellcheck"), self)
            a.setIcon(self.style().standardIcon(QStyle.SP_MessageBoxWarning))
            a.triggered.connect(self.openPyEnchantWebPage, AUC)
            self.menuTools.addAction(a)

    ###############################################################################
    # SPELLCHECK
    ###############################################################################

    def updateMenuDict(self):

        if not enchant:
            return

        self.menuDict.clear()
        for i in enchant.list_dicts():
            a = QAction(str(i[0]), self)
            a.setCheckable(True)
            if settings.dict is None:
                settings.dict = enchant.get_default_language()
            if str(i[0]) == settings.dict:
                a.setChecked(True)
            a.triggered.connect(self.setDictionary, AUC)
            self.menuDictGroup.addAction(a)
            self.menuDict.addAction(a)

    def setDictionary(self):
        if not enchant:
            return

        for i in self.menuDictGroup.actions():
            if i.isChecked():
                # self.dictChanged.emit(i.text().replace("&", ""))
                settings.dict = i.text().replace("&", "")

                # Find all textEditView from self, and toggle spellcheck
                for w in self.findChildren(textEditView, QRegExp(".*"),
                                           Qt.FindChildrenRecursively):
                    w.setDict(settings.dict)

    def openPyEnchantWebPage(self):
        from PyQt5.QtGui import QDesktopServices
        QDesktopServices.openUrl(QUrl("http://pythonhosted.org/pyenchant/"))

    def toggleSpellcheck(self, val):
        settings.spellcheck = val

        # Find all textEditView from self, and toggle spellcheck
        for w in self.findChildren(textEditView, QRegExp(".*"),
                                   Qt.FindChildrenRecursively):
            w.toggleSpellcheck(val)

    ###############################################################################
    # SETTINGS
    ###############################################################################

    def settingsLabel(self):
        self.settingsWindow(3)

    def settingsStatus(self):
        self.settingsWindow(4)

    def settingsWindow(self, tab=None):
        self.sw = settingsWindow(self)
        self.sw.hide()
        self.sw.setWindowModality(Qt.ApplicationModal)
        self.sw.setWindowFlags(Qt.Dialog)
        r = self.sw.geometry()
        r2 = self.geometry()
        self.sw.move(r2.center() - r.center())
        if tab:
            self.sw.setTab(tab)
        self.sw.show()

    ###############################################################################
    # TOOLS
    ###############################################################################

    def frequencyAnalyzer(self):
        self.fw = frequencyAnalyzer(self)
        self.fw.show()

    ###############################################################################
    # VIEW MENU
    ###############################################################################

    def generateViewMenu(self):

        values = [
            (self.tr("Nothing"), "Nothing"),
            (self.tr("POV"), "POV"),
            (self.tr("Label"), "Label"),
            (self.tr("Progress"), "Progress"),
            (self.tr("Compile"), "Compile"),
        ]

        menus = [
            (self.tr("Tree"), "Tree"),
            (self.tr("Index cards"), "Cork"),
            (self.tr("Outline"), "Outline")
        ]

        submenus = {
            "Tree": [
                (self.tr("Icon color"), "Icon"),
                (self.tr("Text color"), "Text"),
                (self.tr("Background color"), "Background"),
            ],
            "Cork": [
                (self.tr("Icon"), "Icon"),
                (self.tr("Text"), "Text"),
                (self.tr("Background"), "Background"),
                (self.tr("Border"), "Border"),
                (self.tr("Corner"), "Corner"),
            ],
            "Outline": [
                (self.tr("Icon color"), "Icon"),
                (self.tr("Text color"), "Text"),
                (self.tr("Background color"), "Background"),
            ],
        }

        self.menuView.clear()

        # print("Generating menus with", settings.viewSettings)

        for mnu, mnud in menus:
            m = QMenu(mnu, self.menuView)
            for s, sd in submenus[mnud]:
                m2 = QMenu(s, m)
                agp = QActionGroup(m2)
                for v, vd in values:
                    a = QAction(v, m)
                    a.setCheckable(True)
                    a.setData("{},{},{}".format(mnud, sd, vd))
                    if settings.viewSettings[mnud][sd] == vd:
                        a.setChecked(True)
                    a.triggered.connect(self.setViewSettingsAction, AUC)
                    agp.addAction(a)
                    m2.addAction(a)
                m.addMenu(m2)
            self.menuView.addMenu(m)

    def setViewSettingsAction(self):
        action = self.sender()
        item, part, element = action.data().split(",")
        self.setViewSettings(item, part, element)

    def setViewSettings(self, item, part, element):
        settings.viewSettings[item][part] = element
        if item == "Cork":
            self.mainEditor.updateCorkView()
        if item == "Outline":
            self.mainEditor.updateTreeView()
            self.treeOutlineOutline.viewport().update()
        if item == "Tree":
            self.treeRedacOutline.viewport().update()

    ###############################################################################
    # COMPILE
    ###############################################################################

    def doCompile(self):
        self.compileDialog = compileDialog()
        self.compileDialog.show()
예제 #51
0
    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)
        self.currentProject = None

        self.readSettings()

        # UI
        self.setupMoreUi()

        # Welcome
        self.welcome.updateValues()
        # self.welcome.btnCreate.clicked.connect
        self.stack.setCurrentIndex(0)

        # Word count
        self.mprWordCount = QSignalMapper(self)
        for t, i in [
            (self.txtSummarySentence, 0),
            (self.txtSummaryPara, 1),
            (self.txtSummaryPage, 2),
            (self.txtSummaryFull, 3)
        ]:
            t.textChanged.connect(self.mprWordCount.map)
            self.mprWordCount.setMapping(t, i)
        self.mprWordCount.mapped.connect(self.wordCount)

        # Snowflake Method Cycle
        self.mapperCycle = QSignalMapper(self)
        for t, i in [
            (self.btnStepTwo, 0),
            (self.btnStepThree, 1),
            (self.btnStepFour, 2),
            (self.btnStepFive, 3),
            (self.btnStepSix, 4),
            (self.btnStepSeven, 5),
            (self.btnStepEight, 6)
        ]:
            t.clicked.connect(self.mapperCycle.map)
            self.mapperCycle.setMapping(t, i)

        self.mapperCycle.mapped.connect(self.clickCycle)
        self.cmbSummary.currentIndexChanged.connect(self.summaryPageChanged)
        self.cmbSummary.setCurrentIndex(0)
        self.cmbSummary.currentIndexChanged.emit(0)

        # Main Menu
        for i in [self.actSave, self.actSaveAs, self.actCloseProject,
                  self.menuEdit, self.menuMode, self.menuView, self.menuTools,
                  self.menuHelp]:
            i.setEnabled(False)

        self.actOpen.triggered.connect(self.welcome.openFile)
        self.actSave.triggered.connect(self.saveDatas)
        self.actSaveAs.triggered.connect(self.welcome.saveAsFile)
        self.actCompile.triggered.connect(self.doCompile)
        self.actLabels.triggered.connect(self.settingsLabel)
        self.actStatus.triggered.connect(self.settingsStatus)
        self.actSettings.triggered.connect(self.settingsWindow)
        self.actCloseProject.triggered.connect(self.closeProject)
        self.actQuit.triggered.connect(self.close)
        self.actToolFrequency.triggered.connect(self.frequencyAnalyzer)
        self.generateViewMenu()

        self.makeUIConnections()
예제 #52
0
class RagingSeasWindow(QMainWindow):

    """A window used to play the game (contains both players' grids)

    """
    def __init__(self):
        """

        Initializes the main game's window and sets its attributes to their
        default values.

        """
        super(RagingSeasWindow, self).__init__()
        self.ui = Ui_RagingSeasWindow()
        self.ui.setupUi(self)
        self.ui.menuFile.menuAction().setStatusTip(self.tr("File"))
        self.ui.menuHelp.menuAction().setStatusTip(self.tr("Help"))
        self.ui.playerOneLabel.hide()
        self.ui.playerTwoLabel.hide()
        self.leftGridMapper = QSignalMapper(self)
        self.rightGridMapper = QSignalMapper(self)
        self.statusLabel = QLabel(self)
        self.statusLabel.setObjectName("StatusLabel")
        self.ui.statusBar.setSizeGripEnabled(False)
        self.ui.statusBar.addPermanentWidget(self.statusLabel)
        self.setStyleSheet(style.INITIAL_MAIN_WINDOW_STYLE)
        self.setFixedSize(self.size())
        self.setWindowFlags(
            self.windowFlags() ^
            (QtCore.Qt.WindowMinimizeButtonHint |
             QtCore.Qt.WindowMaximizeButtonHint)
        )

        self._session = None
        self._grid_size = None
        self._previous_grid_size = None
        self._is_new_game = False
        self._has_game_been_started = False
        self._current_ship_index = 0
        self._current_orientation = ShipOrientation.horizontal

    def get_session(self):
        return self._session

    def set_session(self, value):
        self._session = value

    session = property(get_session, set_session)

    def get_grid_size(self):
        return self._grid_size

    def set_grid_size(self, value):
        self._grid_size = value

    grid_size = property(get_grid_size, set_grid_size)

    def get_is_new_game(self):
        return self._is_new_game

    def set_is_new_game(self, value):
        self._is_new_game = value

    is_new_game = property(get_is_new_game, set_is_new_game)

    def get_has_game_been_started(self):
        return self._has_game_been_started

    def set_has_game_been_started(self, value):
        self._has_game_been_started = value

    has_game_been_started = property(get_has_game_been_started,
                                     set_has_game_been_started)

    def get_current_ship_index(self):
        return self._current_ship_index

    def set_current_ship_index(self, value):
        self._current_ship_index = value

    current_ship_index = property(get_current_ship_index,
                                  set_current_ship_index)

    def get_current_orientation(self):
        return self._current_orientation

    def set_current_orientation(self, value):
        self._current_orientation = value

    current_orientation = property(get_current_orientation,
                                   set_current_orientation)

    def initialize_grids(self):
        """Creates the players' grids using the chose grid size.

        """
        dimensions = self._grid_size.value

        # disconnect the signal mappers and clear the layouts if a game has
        # previously been started
        if self._has_game_been_started:
            self._disconnect_mappers()
            self._clear_layout(self.ui.gridLayoutLeft)
            self._clear_layout(self.ui.gridLayoutRight)
        else:
            self._has_game_been_started = True

        for i in xrange(0, dimensions):
            for j in xrange(0, dimensions):
                # creating QCustomPushButtons
                self._populate_grid_at_position(GridPosition.left,
                                                self.leftGridMapper,
                                                self.ui.gridLayoutLeft,
                                                (i, j))

                self._populate_grid_at_position(GridPosition.right,
                                                self.rightGridMapper,
                                                self.ui.gridLayoutRight,
                                                (i, j))

        # mapping QSignalMappers to the slots that they will be using
        self.leftGridMapper.mapped[str].connect(self.leftGridButtonClick)
        self.rightGridMapper.mapped[str].connect(self.rightGridButtonClick)

        self._adjust_main_window()
        self._update_status_bar()

    def resolve_grid_button(self, grid_layout, coordinates):
        """Fetches a button at the given coordinates.

        :param grid_layout: an instance of QGridLayout,
        :param coordinates: an instance of type Coordinates, location of the
            item
        :return: an instance of type QPushButton, located at the specified
            coordinates

        """
        x, y = coordinates.x, coordinates.y
        layout_item = grid_layout.itemAtPosition(x, y)

        return layout_item.widget()

    def _adjust_main_window(self):
        # resizes the main window to fit the chosen size of the grid

        dimensions = self._grid_size.value
        width = dimensions * (style.FIELD_ICON_SIZE + 10) * 2 + \
            style.SPACER_WIDTH
        height = dimensions * (style.FIELD_ICON_SIZE + 10) + \
            style.PLAYER_LABEL_HEIGHT
        status_bar_geometry = self.ui.statusBar.geometry()

        self.setFixedSize(width, height + (status_bar_geometry.height() * 2))
        self.setStyleSheet(style.NEW_GAME_MAIN_WINDOW_STYLE)
        self.ui.horizontalLayout.setGeometry(QRect(0, 0, width, height))
        self.ui.playerOneLabel.show()
        self.ui.playerTwoLabel.show()

    def _populate_grid_at_position(self,
                                   grid_position,
                                   mapper,
                                   layout,
                                   coordinate_pair):
        # creates a button and positions it on the grid

        x, y = coordinate_pair[0], coordinate_pair[1]
        textual_coordinates = "{0}-{1}".format(x, y)
        button = QCustomPushButton(
            self,
            grid_position,
            Coordinates.parse_coordinates(textual_coordinates,
                                          self._grid_size)
        )

        Helpers.paint_grid_button(button, style.FIELD_BLUE)
        button.setObjectName("GridButton")
        button.setFixedSize(style.FIELD_ICON_SIZE + 10,
                            style.FIELD_ICON_SIZE + 10)
        button.setIconSize(QSize(style.FIELD_ICON_SIZE, style.FIELD_ICON_SIZE))

        # set the QSignalMapper's mapping to work with strings
        mapper.setMapping(button, textual_coordinates)
        # connecting the button's clicked signal to the QSignalMappers
        # mapped slot
        button.clicked.connect(mapper.map)
        # finally, add the button to the QGridLayout
        layout.addWidget(button, x, y)

    def _clear_layout(self, layout):
        # recursively deletes a QLayout's items making it ready to accept new
        # ones

        if layout is not None:
            while layout.count():
                child = layout.takeAt(0)

                if child.widget() is not None:
                    child.widget().deleteLater()
                elif child.layout() is not None:
                    self._clear_layout(child.layout())

    def _disconnect_mappers(self):
        # resets the QSignalMappers so that they can be used again

        dimensions = self._previous_grid_size.value

        for i in xrange(0, dimensions):
            for j in xrange(0, dimensions):
                button_left = self.resolve_grid_button(
                    self.ui.gridLayoutLeft,
                    Coordinates(i, j)
                )
                button_right = self.resolve_grid_button(
                    self.ui.gridLayoutRight,
                    Coordinates(i, j)
                )

                self.leftGridMapper.removeMappings(button_left)
                self.rightGridMapper.removeMappings(button_right)

        self.leftGridMapper.disconnect()
        self.rightGridMapper.disconnect()

    def _update_status_bar(self):
        session_phase = self.session.session_phase
        message = EnumConverters.session_phase_to_string_converter(
            session_phase
        )

        if session_phase == SessionPhase.fleet_layout:
            fleet = self.session.player_one.fleet
            current_ship = fleet.ships[self._current_ship_index]
            message += self.tr(", Current ship: {0} (size - {1})".format(
                EnumConverters.ship_type_to_string_converter(
                    current_ship.ship_type
                ),
                current_ship.ship_type.value)
            )

        self.statusLabel.setText(self.tr("Phase: " + message))

    def _paint_player_grid(self, grid_layout, player, reveal=False):
        # marks the grid's squares according to their state

        grid = player.grid
        dimensions = grid.grid_size.value

        if player.player_type == PlayerType.human:
            reveal = True

        for i in xrange(0, dimensions):
            for j in xrange(0, dimensions):
                current_square = grid.squares.item((i, j))
                owner = current_square.owner
                square_state = current_square.square_state
                button = self.resolve_grid_button(grid_layout,
                                                  Coordinates(i, j))

                if (
                    square_state == SquareState.vacant or
                    square_state == SquareState.unoccupiable
                ):
                    Helpers.paint_grid_button(button, style.FIELD_BLUE)
                elif square_state == SquareState.populated:
                    if reveal:
                        Helpers.paint_grid_button(button, style.FIELD_GRAY)
                    else:
                        Helpers.paint_grid_button(button, style.FIELD_BLUE)
                elif square_state == SquareState.hit:
                    if owner is not None:
                        if owner.ship_state == ShipState.damaged:
                            Helpers.paint_grid_button(button, style.FIELD_RED)
                        elif owner.ship_state == ShipState.sunk:
                            Helpers.paint_grid_button(button,
                                                      style.FIELD_BLACK)
                    else:
                        Helpers.paint_grid_button(button,
                                                  style.FIELD_LIGHT_BLUE)

    def _paint_both_player_grids(self, player_one, player_two, reveal=False):
            self._paint_player_grid(self.ui.gridLayoutLeft,
                                    player_one,
                                    reveal)
            self._paint_player_grid(self.ui.gridLayoutRight,
                                    player_two,
                                    reveal)

    def _declare_winner(self, winner):
        self.session.session_phase = SessionPhase.game_over
        self._is_new_game = False
        self._update_status_bar()

        player_type_textual = EnumConverters.\
            player_type_to_string_converter(winner.player_type)

        Helpers.raise_info(
            self,
            self.tr("Game over - {0} wins!".format(
                    player_type_textual))
        )

    @pyqtSlot(str, name="leftGridButtonClick")
    def leftGridButtonClick(self, textual_coordinates):
        """Slot used when the left grid's QCustomPushButton is clicked.

        :param textual_coordinates: position of the button represented as a
            string

        """
        numerical_coordinates = Coordinates.parse_coordinates(
            textual_coordinates, self._grid_size
        )
        session_phase = self._session.session_phase

        if session_phase == SessionPhase.fleet_layout:
            grid = self._session.player_one.grid
            fleet = self._session.player_one.fleet
            ship = fleet.ships[self._current_ship_index]

            if fleet.position_ship(grid,
                                   ship,
                                   self._current_orientation,
                                   numerical_coordinates):
                self._current_ship_index += 1

                if self._current_ship_index == len(fleet.ships):
                    self._session.session_phase = SessionPhase.battle

                    self._session.player_one.initialize_fleet()
                    self._session.player_two.initialize_fleet()

            self._update_status_bar()
        self._paint_player_grid(self.ui.gridLayoutLeft,
                                self._session.player_one)

    @pyqtSlot(str, name="rightGridButtonClick")
    def rightGridButtonClick(self, textual_coordinates):
        """Slot used when the right grid's QCustomPushButton is clicked.

        :param textual_coordinates: position of the button represented as a
            string

        """
        numerical_coordinates = Coordinates.parse_coordinates(
            textual_coordinates, self._grid_size
        )
        session_phase = self._session.session_phase
        player_one = self.session.player_one
        player_two = self.session.player_two

        if session_phase == SessionPhase.battle:
            if not player_one.shoot(player_two.grid, numerical_coordinates):
                return
            else:
                if player_two.fleet.is_sunk():
                    self._paint_both_player_grids(player_one, player_two, True)
                    self._declare_winner(player_one)
                    return

            if not player_two.shoot(player_one.grid):
                return
            else:
                if player_one.fleet.is_sunk():
                    self._paint_both_player_grids(player_one, player_two, True)
                    self._declare_winner(player_two)
                    return

            self._paint_both_player_grids(player_one, player_two)

    @pyqtSlot(name="menuNewGameClick")
    def menuNewGameClick(self):
        """Slot used when the "New Game" menu item is clicked.

        """
        raise_dialog = True
        new_game_dialog = NewGameDialog(self)
        if self._is_new_game:
            if not Helpers.raise_question(
                self,
                self.tr("Are you sure you want to start a new game?")
            ):
                raise_dialog = False
        if raise_dialog:
            self._previous_grid_size = self._grid_size
            new_game_dialog.exec_()

    @pyqtSlot(name="menuAboutClick")
    def menuAboutClick(self):
        """Slot used when the "About" menu item is clicked.

        """
        about_dialog = AboutDialog(self)
        about_dialog.exec_()

    @pyqtSlot(name="menuExitClick")
    def menuExitClick(self):
        """Slot used when the "Exit" menu item is clicked.

        """
        self.close()

    def closeEvent(self, e):
        """Overridden close event.

        :param e: an instance of type QCloseEvent

        """
        if self._is_new_game:
            if Helpers.raise_question(
                self,
                self.tr("Are you sure you want to quit?")
            ):
                e.accept()
            else:
                e.ignore()
예제 #53
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._viewMode = None
        self._quickSendOptRow = 1

        self.setupUi(self)
        self.setCorner(Qt.TopLeftCorner, Qt.LeftDockWidgetArea)
        self.setCorner(Qt.BottomLeftCorner, Qt.LeftDockWidgetArea)
        font = QtGui.QFont()
        font.setFamily(EDITOR_FONT)
        font.setPointSize(9)
        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.setupMenu()
        self.setupFlatUi()
        self.onEnumPorts()

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

        self.defaultStyleWidget = QWidget()
        self.defaultStyleWidget.setWindowIcon(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.openQuickSend)
        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.onSend)

        self.receiver_thread.read.connect(self.onReceive)
        self.receiver_thread.exception.connect(self.onReaderExcept)
        self._signalMapQuickSendOpt = QSignalMapper(self)
        self._signalMapQuickSendOpt.mapped[int].connect(self.onQuickSendOptions)
        self._signalMapQuickSend = QSignalMapper(self)
        self._signalMapQuickSend.mapped[int].connect(self.onQuickSend)

        # 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()
예제 #54
0
class MainWindow(QMainWindow):
    """This create the main window of the application"""
    def __init__(self):
        super(MainWindow, self).__init__()
        # remove close & maximize window buttons
        #self.setWindowFlags(Qt.CustomizeWindowHint|Qt.WindowMinimizeButtonHint)
        self.setMinimumSize(500, 666)
        #self.setMaximumSize(1000,666)
        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)

        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.child = None

        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.updateMenus()
        self.readSettings()
        self.setWindowTitle("LEKTURE")

        mytoolbar = QToolBar()
        #self.toolbar = self.addToolBar()
        mytoolbar.addAction(self.newAct)
        mytoolbar.addAction(self.openAct)
        mytoolbar.addAction(self.saveAct)
        mytoolbar.addAction(self.saveAsAct)
        mytoolbar.addSeparator()
        mytoolbar.addAction(self.outputsAct)
        mytoolbar.addAction(self.scenarioAct)
        self.scenarioAct.setVisible(False)
        mytoolbar.setMovable(False)
        mytoolbar.setFixedWidth(60)
        self.addToolBar(Qt.LeftToolBarArea, mytoolbar)

    def closeEvent(self, scenario):
        """method called when the main window wants to be closed"""
        self.mdiArea.closeAllSubWindows()
        if self.mdiArea.currentSubWindow():
            scenario.ignore()
        else:
            self.writeSettings()
            scenario.accept()

    def newFile(self):
        """creates a new project"""
        child = self.createProjekt()
        child.newFile()
        child.show()
        self.child = child

    def open(self):
        """open a project"""
        fileName, _ = QFileDialog.getOpenFileName(self)
        if fileName:
            existing = self.findProjekt(fileName)
            if existing:
                self.mdiArea.setActiveSubWindow(existing)
                return

            child = self.createProjekt()
            if child.loadFile(fileName):
                self.statusBar().showMessage("File loaded", 2000)
                child.show()
            else:
                child.close()

    def save(self):
        """called when user save a project"""
        if self.activeProjekt() and self.activeProjekt().save():
            self.statusBar().showMessage("File saved", 2000)
        else:
            self.statusBar().showMessage("Error when trying to save the file")

    def saveAs(self):
        """called when user save AS a project"""
        if self.activeProjekt() and self.activeProjekt().saveAs():
            self.statusBar().showMessage("File saved", 2000)
        else:
            self.statusBar().showMessage("Error when trying to save the file")

    def openFolder(self):
        """called when user calls 'reveal in finder' function"""
        if self.activeProjekt() and self.activeProjekt().openFolder():
            self.statusBar().showMessage("File revealed in Finder", 2000)

    def about(self):
        """called when user wants to know a bit more on the app"""
        import sys
        python_version = str(sys.version_info[0])
        python_version_temp = sys.version_info[1:5]
        for item in python_version_temp:
            python_version = python_version + "." + str(item)
        QMessageBox.about(self, "About Lekture",
                            "pylekture build " + str(pylekture.__version__ + "\n" + \
                            "python version " + str(python_version)))

    def updateMenus(self):
        """update menus"""
        hasProjekt = (self.activeProjekt() is not None)
        self.saveAct.setEnabled(hasProjekt)
        self.saveAsAct.setEnabled(hasProjekt)
        self.outputsAct.setEnabled(hasProjekt)
        self.scenarioAct.setEnabled(hasProjekt)
        self.openFolderAct.setEnabled(hasProjekt)
        self.closeAct.setEnabled(hasProjekt)
        self.closeAllAct.setEnabled(hasProjekt)
        self.nextAct.setEnabled(hasProjekt)
        self.previousAct.setEnabled(hasProjekt)
        self.separatorAct.setVisible(hasProjekt)

    def updateWindowMenu(self):
        """unpates menus on the window toolbar"""
        self.windowMenu.clear()
        self.windowMenu.addAction(self.closeAct)
        self.windowMenu.addAction(self.closeAllAct)
        self.windowMenu.addSeparator()
        self.windowMenu.addAction(self.nextAct)
        self.windowMenu.addAction(self.previousAct)
        self.windowMenu.addAction(self.separatorAct)

        windows = self.mdiArea.subWindowList()
        self.separatorAct.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            child = window.widget()

            text = "%d %s" % (i + 1, child.userFriendlyCurrentFile())
            if i < 9:
                text = '&' + text

            action = self.windowMenu.addAction(text)
            action.setCheckable(True)
            action.setChecked(child is self.activeProjekt())
            action.triggered.connect(self.windowMapper.map)
            self.windowMapper.setMapping(action, window)

    def createProjekt(self):
        """create a new project"""
        child = Projekt()
        self.mdiArea.addSubWindow(child)
        self.child = child
        return child

    def createActions(self):
        """create all actions"""
        self.newAct = QAction("&New", self,
                              shortcut=QKeySequence.New, statusTip="Create a new file",
                              triggered=self.newFile)

        self.openAct = QAction("&Open...", self,
                               shortcut=QKeySequence.Open, statusTip="Open an existing file",
                               triggered=self.open)

        self.saveAct = QAction("&Save", self,
                               shortcut=QKeySequence.Save,
                               statusTip="Save the document to disk", triggered=self.save)

        self.saveAsAct = QAction("Save &As...", self,
                                 shortcut=QKeySequence.SaveAs,
                                 statusTip="Save the document under a new name",
                                 triggered=self.saveAs)

        self.openFolderAct = QAction("Open Project Folder", self,
                                     statusTip="Reveal Project in Finder",
                                     triggered=self.openFolder)

        self.exitAct = QAction("E&xit", self, shortcut=QKeySequence.Quit,
                               statusTip="Exit the application",
                               triggered=QApplication.instance().closeAllWindows)

        self.closeAct = QAction("Cl&ose", self,
                                statusTip="Close the active window",
                                triggered=self.mdiArea.closeActiveSubWindow)

        self.outputsAct = QAction("Outputs", self,
                                  statusTip="Open the outputs panel",
                                  triggered=self.openOutputsPanel)

        self.scenarioAct = QAction("Scenario", self,
                                   statusTip="Open the scenario panel",
                                   triggered=self.openScenarioPanel)

        self.closeAllAct = QAction("Close &All", self,
                                   statusTip="Close all the windows",
                                   triggered=self.mdiArea.closeAllSubWindows)

        self.nextAct = QAction("Ne&xt", self, shortcut=QKeySequence.NextChild,
                               statusTip="Move the focus to the next window",
                               triggered=self.mdiArea.activateNextSubWindow)

        self.previousAct = QAction("Pre&vious", self,
                                   shortcut=QKeySequence.PreviousChild,
                                   statusTip="Move the focus to the previous window",
                                   triggered=self.mdiArea.activatePreviousSubWindow)

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

        self.aboutAct = QAction("&About", self,
                                statusTip="Show the application's About box",
                                triggered=self.about)

    def createMenus(self):
        """create all menus"""
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.openFolderAct)
        self.fileMenu.addAction(self.exitAct)

        self.viewMenu = self.menuBar().addMenu("&View")
        self.viewMenu.addAction(self.outputsAct)
        self.viewMenu.addAction(self.scenarioAct)

        self.windowMenu = self.menuBar().addMenu("&Window")
        self.updateWindowMenu()
        self.windowMenu.aboutToShow.connect(self.updateWindowMenu)

        self.menuBar().addSeparator()

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.aboutAct)

    def createStatusBar(self):
        """create the status bar"""
        self.statusBar().showMessage("Ready")

    def readSettings(self):
        """read the settings"""
        settings = QSettings('Pixel Stereo', 'lekture')
        pos = settings.value('pos', QPoint(200, 200))
        size = settings.value('size', QSize(1000, 650))
        self.move(pos)
        self.resize(size)

    def writeSettings(self):
        """write settings"""
        settings = QSettings('Pixel Stereo', 'lekture')
        settings.setValue('pos', self.pos())
        settings.setValue('size', self.size())

    def activeProjekt(self):
        """return the active project object"""
        activeSubWindow = self.mdiArea.activeSubWindow()
        if activeSubWindow:
            return activeSubWindow.widget()
        else:
            return None

    def findProjekt(self, fileName):
        """return the project"""
        canonicalFilePath = QFileInfo(fileName).canonicalFilePath()

        for window in self.mdiArea.subWindowList():
            if window.widget().currentFile() == canonicalFilePath:
                return window
        return None

    def setActiveSubWindow(self, window):
        """set the active sub window"""
        if window:
            self.mdiArea.setActiveSubWindow(window)

    def openOutputsPanel(self):
        """switch to the outputs editor"""
        if self.child:
            project = self.activeProjekt()
            project.scenario_events_group.setVisible(False)
            project.outputs_group.setVisible(True)
            self.scenarioAct.setVisible(True)
            self.outputsAct.setVisible(False)

    def openScenarioPanel(self):
        """switch to the scenario editors"""
        if self.child:
            project = self.activeProjekt()
            project.outputs_group.setVisible(False)
            project.scenario_events_group.setVisible(True)
            self.scenarioAct.setVisible(False)
            self.outputsAct.setVisible(True)
예제 #55
0
 def __initActions(self):
     """
     Private method to initialize the view actions.
     """
     self.alignMapper = QSignalMapper(self)
     self.alignMapper.mapped[int].connect(self.__alignShapes)
     
     self.deleteShapeAct = \
         QAction(UI.PixmapCache.getIcon("deleteShape.png"),
                 self.tr("Delete shapes"), self)
     self.deleteShapeAct.triggered.connect(self.__deleteShape)
     
     self.incWidthAct = \
         QAction(UI.PixmapCache.getIcon("sceneWidthInc.png"),
                 self.tr("Increase width by {0} points").format(
                     self.deltaSize),
                 self)
     self.incWidthAct.triggered.connect(self.__incWidth)
     
     self.incHeightAct = \
         QAction(UI.PixmapCache.getIcon("sceneHeightInc.png"),
                 self.tr("Increase height by {0} points").format(
                     self.deltaSize),
                 self)
     self.incHeightAct.triggered.connect(self.__incHeight)
     
     self.decWidthAct = \
         QAction(UI.PixmapCache.getIcon("sceneWidthDec.png"),
                 self.tr("Decrease width by {0} points").format(
                     self.deltaSize),
                 self)
     self.decWidthAct.triggered.connect(self.__decWidth)
     
     self.decHeightAct = \
         QAction(UI.PixmapCache.getIcon("sceneHeightDec.png"),
                 self.tr("Decrease height by {0} points").format(
                     self.deltaSize),
                 self)
     self.decHeightAct.triggered.connect(self.__decHeight)
     
     self.setSizeAct = \
         QAction(UI.PixmapCache.getIcon("sceneSize.png"),
                 self.tr("Set size"), self)
     self.setSizeAct.triggered.connect(self.__setSize)
     
     self.rescanAct = \
         QAction(UI.PixmapCache.getIcon("rescan.png"),
                 self.tr("Re-Scan"), self)
     self.rescanAct.triggered.connect(self.__rescan)
     
     self.relayoutAct = \
         QAction(UI.PixmapCache.getIcon("relayout.png"),
                 self.tr("Re-Layout"), self)
     self.relayoutAct.triggered.connect(self.__relayout)
     
     self.alignLeftAct = \
         QAction(UI.PixmapCache.getIcon("shapesAlignLeft.png"),
                 self.tr("Align Left"), self)
     self.alignMapper.setMapping(self.alignLeftAct, Qt.AlignLeft)
     self.alignLeftAct.triggered.connect(self.alignMapper.map)
     
     self.alignHCenterAct = \
         QAction(UI.PixmapCache.getIcon("shapesAlignHCenter.png"),
                 self.tr("Align Center Horizontal"), self)
     self.alignMapper.setMapping(self.alignHCenterAct, Qt.AlignHCenter)
     self.alignHCenterAct.triggered.connect(self.alignMapper.map)
     
     self.alignRightAct = \
         QAction(UI.PixmapCache.getIcon("shapesAlignRight.png"),
                 self.tr("Align Right"), self)
     self.alignMapper.setMapping(self.alignRightAct, Qt.AlignRight)
     self.alignRightAct.triggered.connect(self.alignMapper.map)
     
     self.alignTopAct = \
         QAction(UI.PixmapCache.getIcon("shapesAlignTop.png"),
                 self.tr("Align Top"), self)
     self.alignMapper.setMapping(self.alignTopAct, Qt.AlignTop)
     self.alignTopAct.triggered.connect(self.alignMapper.map)
     
     self.alignVCenterAct = \
         QAction(UI.PixmapCache.getIcon("shapesAlignVCenter.png"),
                 self.tr("Align Center Vertical"), self)
     self.alignMapper.setMapping(self.alignVCenterAct, Qt.AlignVCenter)
     self.alignVCenterAct.triggered.connect(self.alignMapper.map)
     
     self.alignBottomAct = \
         QAction(UI.PixmapCache.getIcon("shapesAlignBottom.png"),
                 self.tr("Align Bottom"), self)
     self.alignMapper.setMapping(self.alignBottomAct, Qt.AlignBottom)
     self.alignBottomAct.triggered.connect(self.alignMapper.map)
예제 #56
0
    def contextMenu(self, parent, index):
        menu = None
        row = index.row()
        if (row >= 0 and row < self.mCommands.size()):
            menu = QMenu(parent)
            if (row > 0):
                action = menu.addAction(self.tr("Move Up"))
                mapper = QSignalMapper(action)
                mapper.setMapping(action, row)
                action.triggered.connect(mapper.map)
                mapper.mapped.connect(self.moveUp)

            if (row+1 < self.mCommands.size()):
                action = menu.addAction(self.tr("Move Down"))
                mapper = QSignalMapper(action)
                mapper.setMapping(action, row + 1)
                action.triggered.connect(mapper.map)
                mapper.mapped.connect(self.moveUp)

            menu.addSeparator()

            action = menu.addAction(self.tr("Execute"))
            mapper = QSignalMapper(action)
            mapper.setMapping(action, row)
            action.triggered.connect(mapper.map)
            mapper.mapped.connect(self.execute)

            if sys.platform in ['linux', 'darwin']:
                action = menu.addAction(self.tr("Execute in Terminal"))
                mapper = QSignalMapper(action)
                mapper.setMapping(action, row)
                action.triggered.connect(mapper.map)
                mapper.mapped.connect(self.executeInTerminal)

            menu.addSeparator()

            action = menu.addAction(self.tr("Delete"))
            mapper = QSignalMapper(action)
            mapper.setMapping(action, row)
            action.triggered.connect(mapper.map)
            mapper.mapped.connect(self.remove)

        return menu
예제 #57
0
class UMLGraphicsView(E5GraphicsView):
    """
    Class implementing a specialized E5GraphicsView for our diagrams.
    
    @signal relayout() emitted to indicate a relayout of the diagram
        is requested
    """
    relayout = pyqtSignal()
    
    def __init__(self, scene, parent=None):
        """
        Constructor
        
        @param scene reference to the scene object (QGraphicsScene)
        @param parent parent widget of the view (QWidget)
        """
        E5GraphicsView.__init__(self, scene, parent)
        self.setObjectName("UMLGraphicsView")
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        
        self.diagramName = "Unnamed"
        self.__itemId = -1
        
        self.border = 10
        self.deltaSize = 100.0
        
        self.__zoomWidget = E5ZoomWidget(
            UI.PixmapCache.getPixmap("zoomOut.png"),
            UI.PixmapCache.getPixmap("zoomIn.png"),
            UI.PixmapCache.getPixmap("zoomReset.png"), self)
        parent.statusBar().addPermanentWidget(self.__zoomWidget)
        self.__zoomWidget.setMapping(
            E5GraphicsView.ZoomLevels, E5GraphicsView.ZoomLevelDefault)
        self.__zoomWidget.valueChanged.connect(self.setZoom)
        self.zoomValueChanged.connect(self.__zoomWidget.setValue)
        
        self.__initActions()
        
        scene.changed.connect(self.__sceneChanged)
        
        self.grabGesture(Qt.PinchGesture)
        
    def __initActions(self):
        """
        Private method to initialize the view actions.
        """
        self.alignMapper = QSignalMapper(self)
        self.alignMapper.mapped[int].connect(self.__alignShapes)
        
        self.deleteShapeAct = \
            QAction(UI.PixmapCache.getIcon("deleteShape.png"),
                    self.tr("Delete shapes"), self)
        self.deleteShapeAct.triggered.connect(self.__deleteShape)
        
        self.incWidthAct = \
            QAction(UI.PixmapCache.getIcon("sceneWidthInc.png"),
                    self.tr("Increase width by {0} points").format(
                        self.deltaSize),
                    self)
        self.incWidthAct.triggered.connect(self.__incWidth)
        
        self.incHeightAct = \
            QAction(UI.PixmapCache.getIcon("sceneHeightInc.png"),
                    self.tr("Increase height by {0} points").format(
                        self.deltaSize),
                    self)
        self.incHeightAct.triggered.connect(self.__incHeight)
        
        self.decWidthAct = \
            QAction(UI.PixmapCache.getIcon("sceneWidthDec.png"),
                    self.tr("Decrease width by {0} points").format(
                        self.deltaSize),
                    self)
        self.decWidthAct.triggered.connect(self.__decWidth)
        
        self.decHeightAct = \
            QAction(UI.PixmapCache.getIcon("sceneHeightDec.png"),
                    self.tr("Decrease height by {0} points").format(
                        self.deltaSize),
                    self)
        self.decHeightAct.triggered.connect(self.__decHeight)
        
        self.setSizeAct = \
            QAction(UI.PixmapCache.getIcon("sceneSize.png"),
                    self.tr("Set size"), self)
        self.setSizeAct.triggered.connect(self.__setSize)
        
        self.rescanAct = \
            QAction(UI.PixmapCache.getIcon("rescan.png"),
                    self.tr("Re-Scan"), self)
        self.rescanAct.triggered.connect(self.__rescan)
        
        self.relayoutAct = \
            QAction(UI.PixmapCache.getIcon("relayout.png"),
                    self.tr("Re-Layout"), self)
        self.relayoutAct.triggered.connect(self.__relayout)
        
        self.alignLeftAct = \
            QAction(UI.PixmapCache.getIcon("shapesAlignLeft.png"),
                    self.tr("Align Left"), self)
        self.alignMapper.setMapping(self.alignLeftAct, Qt.AlignLeft)
        self.alignLeftAct.triggered.connect(self.alignMapper.map)
        
        self.alignHCenterAct = \
            QAction(UI.PixmapCache.getIcon("shapesAlignHCenter.png"),
                    self.tr("Align Center Horizontal"), self)
        self.alignMapper.setMapping(self.alignHCenterAct, Qt.AlignHCenter)
        self.alignHCenterAct.triggered.connect(self.alignMapper.map)
        
        self.alignRightAct = \
            QAction(UI.PixmapCache.getIcon("shapesAlignRight.png"),
                    self.tr("Align Right"), self)
        self.alignMapper.setMapping(self.alignRightAct, Qt.AlignRight)
        self.alignRightAct.triggered.connect(self.alignMapper.map)
        
        self.alignTopAct = \
            QAction(UI.PixmapCache.getIcon("shapesAlignTop.png"),
                    self.tr("Align Top"), self)
        self.alignMapper.setMapping(self.alignTopAct, Qt.AlignTop)
        self.alignTopAct.triggered.connect(self.alignMapper.map)
        
        self.alignVCenterAct = \
            QAction(UI.PixmapCache.getIcon("shapesAlignVCenter.png"),
                    self.tr("Align Center Vertical"), self)
        self.alignMapper.setMapping(self.alignVCenterAct, Qt.AlignVCenter)
        self.alignVCenterAct.triggered.connect(self.alignMapper.map)
        
        self.alignBottomAct = \
            QAction(UI.PixmapCache.getIcon("shapesAlignBottom.png"),
                    self.tr("Align Bottom"), self)
        self.alignMapper.setMapping(self.alignBottomAct, Qt.AlignBottom)
        self.alignBottomAct.triggered.connect(self.alignMapper.map)
        
    def __checkSizeActions(self):
        """
        Private slot to set the enabled state of the size actions.
        """
        diagramSize = self._getDiagramSize(10)
        sceneRect = self.scene().sceneRect()
        if (sceneRect.width() - self.deltaSize) < diagramSize.width():
            self.decWidthAct.setEnabled(False)
        else:
            self.decWidthAct.setEnabled(True)
        if (sceneRect.height() - self.deltaSize) < diagramSize.height():
            self.decHeightAct.setEnabled(False)
        else:
            self.decHeightAct.setEnabled(True)
        
    def __sceneChanged(self, areas):
        """
        Private slot called when the scene changes.
        
        @param areas list of rectangles that contain changes (list of QRectF)
        """
        if len(self.scene().selectedItems()) > 0:
            self.deleteShapeAct.setEnabled(True)
        else:
            self.deleteShapeAct.setEnabled(False)
        
        sceneRect = self.scene().sceneRect()
        newWidth = width = sceneRect.width()
        newHeight = height = sceneRect.height()
        rect = self.scene().itemsBoundingRect()
        # calculate with 10 pixel border on each side
        if sceneRect.right() - 10 < rect.right():
            newWidth = rect.right() + 10
        if sceneRect.bottom() - 10 < rect.bottom():
            newHeight = rect.bottom() + 10
        
        if newHeight != height or newWidth != width:
            self.setSceneSize(newWidth, newHeight)
            self.__checkSizeActions()
        
    def initToolBar(self):
        """
        Public method to populate a toolbar with our actions.
        
        @return the populated toolBar (QToolBar)
        """
        toolBar = QToolBar(self.tr("Graphics"), self)
        toolBar.setIconSize(UI.Config.ToolBarIconSize)
        toolBar.addAction(self.deleteShapeAct)
        toolBar.addSeparator()
        toolBar.addAction(self.alignLeftAct)
        toolBar.addAction(self.alignHCenterAct)
        toolBar.addAction(self.alignRightAct)
        toolBar.addAction(self.alignTopAct)
        toolBar.addAction(self.alignVCenterAct)
        toolBar.addAction(self.alignBottomAct)
        toolBar.addSeparator()
        toolBar.addAction(self.incWidthAct)
        toolBar.addAction(self.incHeightAct)
        toolBar.addAction(self.decWidthAct)
        toolBar.addAction(self.decHeightAct)
        toolBar.addAction(self.setSizeAct)
        toolBar.addSeparator()
        toolBar.addAction(self.rescanAct)
        toolBar.addAction(self.relayoutAct)
        
        return toolBar
        
    def filteredItems(self, items, itemType=UMLItem):
        """
        Public method to filter a list of items.
        
        @param items list of items as returned by the scene object
            (QGraphicsItem)
        @param itemType type to be filtered (class)
        @return list of interesting collision items (QGraphicsItem)
        """
        return [itm for itm in items if isinstance(itm, itemType)]
        
    def selectItems(self, items):
        """
        Public method to select the given items.
        
        @param items list of items to be selected (list of QGraphicsItemItem)
        """
        # step 1: deselect all items
        self.unselectItems()
        
        # step 2: select all given items
        for itm in items:
            if isinstance(itm, UMLItem):
                itm.setSelected(True)
        
    def selectItem(self, item):
        """
        Public method to select an item.
        
        @param item item to be selected (QGraphicsItemItem)
        """
        if isinstance(item, UMLItem):
            item.setSelected(not item.isSelected())
        
    def __deleteShape(self):
        """
        Private method to delete the selected shapes from the display.
        """
        for item in self.scene().selectedItems():
            item.removeAssociations()
            item.setSelected(False)
            self.scene().removeItem(item)
            del item
        
    def __incWidth(self):
        """
        Private method to handle the increase width context menu entry.
        """
        self.resizeScene(self.deltaSize, True)
        self.__checkSizeActions()
        
    def __incHeight(self):
        """
        Private method to handle the increase height context menu entry.
        """
        self.resizeScene(self.deltaSize, False)
        self.__checkSizeActions()
        
    def __decWidth(self):
        """
        Private method to handle the decrease width context menu entry.
        """
        self.resizeScene(-self.deltaSize, True)
        self.__checkSizeActions()
        
    def __decHeight(self):
        """
        Private method to handle the decrease height context menu entry.
        """
        self.resizeScene(-self.deltaSize, False)
        self.__checkSizeActions()
        
    def __setSize(self):
        """
        Private method to handle the set size context menu entry.
        """
        from .UMLSceneSizeDialog import UMLSceneSizeDialog
        rect = self._getDiagramRect(10)
        sceneRect = self.scene().sceneRect()
        dlg = UMLSceneSizeDialog(sceneRect.width(), sceneRect.height(),
                                 rect.width(), rect.height(), self)
        if dlg.exec_() == QDialog.Accepted:
            width, height = dlg.getData()
            self.setSceneSize(width, height)
        self.__checkSizeActions()
        
    def autoAdjustSceneSize(self, limit=False):
        """
        Public method to adjust the scene size to the diagram size.
        
        @param limit flag indicating to limit the scene to the
            initial size (boolean)
        """
        super(UMLGraphicsView, self).autoAdjustSceneSize(limit=limit)
        self.__checkSizeActions()
        
    def saveImage(self):
        """
        Public method to handle the save context menu entry.
        """
        fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
            self,
            self.tr("Save Diagram"),
            "",
            self.tr("Portable Network Graphics (*.png);;"
                    "Scalable Vector Graphics (*.svg)"),
            "",
            E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
        if fname:
            ext = QFileInfo(fname).suffix()
            if not ext:
                ex = selectedFilter.split("(*")[1].split(")")[0]
                if ex:
                    fname += ex
            if QFileInfo(fname).exists():
                res = E5MessageBox.yesNo(
                    self,
                    self.tr("Save Diagram"),
                    self.tr("<p>The file <b>{0}</b> already exists."
                            " Overwrite it?</p>").format(fname),
                    icon=E5MessageBox.Warning)
                if not res:
                    return
            
            success = super(UMLGraphicsView, self).saveImage(
                fname, QFileInfo(fname).suffix().upper())
            if not success:
                E5MessageBox.critical(
                    self,
                    self.tr("Save Diagram"),
                    self.tr(
                        """<p>The file <b>{0}</b> could not be saved.</p>""")
                    .format(fname))
        
    def __relayout(self):
        """
        Private slot to handle the re-layout context menu entry.
        """
        self.__itemId = -1
        self.scene().clear()
        self.relayout.emit()
        
    def __rescan(self):
        """
        Private slot to handle the re-scan context menu entry.
        """
        # 1. save positions of all items and names of selected items
        itemPositions = {}
        selectedItems = []
        for item in self.filteredItems(self.scene().items(), UMLItem):
            name = item.getName()
            if name:
                itemPositions[name] = (item.x(), item.y())
                if item.isSelected():
                    selectedItems.append(name)
        
        # 2. save
        
        # 2. re-layout the diagram
        self.__relayout()
        
        # 3. move known items to the saved positions
        for item in self.filteredItems(self.scene().items(), UMLItem):
            name = item.getName()
            if name in itemPositions:
                item.setPos(*itemPositions[name])
            if name in selectedItems:
                item.setSelected(True)
        
    def printDiagram(self):
        """
        Public slot called to print the diagram.
        """
        printer = QPrinter(mode=QPrinter.ScreenResolution)
        printer.setFullPage(True)
        if Preferences.getPrinter("ColorMode"):
            printer.setColorMode(QPrinter.Color)
        else:
            printer.setColorMode(QPrinter.GrayScale)
        if Preferences.getPrinter("FirstPageFirst"):
            printer.setPageOrder(QPrinter.FirstPageFirst)
        else:
            printer.setPageOrder(QPrinter.LastPageFirst)
        printer.setPageMargins(
            Preferences.getPrinter("LeftMargin") * 10,
            Preferences.getPrinter("TopMargin") * 10,
            Preferences.getPrinter("RightMargin") * 10,
            Preferences.getPrinter("BottomMargin") * 10,
            QPrinter.Millimeter
        )
        printerName = Preferences.getPrinter("PrinterName")
        if printerName:
            printer.setPrinterName(printerName)
        
        printDialog = QPrintDialog(printer, self)
        if printDialog.exec_():
            super(UMLGraphicsView, self).printDiagram(
                printer, self.diagramName)
        
    def printPreviewDiagram(self):
        """
        Public slot called to show a print preview of the diagram.
        """
        from PyQt5.QtPrintSupport import QPrintPreviewDialog
        
        printer = QPrinter(mode=QPrinter.ScreenResolution)
        printer.setFullPage(True)
        if Preferences.getPrinter("ColorMode"):
            printer.setColorMode(QPrinter.Color)
        else:
            printer.setColorMode(QPrinter.GrayScale)
        if Preferences.getPrinter("FirstPageFirst"):
            printer.setPageOrder(QPrinter.FirstPageFirst)
        else:
            printer.setPageOrder(QPrinter.LastPageFirst)
        printer.setPageMargins(
            Preferences.getPrinter("LeftMargin") * 10,
            Preferences.getPrinter("TopMargin") * 10,
            Preferences.getPrinter("RightMargin") * 10,
            Preferences.getPrinter("BottomMargin") * 10,
            QPrinter.Millimeter
        )
        printerName = Preferences.getPrinter("PrinterName")
        if printerName:
            printer.setPrinterName(printerName)
        
        preview = QPrintPreviewDialog(printer, self)
        preview.paintRequested[QPrinter].connect(self.__printPreviewPrint)
        preview.exec_()
        
    def __printPreviewPrint(self, printer):
        """
        Private slot to generate a print preview.
        
        @param printer reference to the printer object (QPrinter)
        """
        super(UMLGraphicsView, self).printDiagram(printer, self.diagramName)
        
    def setDiagramName(self, name):
        """
        Public slot to set the diagram name.
        
        @param name diagram name (string)
        """
        self.diagramName = name
        
    def __alignShapes(self, alignment):
        """
        Private slot to align the selected shapes.
        
        @param alignment alignment type (Qt.AlignmentFlag)
        """
        # step 1: get all selected items
        items = self.scene().selectedItems()
        if len(items) <= 1:
            return
        
        # step 2: find the index of the item to align in relation to
        amount = None
        for i, item in enumerate(items):
            rect = item.sceneBoundingRect()
            if alignment == Qt.AlignLeft:
                if amount is None or rect.x() < amount:
                    amount = rect.x()
                    index = i
            elif alignment == Qt.AlignRight:
                if amount is None or rect.x() + rect.width() > amount:
                    amount = rect.x() + rect.width()
                    index = i
            elif alignment == Qt.AlignHCenter:
                if amount is None or rect.width() > amount:
                    amount = rect.width()
                    index = i
            elif alignment == Qt.AlignTop:
                if amount is None or rect.y() < amount:
                    amount = rect.y()
                    index = i
            elif alignment == Qt.AlignBottom:
                if amount is None or rect.y() + rect.height() > amount:
                    amount = rect.y() + rect.height()
                    index = i
            elif alignment == Qt.AlignVCenter:
                if amount is None or rect.height() > amount:
                    amount = rect.height()
                    index = i
        rect = items[index].sceneBoundingRect()
        
        # step 3: move the other items
        for i, item in enumerate(items):
            if i == index:
                continue
            itemrect = item.sceneBoundingRect()
            xOffset = yOffset = 0
            if alignment == Qt.AlignLeft:
                xOffset = rect.x() - itemrect.x()
            elif alignment == Qt.AlignRight:
                xOffset = (rect.x() + rect.width()) - \
                          (itemrect.x() + itemrect.width())
            elif alignment == Qt.AlignHCenter:
                xOffset = (rect.x() + rect.width() // 2) - \
                          (itemrect.x() + itemrect.width() // 2)
            elif alignment == Qt.AlignTop:
                yOffset = rect.y() - itemrect.y()
            elif alignment == Qt.AlignBottom:
                yOffset = (rect.y() + rect.height()) - \
                          (itemrect.y() + itemrect.height())
            elif alignment == Qt.AlignVCenter:
                yOffset = (rect.y() + rect.height() // 2) - \
                          (itemrect.y() + itemrect.height() // 2)
            item.moveBy(xOffset, yOffset)
        
        self.scene().update()
    
    def __itemsBoundingRect(self, items):
        """
        Private method to calculate the bounding rectangle of the given items.
        
        @param items list of items to operate on (list of UMLItem)
        @return bounding rectangle (QRectF)
        """
        rect = self.scene().sceneRect()
        right = rect.left()
        bottom = rect.top()
        left = rect.right()
        top = rect.bottom()
        for item in items:
            rect = item.sceneBoundingRect()
            left = min(rect.left(), left)
            right = max(rect.right(), right)
            top = min(rect.top(), top)
            bottom = max(rect.bottom(), bottom)
        return QRectF(left, top, right - left, bottom - top)
    
    def keyPressEvent(self, evt):
        """
        Protected method handling key press events.
        
        @param evt reference to the key event (QKeyEvent)
        """
        key = evt.key()
        if key in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]:
            items = self.filteredItems(self.scene().selectedItems())
            if items:
                if evt.modifiers() & Qt.ControlModifier:
                    stepSize = 50
                else:
                    stepSize = 5
                if key == Qt.Key_Up:
                    dx = 0
                    dy = -stepSize
                elif key == Qt.Key_Down:
                    dx = 0
                    dy = stepSize
                elif key == Qt.Key_Left:
                    dx = -stepSize
                    dy = 0
                else:
                    dx = stepSize
                    dy = 0
                for item in items:
                    item.moveBy(dx, dy)
                evt.accept()
                return
        
        super(UMLGraphicsView, self).keyPressEvent(evt)
    
    def wheelEvent(self, evt):
        """
        Protected method to handle wheel events.
        
        @param evt reference to the wheel event (QWheelEvent)
        """
        if evt.modifiers() & Qt.ControlModifier:
            if qVersion() >= "5.0.0":
                delta = evt.angleDelta().y()
            else:
                delta = evt.delta()
            if delta < 0:
                self.zoomOut()
            else:
                self.zoomIn()
            evt.accept()
            return
        
        super(UMLGraphicsView, self).wheelEvent(evt)
    
    def event(self, evt):
        """
        Public method handling events.
        
        @param evt reference to the event (QEvent)
        @return flag indicating, if the event was handled (boolean)
        """
        if evt.type() == QEvent.Gesture:
            self.gestureEvent(evt)
            return True
        
        return super(UMLGraphicsView, self).event(evt)
    
    def gestureEvent(self, evt):
        """
        Protected method handling gesture events.
        
        @param evt reference to the gesture event (QGestureEvent
        """
        pinch = evt.gesture(Qt.PinchGesture)
        if pinch:
            if pinch.state() == Qt.GestureStarted:
                pinch.setScaleFactor(self.zoom() / 100.0)
            else:
                self.setZoom(int(pinch.scaleFactor() * 100))
            evt.accept()
    
    def getItemId(self):
        """
        Public method to get the ID to be assigned to an item.
        
        @return item ID (integer)
        """
        self.__itemId += 1
        return self.__itemId

    def findItem(self, id):
        """
        Public method to find an UML item based on the ID.
        
        @param id of the item to search for (integer)
        @return item found (UMLItem) or None
        """
        for item in self.scene().items():
            try:
                if item.getId() == id:
                    return item
            except AttributeError:
                continue
        
        return None
    
    def findItemByName(self, name):
        """
        Public method to find an UML item based on its name.
        
        @param name name to look for (string)
        @return item found (UMLItem) or None
        """
        for item in self.scene().items():
            try:
                if item.getName() == name:
                    return item
            except AttributeError:
                continue
        
        return None
    
    def getPersistenceData(self):
        """
        Public method to get a list of data to be persisted.
        
        @return list of data to be persisted (list of strings)
        """
        lines = [
            "diagram_name: {0}".format(self.diagramName),
        ]
        
        for item in self.filteredItems(self.scene().items(), UMLItem):
            lines.append("item: id={0}, x={1}, y={2}, item_type={3}{4}".format(
                item.getId(), item.x(), item.y(), item.getItemType(),
                item.buildItemDataString()))
        
        from .AssociationItem import AssociationItem
        for item in self.filteredItems(self.scene().items(), AssociationItem):
            lines.append("association: {0}".format(
                item.buildAssociationItemDataString()))
        
        return lines
    
    def parsePersistenceData(self, version, data):
        """
        Public method to parse persisted data.
        
        @param version version of the data (string)
        @param data persisted data to be parsed (list of string)
        @return tuple of flag indicating success (boolean) and faulty line
            number (integer)
        """
        umlItems = {}
        
        if not data[0].startswith("diagram_name:"):
            return False, 0
        self.diagramName = data[0].split(": ", 1)[1].strip()
        
        from .ClassItem import ClassItem
        from .ModuleItem import ModuleItem
        from .PackageItem import PackageItem
        from .AssociationItem import AssociationItem
        
        linenum = 0
        for line in data[1:]:
            linenum += 1
            if not line.startswith(("item:", "association:")):
                return False, linenum
            
            key, value = line.split(": ", 1)
            if key == "item":
                id, x, y, itemType, itemData = value.split(", ", 4)
                try:
                    id = int(id.split("=", 1)[1].strip())
                    x = float(x.split("=", 1)[1].strip())
                    y = float(y.split("=", 1)[1].strip())
                    itemType = itemType.split("=", 1)[1].strip()
                    if itemType == ClassItem.ItemType:
                        itm = ClassItem(x=x, y=y, scene=self.scene())
                    elif itemType == ModuleItem.ItemType:
                        itm = ModuleItem(x=x, y=y, scene=self.scene())
                    elif itemType == PackageItem.ItemType:
                        itm = PackageItem(x=x, y=y, scene=self.scene())
                    itm.setId(id)
                    umlItems[id] = itm
                    if not itm.parseItemDataString(version, itemData):
                        return False, linenum
                except ValueError:
                    return False, linenum
            elif key == "association":
                srcId, dstId, assocType, topToBottom = \
                    AssociationItem.parseAssociationItemDataString(
                        value.strip())
                assoc = AssociationItem(umlItems[srcId], umlItems[dstId],
                                        assocType, topToBottom)
                self.scene().addItem(assoc)
        
        return True, -1
예제 #58
0
class AddSeqTool(AbstractPathTool):
    """Summary

    Attributes:
        apply_button (TYPE): Description
        buttons (list): Description
        dialog (TYPE): Description
        highlighter (TYPE): Description
        seq_box (TYPE): Description
        sequence_radio_button_id (dict): Description
        signal_mapper (TYPE): Description
        use_abstract_sequence (bool): Description
        validated_sequence_to_apply (TYPE): Description
    """
    def __init__(self, manager):
        """Summary

        Args:
            manager (TYPE): Description
        """
        AbstractPathTool.__init__(self, manager)
        self.dialog = QDialog()
        self.buttons = []
        self.seq_box = None
        self.sequence_radio_button_id = {}
        self.use_abstract_sequence = True
        self.validated_sequence_to_apply = None
        self.initDialog()

    def __repr__(self):
        """Summary

        Returns:
            TYPE: Description
        """
        return "add_seq_tool"  # first letter should be lowercase

    def methodPrefix(self):
        """Summary

        Returns:
            TYPE: Description
        """
        return "addSeqTool"  # first letter should be lowercase

    def initDialog(self):
        """Creates buttons for each sequence option and add them to the dialog.
        Maps the clicked signal of those buttons to keep track of what sequence
        gets selected.
        """
        ui_dlg = Ui_AddSeqDialog()
        ui_dlg.setupUi(self.dialog)
        self.signal_mapper = QSignalMapper(self)
        # set up the radio buttons
        for i, name in enumerate(['Abstract', 'Custom'] + sorted(sequences.keys())):
            radio_button = QRadioButton(ui_dlg.group_box)
            radio_button.setObjectName(name + "Button")
            radio_button.setText(name)
            self.buttons.append(radio_button)
            ui_dlg.horizontalLayout.addWidget(radio_button)
            self.signal_mapper.setMapping(radio_button, i)
            radio_button.clicked.connect(self.signal_mapper.map)
            if name in sequences:
                self.sequence_radio_button_id[sequences[name]] = i
        self.signal_mapper.mapped.connect(self.sequenceOptionChangedSlot)
        # disable apply until valid option or custom sequence is chosen
        self.apply_button = ui_dlg.custom_button_box.button(QDialogButtonBox.Apply)
        self.apply_button.setEnabled(False)
        # watch sequence textedit box to validate custom sequences
        self.seq_box = ui_dlg.seq_text_edit
        self.seq_box.textChanged.connect(self.validateCustomSequence)
        self.highlighter = DNAHighlighter(self.seq_box)
        # finally, pre-click the first radio button
        self.buttons[0].click()

    def sequenceOptionChangedSlot(self, option_chosen):
        """
        Connects to signal_mapper to receive a signal whenever user selects
        a sequence option.

        Args:
            option_chosen (TYPE): Description
        """
        option_name = self.buttons[option_chosen].text()
        if option_name == 'Abstract':
            self.use_abstract_sequence = True
        elif option_name == 'Custom':
            self.use_abstract_sequence = False
        else:
            self.use_abstract_sequence = False
            user_sequence = sequences.get(option_name, None)
            if self.seq_box.toPlainText() != user_sequence:
                self.seq_box.setText(user_sequence)

    def validateCustomSequence(self):
        """
        Called when user changes sequence (seq_box emits textChanged signal)
        If sequence is valid, make the apply_button active to click.
        Select an appropriate sequence option radio button, if necessary.
        """
        user_sequence = self.seq_box.toPlainText()
        # Validate the sequence and activate the button if it checks out.
        if re.search(RE_DNA_PATTERN, user_sequence) is None:
            self.apply_button.setEnabled(True)
        else:
            self.apply_button.setEnabled(False)

        if len(user_sequence) == 0:
            # A zero-length custom sequence defaults to Abstract type.
            if not self.buttons[0].isChecked():
                self.buttons[0].click()
        else:
            # Does this match a known sequence?
            if user_sequence in self.sequence_radio_button_id:
                # Handles case where the user might copy & paste in a known sequence
                i = self.sequence_radio_button_id[user_sequence]
                if not self.buttons[i].isChecked():
                    # Select the corresponding radio button for known sequence
                    self.buttons[i].click()
            else:
                # Unrecognized, Custom type
                if not self.buttons[1].isChecked():
                    self.buttons[1].click()

    def applySequence(self, oligo):
        """Summary

        Args:
            oligo (TYPE): Description

        Returns:
            TYPE: Description
        """
        self.dialog.setFocus()
        if self.dialog.exec_():  # apply the sequence if accept was clicked
            if self.use_abstract_sequence:
                oligo.applySequence(None)
                return (oligo.length(), None)
            else:
                self.validated_sequence_to_apply = self.seq_box.toPlainText().upper()
                oligo.applySequence(self.validated_sequence_to_apply)
                return oligo.length(), len(self.validated_sequence_to_apply)
        return (None, None)
예제 #59
0
    def makePopupMenu(self):
        index = self.currentIndex()
        sel = self.getSelection()
        clipboard = qApp.clipboard()

        menu = QMenu(self)

        # Add / remove items
        self.actAddFolder = QAction(QIcon.fromTheme("folder-new"), qApp.translate("outlineBasics", "New Folder"), menu)
        self.actAddFolder.triggered.connect(self.addFolder)
        menu.addAction(self.actAddFolder)

        self.actAddText = QAction(QIcon.fromTheme("document-new"), qApp.translate("outlineBasics", "New Text"), menu)
        self.actAddText.triggered.connect(self.addText)
        menu.addAction(self.actAddText)

        self.actDelete = QAction(QIcon.fromTheme("edit-delete"), qApp.translate("outlineBasics", "Delete"), menu)
        self.actDelete.triggered.connect(self.delete)
        menu.addAction(self.actDelete)

        menu.addSeparator()

        # Copy, cut, paste
        self.actCopy = QAction(QIcon.fromTheme("edit-copy"), qApp.translate("outlineBasics", "Copy"), menu)
        self.actCopy.triggered.connect(self.copy)
        menu.addAction(self.actCopy)

        self.actCut = QAction(QIcon.fromTheme("edit-cut"), qApp.translate("outlineBasics", "Cut"), menu)
        self.actCut.triggered.connect(self.cut)
        menu.addAction(self.actCut)

        self.actPaste = QAction(QIcon.fromTheme("edit-paste"), qApp.translate("outlineBasics", "Paste"), menu)
        self.actPaste.triggered.connect(self.paste)
        menu.addAction(self.actPaste)

        menu.addSeparator()

        # POV
        self.menuPOV = QMenu(qApp.translate("outlineBasics", "Set POV"), menu)
        mw = mainWindow()
        a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuPOV)
        a.triggered.connect(lambda: self.setPOV(""))
        self.menuPOV.addAction(a)
        self.menuPOV.addSeparator()

        menus = []
        for i in [self.tr("Main"), self.tr("Secondary"), self.tr("Minor")]:
            m = QMenu(i, self.menuPOV)
            menus.append(m)
            self.menuPOV.addMenu(m)

        mpr = QSignalMapper(self.menuPOV)
        for i in range(mw.mdlPersos.rowCount()):
            a = QAction(mw.mdlPersos.icon(i), mw.mdlPersos.name(i), self.menuPOV)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, int(mw.mdlPersos.ID(i)))

            imp = toInt(mw.mdlPersos.importance(i))

            menus[2 - imp].addAction(a)

        mpr.mapped.connect(self.setPOV)
        menu.addMenu(self.menuPOV)

        # Status
        self.menuStatus = QMenu(qApp.translate("outlineBasics", "Set Status"), menu)
        # a = QAction(QIcon.fromTheme("dialog-no"), qApp.translate("outlineBasics", "None"), self.menuStatus)
        # a.triggered.connect(lambda: self.setStatus(""))
        # self.menuStatus.addAction(a)
        # self.menuStatus.addSeparator()

        mpr = QSignalMapper(self.menuStatus)
        for i in range(mw.mdlStatus.rowCount()):
            a = QAction(mw.mdlStatus.item(i, 0).text(), self.menuStatus)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuStatus.addAction(a)
        mpr.mapped.connect(self.setStatus)
        menu.addMenu(self.menuStatus)

        # Labels
        self.menuLabel = QMenu(qApp.translate("outlineBasics", "Set Label"), menu)
        mpr = QSignalMapper(self.menuLabel)
        for i in range(mw.mdlLabels.rowCount()):
            a = QAction(mw.mdlLabels.item(i, 0).icon(),
                        mw.mdlLabels.item(i, 0).text(),
                        self.menuLabel)
            a.triggered.connect(mpr.map)
            mpr.setMapping(a, i)
            self.menuLabel.addAction(a)
        mpr.mapped.connect(self.setLabel)
        menu.addMenu(self.menuLabel)

        if len(sel) > 0 and index.isValid() and not index.internalPointer().isFolder() \
                or not clipboard.mimeData().hasFormat("application/xml"):
            self.actPaste.setEnabled(False)

        if len(sel) > 0 and index.isValid() and not index.internalPointer().isFolder():
            self.actAddFolder.setEnabled(False)
            self.actAddText.setEnabled(False)

        if len(sel) == 0:
            self.actCopy.setEnabled(False)
            self.actCut.setEnabled(False)
            self.actDelete.setEnabled(False)
            self.menuPOV.setEnabled(False)
            self.menuStatus.setEnabled(False)
            self.menuLabel.setEnabled(False)

        return menu