Ejemplo n.º 1
0
    def initUI(self):
        # 添加打开菜单
        openFile = QAction(QIcon('open.png'), 'Open', self)
        openFile.setShortcut('Ctrl+O')
        openFile.setStatusTip('Open new File')
        openFile.triggered.connect(self.openFile)
        openFile.setIcon(QIcon('import.ico'))

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(openFile)

        toolBar = self.addToolBar("File")
        toolBar.addAction(openFile)

        # 设置PlotWidget
        self.dataPlot.plotItem.showGrid(True, True, 0.5)
        pen = pyqtgraph.mkPen(color='b')
        self.dataPlotRange.setMouseEnabled(x=False,
                                           y=False)  # dataPlotRange 不能移动
        self.dataPlot.setAutoVisible(y=True)

        # 设置treeWidget的相关
        self.treeWidget.setColumnCount(4)
        self.treeWidget.setHeaderLabels(
            ['#', 'File Name', 'Corrective Name', 'Unit'])
        self.treeWidget.setColumnWidth(0, 30)
        self.treeWidget.setColumnWidth(1, 100)
        self.treeWidget.setColumnWidth(2, 200)
 def create_context_menu(self):
     self.setContextMenuPolicy(Qt.ActionsContextMenu)
     self.assign_original_index_action = QAction('Lock old series index',
                                                 self)
     self.assign_original_index_action.setIcon(get_icon('images/lock.png'))
     self.assign_original_index_action.triggered.connect(
         self.parent().assign_original_index)
     self.addAction(self.assign_original_index_action)
     self.assign_index_action = QAction('Lock series index...', self)
     self.assign_index_action.setIcon(get_icon('images/lock.png'))
     self.assign_index_action.triggered.connect(self.parent().assign_index)
     self.addAction(self.assign_index_action)
     self.clear_index_action = QAction('Unlock series index', self)
     self.clear_index_action.setIcon(get_icon('images/lock_delete.png'))
     self.clear_index_action.triggered.connect(
         partial(self.parent().clear_index, all_rows=False))
     self.addAction(self.clear_index_action)
     self.clear_all_index_action = QAction('Unlock all series index', self)
     self.clear_all_index_action.setIcon(get_icon('images/lock_open.png'))
     self.clear_all_index_action.triggered.connect(
         partial(self.parent().clear_index, all_rows=True))
     self.addAction(self.clear_all_index_action)
     sep1 = QAction(self)
     sep1.setSeparator(True)
     self.addAction(sep1)
     self.add_empty_action = QAction('Add empty books...', self)
     self.add_empty_action.setIcon(get_icon('add_book.png'))
     self.add_empty_action.triggered.connect(self.parent().add_empty_book)
     self.addAction(self.add_empty_action)
     sep2 = QAction(self)
     sep2.setSeparator(True)
     self.addAction(sep2)
     for name in [
             'PubDate', 'Original Series Index', 'Original Series Name'
     ]:
         sort_action = QAction('Sort by ' + name, self)
         sort_action.setIcon(get_icon('images/sort.png'))
         sort_action.triggered.connect(partial(self.parent().sort_by, name))
         self.addAction(sort_action)
     sep3 = QAction(self)
     sep3.setSeparator(True)
     self.addAction(sep3)
     for name, icon in [('FantasticFiction', 'images/ms_ff.png'),
                        ('Goodreads', 'images/ms_goodreads.png'),
                        ('Google', 'images/ms_google.png'),
                        ('Wikipedia', 'images/ms_wikipedia.png')]:
         menu_action = QAction('Search %s' % name, self)
         menu_action.setIcon(get_icon(icon))
         menu_action.triggered.connect(
             partial(self.parent().search_web, name))
         self.addAction(menu_action)
Ejemplo n.º 3
0
    def contextMenuEvent(self, e):
        if self.selectionModel().selection().indexes():
            for i in self.selectionModel().selection().indexes():
                row, column = i.row(), i.column()
            player_name = self.window.listWidget.selectedItems()[0].text()
            menu = QMenu(self)

            op_action = QAction("Op", self.window)
            op_action.setIcon(self.get_icon('head.png'))
            menu.addAction(op_action)

            deop_action = QAction('De-Op', self)
            deop_action.setIcon(self.get_icon('head.png'))
            menu.addAction(deop_action)

            kick_action = QAction("Kick", self)
            kick_action.setIcon(self.get_icon('head.png'))
            menu.addAction(kick_action)

            ban_action = QAction("Ban", self)
            ban_action.setIcon(self.get_icon('head.png'))
            menu.addAction(ban_action)

            gamemode = menu.addMenu('Gamemode')
            gamemode.setIcon(self.get_icon('head.png'))
            gamemode.addAction('Creative')
            gamemode.addAction('Survival')
            gamemode.addAction('Adventure')

            action = menu.exec_(self.mapToGlobal(e.pos()))
            if action is None:
                return
            action = action.text()
            if "Kick" in action or "Ban" in action:
                for index, player in enumerate(self.players):
                    if player['name'] == player_name:
                        self.remove_player_by_index(index)
                if "Kick" in action:
                    self.window.execute_input("kick %s" % player_name)
                else:
                    self.window.execute_input("ban %s" % player_name)

                self.window.update_players()
            elif "Op" == action:
                self.window.execute_input("op %s" % player_name)
                ##TODO Update players op dict value maybe?
            elif "De-Op" in action:
                self.window.execute_input("deop %s" % player_name)
            elif "Survival" in action:
                self.window.execute_input("gamemode survival %s" % player_name)
            elif "Creative" in action:
                self.window.execute_input("gamemode creative %s" % player_name)
            elif "Adventure" in action:
                self.window.execute_input("gamemode adventure %s" %
                                          player_name)
Ejemplo n.º 4
0
    def initUI(self):
        # 添加打开菜单
        openFile = QAction(QIcon('open.png'), 'Open', self)
        openFile.setShortcut('Ctrl+O')
        openFile.setStatusTip('Open new File')
        openFile.triggered.connect(self.openFile)
        openFile.setIcon(QIcon('import.ico'))

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(openFile)

        toolBar = self.addToolBar("File")
        toolBar.addAction(openFile)

        # 设置PlotWidget
        self.dataPlot.plotItem.showGrid(True, True, 0.5)
        self.dataPlotRange.setMouseEnabled(x=False,
                                           y=False)  # dataPlotRange 不能移动
        self.dataPlot.setAutoVisible(y=True)

        # 设置treeWidget的相关
        self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeWidget.customContextMenuRequested.connect(
            self.showContextMenu)
        self.treeWidget.treeContextMenu = QMenu(self)
        self.actionA = self.treeWidget.treeContextMenu.addAction(u'Plot')
        self.actionA.triggered.connect(lambda: self.chartPlot(
            self.treeWidget.currentItem(), self.treeWidget.selectedItems()))

        self.treeWidget.setColumnCount(4)
        self.treeWidget.setHeaderLabels(
            ['#', 'File Name', 'Corrective Name', 'Unit'])
        self.treeWidget.setColumnWidth(0, 30)
        self.treeWidget.setColumnWidth(1, 100)
        self.treeWidget.setColumnWidth(2, 200)
Ejemplo n.º 5
0
    def _aboutToShowTabsMenu(self):
        self._menuTabs.clear()

        for idx in range(self.count()):
            tab = self._weTab(idx)
            if not tab or tab.isPinned():
                continue

            action = QAction(self)
            action.setIcon(tab.icon())

            if idx == self.currentIndex():
                f = action.font()
                f.setBold(True)
                action.setFont(f)

            title = tab.title()
            title.replace('&', '&&')
            action.setText(gVar.appTools.truncatedText(title, 40))

            # TODO: QVariant::fromValue(qobject_cast<QWidget*>(tab)
            action.setData(tab)
            action.triggered.connect(self._actionChangeIndex)
            self._menuTabs.addAction(action)
class SortColumnListWidget(ColumnListWidget):
    def __init__(self, parent, gui):
        ColumnListWidget.__init__(self, parent, gui)
        self.create_context_menu()
        self.itemChanged.connect(self.set_sort_icon)
        self.itemSelectionChanged.connect(self.item_selection_changed)

    def create_context_menu(self):
        self.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.sort_ascending_action = QAction('Sort ascending', self)
        self.sort_ascending_action.setIcon(get_icon('images/sort_asc.png'))
        self.sort_ascending_action.triggered.connect(
            partial(self.change_sort, 0))
        self.addAction(self.sort_ascending_action)
        self.sort_descending_action = QAction('Sort descending', self)
        self.sort_descending_action.setIcon(get_icon('images/sort_desc.png'))
        self.sort_descending_action.triggered.connect(
            partial(self.change_sort, 1))
        self.addAction(self.sort_descending_action)

    def populate(self, columns, all_columns):
        self.blockSignals(True)
        all_columns = [colname for colname, _width in all_columns]
        self.clear()
        for col, asc in columns:
            if col in all_columns:
                all_columns.remove(col)
                self.populate_column(col, asc, is_checked=True)
        if len(all_columns) > 0:
            for col in all_columns:
                self.populate_column(col, 0, is_checked=False)
        self.blockSignals(False)

    def populate_column(self, col, asc, is_checked):
        item = QListWidgetItem(self.gui.library_view.model().headers[col],
                               self)
        item.setData(Qt.UserRole, col + '|' + str(asc))
        flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
        item.setFlags(flags)
        item.setCheckState(Qt.Checked if is_checked else Qt.Unchecked)
        self.set_sort_icon(item)

    def set_sort_icon(self, item):
        previous = self.blockSignals(True)
        if item.checkState() == Qt.Checked:
            data = convert_qvariant(item.data(Qt.UserRole)).strip()
            asc = int(data.rpartition('|')[2])
            if asc == 0:
                item.setIcon(get_icon('images/sort_asc.png'))
            else:
                item.setIcon(get_icon('images/sort_desc.png'))
        else:
            item.setIcon(QIcon())
        self.item_selection_changed(
        )  ## otherwise asc/desc can be disabled if selected, then checked.
        self.blockSignals(previous)

    def item_selection_changed(self):
        self.sort_ascending_action.setEnabled(False)
        self.sort_descending_action.setEnabled(False)
        item = self.currentItem()
        if item and item.checkState() == Qt.Checked:
            self.sort_ascending_action.setEnabled(True)
            self.sort_descending_action.setEnabled(True)

    def change_sort(self, asc):
        item = self.currentItem()
        if item:
            self.blockSignals(True)
            data = convert_qvariant(item.data(Qt.UserRole)).strip().split('|')
            col = data[0]
            item.setData(Qt.UserRole, col + '|' + str(asc))
            self.set_sort_icon(item)
            self.blockSignals(False)

    def get_data(self):
        cols = []
        for idx in range(self.count()):
            item = self.item(idx)
            data = convert_qvariant(item.data(Qt.UserRole)).strip().split('|')
            if item.checkState() == Qt.Checked:
                cols.append((data[0], int(data[1])))
        return cols
Ejemplo n.º 7
0
    def __init__(self, astergui, parent=None):
        """
        Create panel.

        Arguments:
            astergui (AsterGui): AsterGui instance.
            parent (Optional[QWidget]): Parent widget.
        """
        super(ParameterPanel,
              self).__init__(parent=parent,
                             name=translate("ParameterPanel", "Edit command"),
                             astergui=astergui)
        self.setPixmap(load_pixmap("as_pic_edit_command.png"))

        self._files_model = astergui.study().dataFilesModel()
        self._unit_model = None

        self._command = None
        self.title = ParameterTitle(self)
        self.title.installEventFilter(self)
        self._name = QLineEdit(self)
        self.views = QStackedWidget(self)
        v_layout = QVBoxLayout(self)
        v_layout.setContentsMargins(0, 0, 0, 0)
        v_layout.setSpacing(5)
        v_layout.addWidget(self.title)
        v_layout.addWidget(HLine(self))

        n_layout = QHBoxLayout()
        v_layout.addLayout(n_layout)
        n_layout.addWidget(QLabel(translate("ParameterPanel", "Name"), self))
        n_layout.addWidget(self._name)
        # force to be a valid identifier + length <= 8
        self._name.setValidator(QRegExpValidator(QRegExp(r"[a-zA-Z]\w{1,7}")))

        # create toolbar
        tbar = QToolBar(self)
        tbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
        # - Edit comment
        edit_comment = QAction(translate("AsterStudy", "Edit &Comment"), self)
        edit_comment.setToolTip(translate("AsterStudy", "Edit comment"))
        edit_comment.setStatusTip(
            translate("AsterStudy", "Edit comment for the "
                      "selected object"))
        edit_comment.setIcon(load_icon("as_pic_edit_comment.png"))
        connect(edit_comment.triggered, self._editComment)
        tbar.addAction(edit_comment)
        # - Switch on/off business-translations
        title = translate("AsterStudy", "Use Business-Oriented Translations")
        self.use_translations = QAction(title, self)
        title = translate("AsterStudy", "Use business-oriented translations")
        self.use_translations.setToolTip(title)
        self.use_translations.setStatusTip(title)
        self.use_translations.setIcon(load_icon("as_pic_use_translations.png"))
        self.use_translations.setCheckable(True)
        if behavior().forced_native_names:
            force = behavior().force_native_names
            self.use_translations.setDisabled(True)
            is_on = not force
        else:
            is_on = behavior().use_business_translations
        Options.use_translations = is_on
        self.use_translations.setChecked(is_on)
        connect(self.use_translations.toggled, self.updateTranslations)
        tbar.addAction(self.use_translations)
        # - Hide unused
        hide_unused = astergui.action(ActionType.HideUnused)
        connect(hide_unused.toggled, self._unusedVisibility)
        tbar.addAction(hide_unused)
        # - What's this
        whats_this = QWhatsThis.createAction(tbar)
        whats_this.setToolTip(translate("AsterStudy", "What's this?"))
        whats_this.setStatusTip(
            translate("AsterStudy", "Show element's description"))
        whats_this.setIcon(load_icon("as_pic_whats_this.png"))
        tbar.addAction(whats_this)
        # - Link to doc
        tbar.addAction(astergui.action(ActionType.LinkToDoc))

        n_layout.addWidget(tbar)

        v_layout.addWidget(self.views)
        self._updateState()
Ejemplo n.º 8
0
class ParameterPanel(EditionWidget, WidgetController):
    """Edition Panel implementation."""
    def __init__(self, astergui, parent=None):
        """
        Create panel.

        Arguments:
            astergui (AsterGui): AsterGui instance.
            parent (Optional[QWidget]): Parent widget.
        """
        super(ParameterPanel,
              self).__init__(parent=parent,
                             name=translate("ParameterPanel", "Edit command"),
                             astergui=astergui)
        self.setPixmap(load_pixmap("as_pic_edit_command.png"))

        self._files_model = astergui.study().dataFilesModel()
        self._unit_model = None

        self._command = None
        self.title = ParameterTitle(self)
        self.title.installEventFilter(self)
        self._name = QLineEdit(self)
        self.views = QStackedWidget(self)
        v_layout = QVBoxLayout(self)
        v_layout.setContentsMargins(0, 0, 0, 0)
        v_layout.setSpacing(5)
        v_layout.addWidget(self.title)
        v_layout.addWidget(HLine(self))

        n_layout = QHBoxLayout()
        v_layout.addLayout(n_layout)
        n_layout.addWidget(QLabel(translate("ParameterPanel", "Name"), self))
        n_layout.addWidget(self._name)
        # force to be a valid identifier + length <= 8
        self._name.setValidator(QRegExpValidator(QRegExp(r"[a-zA-Z]\w{1,7}")))

        # create toolbar
        tbar = QToolBar(self)
        tbar.setToolButtonStyle(Qt.ToolButtonIconOnly)
        # - Edit comment
        edit_comment = QAction(translate("AsterStudy", "Edit &Comment"), self)
        edit_comment.setToolTip(translate("AsterStudy", "Edit comment"))
        edit_comment.setStatusTip(
            translate("AsterStudy", "Edit comment for the "
                      "selected object"))
        edit_comment.setIcon(load_icon("as_pic_edit_comment.png"))
        connect(edit_comment.triggered, self._editComment)
        tbar.addAction(edit_comment)
        # - Switch on/off business-translations
        title = translate("AsterStudy", "Use Business-Oriented Translations")
        self.use_translations = QAction(title, self)
        title = translate("AsterStudy", "Use business-oriented translations")
        self.use_translations.setToolTip(title)
        self.use_translations.setStatusTip(title)
        self.use_translations.setIcon(load_icon("as_pic_use_translations.png"))
        self.use_translations.setCheckable(True)
        if behavior().forced_native_names:
            force = behavior().force_native_names
            self.use_translations.setDisabled(True)
            is_on = not force
        else:
            is_on = behavior().use_business_translations
        Options.use_translations = is_on
        self.use_translations.setChecked(is_on)
        connect(self.use_translations.toggled, self.updateTranslations)
        tbar.addAction(self.use_translations)
        # - Hide unused
        hide_unused = astergui.action(ActionType.HideUnused)
        connect(hide_unused.toggled, self._unusedVisibility)
        tbar.addAction(hide_unused)
        # - What's this
        whats_this = QWhatsThis.createAction(tbar)
        whats_this.setToolTip(translate("AsterStudy", "What's this?"))
        whats_this.setStatusTip(
            translate("AsterStudy", "Show element's description"))
        whats_this.setIcon(load_icon("as_pic_whats_this.png"))
        tbar.addAction(whats_this)
        # - Link to doc
        tbar.addAction(astergui.action(ActionType.LinkToDoc))

        n_layout.addWidget(tbar)

        v_layout.addWidget(self.views)
        self._updateState()

    def unitModel(self):
        """
        Method that get unit model.

        Returns:
            UnitModel: Unit model.
        """
        return self._unit_model

    def command(self):
        """
        Get command being edited.

        Returns:
            Command: Command being edited.
        """
        return self._command

    def setCommand(self, command):
        """
        Set command to edit.

        Arguments:
            command (Command): Command to edit.
        """
        self.clear()
        self._command = command
        if self._command is None:
            self._name.setText("")
        else:
            self._name.setText(self._command.name)
            self._unit_model = UnitModel(command.stage)
            pview = self._createParameterView(ParameterPath(self._command), '')
            pview.view().setItemValue(command.storage)
            hide_unused = self.astergui().action(ActionType.HideUnused)
            pview.setUnusedVisibile(not hide_unused.isChecked())
            self.views.setCurrentWidget(pview)
        self._updateState()

    def currentPath(self):
        """
        Get currently edited parameter path.

        Returns:
            str: currently edited parameter path.
        """
        path = ""
        wid = self.currentParameterView()
        if wid is not None:
            path = wid.path()
        return path

    def isCurrentCommand(self):
        """
        Get true if the currently edited view contains command.

        Returns:
            bool: Current edited command flag
        """
        curpath = self.currentPath()
        return ParameterPath(self.command()).isEqual(curpath)

    def currentParameterView(self):
        """
        Get current parameter view.

        Returns:
           ParameterView: current view.
        """
        return self.views.currentWidget()

    def clear(self):
        """Remove all parameter views."""
        while self.views.count() > 0:
            wid = self.views.widget(0)
            if wid is not None:
                self.views.removeWidget(wid)
                wid.deleteLater()

    def store(self):
        """
        Save data from all parameter views.
        """
        cmd = self.command()
        if cmd is not None:
            with auto_dupl_on(self.astergui().study().activeCase):
                cmd.rename(self._name.text())
                wid = self._viewByPath(ParameterPath(cmd))
                if wid is not None:
                    cmd.init(wid.view().itemValue())

    def requiredButtons(self):
        """
        Return the combination of standard button flags required for this
        widget.

        Returns:
            int: button flags for buttons required for this widget
                 (combination of QDialogButtonBox.StandardButton flags).
        """
        if self.isCurrentCommand():
            return QDialogButtonBox.Ok | QDialogButtonBox.Apply | \
                QDialogButtonBox.Close
        else:
            return QDialogButtonBox.Ok | QDialogButtonBox.Cancel | \
                QDialogButtonBox.Abort

    def isButtonEnabled(self, button):
        """
        Return True if a particular button is enabled.

        Arguments:
            button (QDialogButtonBox.StandardButton): button flag.

        Returns:
            True: that means that all buttons should be enabled.
        """
        return True

    def perform(self, button):
        """
        Perform action on button click. Redefined method from the base class.

        Arguments:
            button (QDialogButtonBox.StandardButton): clicked button flag.
        """
        if button == QDialogButtonBox.Ok:
            self.performOk()
        elif button == QDialogButtonBox.Apply:
            self.performApply()
        elif button == QDialogButtonBox.Abort:
            self.performAbort()
        elif button == QDialogButtonBox.Close or \
                button == QDialogButtonBox.Cancel:
            self.performClose()

    def performOk(self):
        """Called when `Ok` button is clicked in Edition panel."""
        self.performChanges(True)

    def performApply(self):
        """Called when `Apply` button is clicked in Edition panel."""
        self.performChanges(False)

    def performAbort(self):
        """Called when `Abort` button is clicked in Edition panel."""
        pref_mgr = self.astergui().preferencesMgr()
        msg = translate(
            "ParameterPanel", "Command edition will be aborted and "
            "all made changes will be lost. "
            "Do you want to continue?")
        noshow = "parampanel_abort"
        ask = MessageBox.question(self.astergui().mainWindow(),
                                  translate("ParameterPanel", "Abort"),
                                  msg,
                                  QMessageBox.Yes | QMessageBox.No,
                                  QMessageBox.Yes,
                                  noshow=noshow,
                                  prefmgr=pref_mgr)
        if ask == QMessageBox.Yes:
            self.close()
            self.astergui().study().revert()

    def performClose(self):
        """Called when `Cancel` button is clicked in Edition panel."""
        has_modif = self._hasModifications()
        if has_modif:
            pref_mgr = self.astergui().preferencesMgr()
            msg = translate(
                "ParameterPanel",
                "There are some unsaved modifications will be "
                "lost. Do you want to continue?")
            noshow = "parampanel_close"
            ask = MessageBox.question(self.astergui().mainWindow(),
                                      translate("ParameterPanel", "Close"),
                                      msg,
                                      QMessageBox.Yes | QMessageBox.No,
                                      QMessageBox.Yes,
                                      noshow=noshow,
                                      prefmgr=pref_mgr)
            has_modif = ask != QMessageBox.Yes

        if not has_modif:
            self.performDissmis(True)

    def performChanges(self, close=True):
        """
        Validate and store the command into data model.
        """
        wid = self.currentParameterView()
        if wid is not None:
            view = wid.view()
            if view.validate():
                cur_path = self.currentPath()
                if self.isCurrentCommand():
                    self.store()
                    self._files_model.update()
                    if self.astergui() is not None:
                        opname = translate("ParameterPanel", "Edit command")
                        self.astergui().study().commit(opname)
                        self.astergui().update()
                    if close:
                        self.performDissmis(False)
                    msg = translate("ParameterPanel",
                                    "Command '{}' successfully stored")
                    msg = msg.format(self._name.text())
                    self.astergui().showMessage(msg)
                else:
                    child_val = view.itemValue()
                    self._removeCurrentView()
                    curview = self.currentParameterView()
                    subitem = curview.view().findItemByPath(cur_path)
                    if subitem is not None:
                        subitem.setItemValue(child_val)
        self._updateState()
        self.updateButtonStatus()

    def performDissmis(self, revert=True):
        """
        Cancel changes and revert the command changes.
        """
        if self.isCurrentCommand():
            self.close()
            if revert:
                self.astergui().study().revert()
        else:
            self._removeCurrentView()
        self._updateState()
        self.updateButtonStatus()

    def showEvent(self, event):
        """
        Reimplemented for internal reason: updates the title
        depending on read only state, etc.
        """
        title = translate("ParameterPanel", "View command") \
            if self.isReadOnly() else \
            translate("ParameterPanel", "Edit command")
        self.setWindowTitle(title)

        hide_unused = self.astergui().action(ActionType.HideUnused)
        hide_unused.setVisible(True)
        hide_unused.setChecked(self.isReadOnly())

        # update meshview
        meshes = avail_meshes_in_cmd(self.command())
        for i, mesh in enumerate(meshes):
            filename, meshname = get_cmd_mesh(mesh)
            if filename:
                if i > 0:
                    self.meshview().displayMEDFileName(filename, meshname, 1.0,
                                                       False)
                else:
                    self.meshview().displayMEDFileName(filename, meshname, 1.0,
                                                       True)

        super(ParameterPanel, self).showEvent(event)

    def hideEvent(self, event):
        """
        Reimplemented for internal reason: hides "Hide unused" action.
        """
        hide_unused = self.astergui().action(ActionType.HideUnused)
        hide_unused.setVisible(False)
        super(ParameterPanel, self).hideEvent(event)

    def updateTranslations(self):
        """
        Update translations in GUI elements.
        """
        Options.use_translations = self.use_translations.isChecked()
        self._updateState()
        for i in xrange(self.views.count()):
            view = self.views.widget(i)
            view.updateTranslations()

    def eventFilter(self, receiver, event):
        """
        Event filter; processes clicking ln links in What's This window.
        """
        if receiver == self.title and event.type() == QEvent.WhatsThisClicked:
            QDesktopServices.openUrl(QUrl(event.href()))
        return super(ParameterPanel, self).eventFilter(receiver, event)

    def _hasModifications(self):
        curview = self.currentParameterView().view() \
            if self.currentParameterView() is not None else None
        return curview.hasModifications() \
            if curview is not None else False

    def _updateState(self):
        """Update state and current title label."""
        disabled = self.command() is None
        self.setDisabled(disabled)

        if not disabled:
            disabled = self.command().gettype(ConversionLevel.NoFail) is None
        self._name.setDisabled(disabled)

        txt = []
        pview = self.currentParameterView()
        if pview is not None:
            txt = pview.path().names()

        ppath = None
        txt_list = []
        tooltip = ""
        whats_this = ""
        while len(txt) > 0:
            name = txt.pop(0)
            if ppath is None:
                ppath = ParameterPath(self.command(), name=name)
            else:
                ppath = ppath.absolutePath(name)
            if ppath.isInSequence():
                txt_list.append("[" + name + "]")
            elif get_cata_typeid(ppath.keyword()) in (IDS.simp, IDS.fact):
                # translate keyword
                kwtext = Options.translate_command(ppath.command().title, name)
                txt_list.append(kwtext)
            elif get_cata_typeid(ppath.keyword()) == IDS.command:
                # translate command
                translation = Options.translate_command(name)
                txt_list.append(translation)
                if translation != name:
                    wttext = italic(translation) + " ({})".format(bold(name))
                else:
                    wttext = bold(name)
                tooltip = preformat(wttext)
                url = self.astergui().doc_url(name)
                if url:
                    wttext += "&nbsp;"
                    wttext += href(
                        image(CFG.rcfile("as_pic_help.png"),
                              width=20,
                              height=20), url)
                wttext = preformat(wttext)
                docs = CATA.get_command_docstring(name)
                if docs:
                    wttext += "<hr>"
                    wttext += docs
                whats_this = wttext

        self.title.setTitle(txt_list)
        self.title.setToolTip(tooltip)
        self.title.setWhatsThis(whats_this)

    def _removeCurrentView(self):
        """
        Remove the parameter view for given object.

        Arguments:
            obj (Parameter): Command's parameter.
        """
        curview = self.currentParameterView()
        if curview is not None:
            master = curview.view().masterItem()
            if master is not None and master.slaveItem() == curview.view():
                master.setSlaveItem(None)
            curview.view().setMasterItem(None)
            view = self._parentView(curview)
            if view is not None:
                self.views.setCurrentWidget(view)
                hide_unused = self.astergui().action(ActionType.HideUnused)
                view.setUnusedVisibile(not hide_unused.isChecked())
            self.views.removeWidget(curview)
            curview.deleteLater()
        self._updateState()

    def _viewByPath(self, path):
        view = None
        for i in xrange(self.views.count()):
            the_view = self.views.widget(i)
            if the_view.path().isEqual(path):
                view = the_view
                break
        return view

    def _parentView(self, curview):
        view = None
        path = curview.path()
        while path is not None and view is None:
            path = path.parentPath()
            view = self._viewByPath(path)
        return view

    def _gotoParameter(self, path, link):
        """
        Activate the parameter view for object with given id.

        Arguments:
            uid (int): Object's UID.
        """
        curview = self.currentParameterView()
        act_item = curview.view().findItemByPath(path)
        child_val = None
        wid = self._createParameterView(path, link)
        if act_item is not None:
            child_val = act_item.itemValue()
            act_item.setSlaveItem(wid.view())
        wid.view().setMasterItem(act_item)
        hide_unused = self.astergui().action(ActionType.HideUnused)
        wid.setUnusedVisibile(not hide_unused.isChecked())
        self.views.setCurrentWidget(wid)
        wid.view().setItemValue(child_val)
        self._updateState()
        self.updateButtonStatus()

    def _createParameterView(self, path, link):
        """
        Create parameter view for given object.

        Arguments:
            path (ParameterPath): Path of parameter to edit.

        Returns:
            ParameterWindow: Parameter view for parameter path.
        """
        # pragma pylint: disable=redefined-variable-type
        pview = None
        if link == EditorLink.Table:
            pview = ParameterTableWindow(path, self, self.views)
        elif link == EditorLink.List:
            pview = ParameterListWindow(path, self, self.views)
        elif link == EditorLink.GrMa:
            pview = ParameterMeshGroupWindow(path, self, self.views)
        else:
            pview = ParameterFactWindow(path, self, self.views)
        connect(pview.gotoParameter, self._gotoParameter)
        self.views.addWidget(pview)
        return pview

    def _unusedVisibility(self, ison):
        """
        Invoked when 'Hide unused' button toggled
        """
        curview = self.currentParameterView()
        curview.setUnusedVisibile(not ison)

    def meshview(self):
        """
        Returns the central *MeshView* object
        """
        return self.astergui().workSpace().panels[Panel.View]

    def _editComment(self):
        """
        Invoked when 'Edit comment' button is clicked
        """
        panel = CommentPanel(self.astergui(), owner=self)
        panel.node = self.command()
        self.astergui().workSpace().panel(Panel.Edit).setEditor(panel)

    def pendingStorage(self):
        """
        Dictionnary being filled as this command is edited.
        """
        wid = self._viewByPath(ParameterPath(self.command()))
        if wid is not None:
            return wid.view().itemValue()
        return None
Ejemplo n.º 9
0
    def initUI(self):

        # 添加打开菜单
        selFileAction = QAction('&Open', self)  # QAction(QIcon('open.png'), '&Open', self)
        selFileAction.setShortcut('Ctrl+O')
        selFileAction.setStatusTip('Open new File')
        selFileAction.triggered.connect(self.openFile)     # open data file
        selFileAction.setIcon(QIcon(self.resource_path('import.png')))

        exitAction = QAction('&Exit', self)    #QtGui.QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit the application')
        #exitAction.triggered.connect(QtGui.qApp.quit)
        exitAction.triggered.connect(self.exitAPP)     # exit the application
        exitAction.setIcon(QIcon(self.resource_path('exit.png')))

        clearAction = QAction('Clear', self)   # QtGui.QAction(QIcon('Clear.png'), 'Clear', self)
        clearAction.triggered.connect(self.clearPlotArea)
        clearAction.setIcon(QIcon(self.resource_path('clear.png')))

        addPlotAction = QAction( 'Add a Plot', self)  #QtGui.QAction(QIcon('Addplot.png'), 'Add a Plot', self)
        addPlotAction.triggered.connect(self.addPlotAera)
        addPlotAction.setIcon(QIcon(self.resource_path('addplot.png')))

        removePlotAction = QAction('Remove the Plot', self) # QtGui.QAction(QIcon('Addplot.png'), 'Remove a Plot', self)
        removePlotAction.triggered.connect(self.removeDataPlotWin)
        removePlotAction.setIcon(QIcon(self.resource_path('remvplot.png')))

        viewAllAction = QAction("View All", self)
        viewAllAction.triggered.connect(self.autoRangeAllWins)
        viewAllAction.setIcon(QIcon(self.resource_path('viewall.png')))

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')         # add menu File
        fileMenu.addAction(selFileAction)            # link menu bar to openfile action with a menu item
        fileMenu.addAction(exitAction)               # add menu item exit

        plotMenu = menubar.addMenu("Plot")           # add menu Plot
        plotMenu.addAction(clearAction)               # add menu item of 'Clear' plot
        plotMenu.addAction(addPlotAction)             # add menu item of 'Add a Plot'
        plotMenu.addAction(removePlotAction)          # add menu item of 'Add a Plot'

        helpMenu = menubar.addMenu("Help")  # add menu help
        helpAction = QAction('?', helpMenu)
        helpAction.triggered.connect(self.helpme)
        helpMenu.addAction(helpAction)

        toolBar = self.addToolBar("Open")
        toolBar.addAction(selFileAction)             # link tool bar to openfile action

        toolBar.addAction(clearAction)
        toolBar.addAction(addPlotAction)
        toolBar.addAction(removePlotAction)
        toolBar.addAction(viewAllAction)




        # toolBar = self.addToolBar('Exit')
        # toolBar.addAction(selExitAction)  # link menu bar to openfile action

        # 设置dataPlot  class: PlotWidget
        self.dataPlot.plotItem.showGrid(True, True, 0.5)
        #self.dataPlot.plotItem.addLegend()

        self.dataPlot.setAutoVisible(y=True)


        # 设置treeWidget的相关  class: QTreeWidget
        self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeWidget.customContextMenuRequested.connect(self.showContextMenu)
        self.treeWidget.treeContextMenu = QMenu(self)
        self.actionA = self.treeWidget.treeContextMenu.addAction(u'Plot')
        self.actionA.triggered.connect(
            lambda: self.plotData(self.currSelctPlotWgt, self.treeWidget.selectedItems()))
        self.treeWidget.setColumnCount(4)
        self.treeWidget.setHeaderLabels(['#', 'Parameter', 'Parameter Name', 'Unit'])
        self.treeWidget.setColumnWidth(0, 10)
        self.treeWidget.setColumnWidth(1, 50)
        self.treeWidget.setColumnWidth(2, 100)

        ### drag and drop
        self.treeWidget.setDragDropMode(self.treeWidget.DragOnly)


        # set up context menu of list widget
        self.listWidget.setContextMenuPolicy(Qt.CustomContextMenu)
        self.listWidget.customContextMenuRequested.connect(self.showListContextMenu)
        self.listWidget.listContextMenu = QMenu(self)
        self.actionB = self.listWidget.listContextMenu.addAction(u'Remove')
        self.actionB.triggered.connect(
            lambda: self.removeItemInPlot(self.listWidget.selectedItems()))


        #################### get the test data from the import window
        self.winImpData = clsImportData(self.dataparam, self.lTestDATA)     # instance of the ImportData window

        # # x axis for time
        # xAxis = self.TimeAxisItem("bottom")
        xAxis = self.dataPlot.plotItem.axes['bottom']['item']
        # plotitem and viewbox
        ## at least one plotitem is used whioch holds its own viewbox and left axis
        viewBox = self.dataPlot.plotItem.vb  # reference to viewbox of the plotitem
        viewBox.scaleBy(y=None)

        # # link x axis to view box
        xAxis.linkToView(viewBox)

        self.dataPlot.plotItem.scene().sigMouseMoved.connect(self.mouseMove)
        #self.dataPlot.plotItem.scene().sigMouseClicked.connect(self.mouseClick)

        # self.dataPlot.HoverEnterEvent = self.hoverEnterEvent

        ## drag and drop
        # self.dataPlot.dragEnterEvent = self.dragEnterEvent
        # self.dataPlot.plotItem.setAcceptDrops(True)
        # self.dataPlot.plotItem.dropEvent = self.dropEvent


        vLine = InfiniteLine(angle=90, movable=False, name='vline')
        hLine = InfiniteLine(angle=0, movable=False, name='hline')

        self.dataPlot.addItem(vLine, ignoreBounds=True)
        self.dataPlot.addItem(hLine, ignoreBounds=True)

        # set the default plot range
        self.dataPlot.setXRange(self.minTimestamp,self.maxTimestamp,padding=20)
        self.dataPlot.setYRange(-10, 10, padding=20)

        self.dataPlot.plotItem.getViewBox().setLimits()

        self.dataPlot.plotItem.getAxis('left').setWidth(w=30)
        self.dataPlot.plotItem.hideButtons()


        #self.dataPlot.plotItem.scene().sigMouseLeave.connect(self.mouseLeave) # ##TODO: cleaning house job
        self.dataPlot.installEventFilter(self)

        txtY_value = TextItem("", fill=(0, 0, 255, 80), anchor=(0,1),color='w')
        txtY_value.setParentItem(viewBox)

        self.curLabelofYvalue = txtY_value
        # #self.dataPlot.addItem(self.lableY_value)
        # labelY_value.setPos(self.minTimestamp,100.0)


        self.configPlotArea(self.dataPlot)

        # set current selection plot window background
        self.currSelctPlotWgt = self.dataPlot
        self.currSelctPlotWgt.setBackground(0.95)
Ejemplo n.º 10
0
class ColorPicker(QToolButton):
    """Widget for select a color."""

    select_color = pyqtSignal(str)

    def __init__(self,
                 text=None,
                 color_caption="#F0F0FF",
                 icon="",
                 config=None):
        """
        text - text in caption and tooltip
        icon - filename for icon of button
        list_colors - list colors for select
        """
        QToolButton.__init__(self, None)
        self.setAutoRaise(True)

        self._text = self.tr("Color") if text is None else text
        self._color_caption = color_caption

        # --- list of colors -----------------------------------
        lst = []
        if config:
            lst = [
                c for c in config.get("TextEditor/Colors", "").split(";") if c
            ]

        if not lst:
            lst = [
                "#99cc00", "#e2fbfe", "#fee5e2", "#fa8072", "#f5f7a8",
                "#fef65b", "#ff9a00", "#ff00f4", "#f6f900", "#914285",
                "#c0d6e4", "#f5f5dc", "#3d40a2", "#acd2cd", "#ff9966",
                "#a4c73c", "#ff7373", "#50d4ee", "#8d5959", "#104022",
                "#000000", "#160042", "#6e57d2", "#4c9828", "#444193",
                "#0000ff", "#ff0000", "white", "#AA0000", "#00AA00", "#0040C2",
                "#550000", "#004100", "#BF4040"
            ]
        if config:
            config["TextEditor/Colors"] = ";".join(lst)

        lst.append(color_caption)  # the list must contain a background color
        self._colors = lst
        # ------------------------------------------------------

        self._colors_widget = ColorsWidget(text=self._text,
                                           colors=self._colors,
                                           color_caption=color_caption)
        self._colors_widget.select_color.connect(self.select_color_)
        self._colors_widget.hide_form.connect(self.hide_color_form)
        self._colors_widget.other_color.connect(self.other_color)

        self._action = QAction(self._text, None)
        self._action.setIcon(QIcon(img(icon)))
        self._action.triggered.connect(self.show_form_colors)

        self.setDefaultAction(self._action)

    # -------------------------------------------------------------------------
    def show_form_colors(self):
        self.setCheckable(True)
        self.setChecked(True)
        QApplication.processEvents()
        pos = QPoint(self.rect().left(), self.rect().bottom())
        self._colors_widget.show_form(self.mapToGlobal(pos))

    # -------------------------------------------------------------------------
    def select_color_(self, color):
        self.select_color.emit(color)

    # -------------------------------------------------------------------------
    def _get_color(self):  # pragma: no cover
        """
        The method is made to bypass the program crashes during testing
        in Ubuntu. Tests terminated if QColorDialog used in other_color.

        For use in tests (obj is object of ColorPicker):
          with patch.object(obj, '_get_color', return_value=QColor("blue")):
        """
        return QColorDialog(self).getColor(initial=QColor("black"))

    # -------------------------------------------------------------------------
    def other_color(self):
        color = self._get_color()
        QApplication.processEvents()
        if color.isValid():
            self.select_color.emit(color.name())

    # -------------------------------------------------------------------------
    def hide_color_form(self):
        self.setCheckable(False)

    # -------------------------------------------------------------------------
    def retranslate_ui(self, text):
        self._text = self.tr("Color") if text is None else text
        self._colors_widget.retranslate_ui(self._text)
        self.setToolTip(self._text)
Ejemplo n.º 11
0
class InsertTable(QToolButton):
    """Widget for select a size of table."""

    insert_table = pyqtSignal(dict)

    def __init__(self, text=None, color_caption="#F0F0FF", icon="",
                 config=None):
        """
        text - text in caption and tooltip
        icon - filename for icon of button
        """
        QToolButton.__init__(self, None)
        self.setAutoRaise(True)

        self._cfg = config
        self._text = self.tr("Table") if text is None else text
        self._color_caption = color_caption

        # ------------------------------------------------------

        self._colors_widget = InsertTableWidget(color_caption=color_caption)
        self._colors_widget.select_size.connect(self.select_size_)
        self._colors_widget.hide_form.connect(self.hide_form)
        self._colors_widget.other_size.connect(self.other_size)

        self._action = QAction(self._text, None)
        self._action.setIcon(QIcon(img(icon)))
        self._action.triggered.connect(self.show_form)

        self.setDefaultAction(self._action)

    # -------------------------------------------------------------------------
    def show_form(self):
        self.setCheckable(True)
        self.setChecked(True)
        QApplication.processEvents()
        pos = QPoint(self.rect().left(), self.rect().bottom())
        self._colors_widget.show_form(self.mapToGlobal(pos))

    # -------------------------------------------------------------------------
    def select_size_(self, width, height):
        table_params = {
            "rows": height,
            "cols": width,
            "padding": self._cfg.get('TextEditor/PaddingInTable', 3),
            "space": self._cfg.get('TextEditor/SpaceInTable', 0),
        }
        self.insert_table.emit(table_params)

    # -------------------------------------------------------------------------
    def other_size(self):
        t = TableParamsDlg(self.parent(), self._cfg)
        if t.exec_():
            self.insert_table.emit(t.table_params)

    # -------------------------------------------------------------------------
    def hide_form(self):
        self.setCheckable(False)

    # -------------------------------------------------------------------------
    def retranslate_ui(self, text):
        self._text = self.tr("Table") if text is None else text
        self._colors_widget.retranslate_ui(self._text)
        self.setToolTip(self._text)
Ejemplo n.º 12
0
Archivo: align.py Proyecto: ligm74/LiGM
class AlignText(QToolButton):
    """Widget for select a align of text."""

    # noinspection PyUnresolvedReferences
    select_align = pyqtSignal(Qt.Alignment, QTextCharFormat.VerticalAlignment)

    def __init__(self, text=None, color_caption="#F0F0FF", icon=""):
        """
        text - text in caption and tooltip
        icon - filename for icon of button
        """
        QToolButton.__init__(self, None)
        self.setAutoRaise(True)

        self._text = self.tr("Alignment") if text is None else text
        self._color_caption = color_caption

        # ------------------------------------------------------
        self._colors_widget = AlignTextWidget(color_caption=color_caption)
        self._colors_widget.select_align.connect(self.select_align_)
        self._colors_widget.hide_form.connect(self.hide_form)

        self._action = QAction(self._text, None)
        self._action.setIcon(QIcon(img(icon)))
        self._action.triggered.connect(self.show_form)
        self.setDefaultAction(self._action)

    # -------------------------------------------------------------------------
    def show_form(self):
        self.setCheckable(True)
        self.setChecked(True)
        QApplication.processEvents()
        pos = QPoint(self.rect().left(), self.rect().bottom())
        self._colors_widget.show_form(self.mapToGlobal(pos))

    # -------------------------------------------------------------------------
    def select_align_(self, r, c):
        horiz = {
            1: Qt.AlignLeft,
            2: Qt.AlignCenter,
            3: Qt.AlignRight,
            4: Qt.AlignJustify,
        }
        vert = {
            1: QTextCharFormat.AlignTop,
            2: QTextCharFormat.AlignMiddle,
            3: QTextCharFormat.AlignBottom,
        }
        self.select_align.emit(horiz[c], vert[r])

    # -------------------------------------------------------------------------
    def hide_form(self):
        self.setCheckable(False)

    # -------------------------------------------------------------------------
    def retranslate_ui(self, text):
        self._text = self.tr("Alignment") if text is None else text
        self._colors_widget.retranslate_ui()
        self.setToolTip(self._text)

    # -------------------------------------------------------------------------
    def set_enable_vertical_align(self, value):
        self._colors_widget.set_enable_vertical_align(value)
class SeriesTableWidget(QTableWidget):
    def __init__(self, parent):
        QTableWidget.__init__(self, parent)
        self.create_context_menu()
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setDropIndicatorShown(True)
        self.fmt = tweaks['gui_pubdate_display_format']
        if self.fmt is None:
            self.fmt = 'MMM yyyy'

    def create_context_menu(self):
        self.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.assign_original_index_action = QAction('Lock old series index',
                                                    self)
        self.assign_original_index_action.setIcon(get_icon('images/lock.png'))
        self.assign_original_index_action.triggered.connect(
            self.parent().assign_original_index)
        self.addAction(self.assign_original_index_action)
        self.assign_index_action = QAction('Lock series index...', self)
        self.assign_index_action.setIcon(get_icon('images/lock.png'))
        self.assign_index_action.triggered.connect(self.parent().assign_index)
        self.addAction(self.assign_index_action)
        self.clear_index_action = QAction('Unlock series index', self)
        self.clear_index_action.setIcon(get_icon('images/lock_delete.png'))
        self.clear_index_action.triggered.connect(
            partial(self.parent().clear_index, all_rows=False))
        self.addAction(self.clear_index_action)
        self.clear_all_index_action = QAction('Unlock all series index', self)
        self.clear_all_index_action.setIcon(get_icon('images/lock_open.png'))
        self.clear_all_index_action.triggered.connect(
            partial(self.parent().clear_index, all_rows=True))
        self.addAction(self.clear_all_index_action)
        sep1 = QAction(self)
        sep1.setSeparator(True)
        self.addAction(sep1)
        self.add_empty_action = QAction('Add empty books...', self)
        self.add_empty_action.setIcon(get_icon('add_book.png'))
        self.add_empty_action.triggered.connect(self.parent().add_empty_book)
        self.addAction(self.add_empty_action)
        sep2 = QAction(self)
        sep2.setSeparator(True)
        self.addAction(sep2)
        for name in [
                'PubDate', 'Original Series Index', 'Original Series Name'
        ]:
            sort_action = QAction('Sort by ' + name, self)
            sort_action.setIcon(get_icon('images/sort.png'))
            sort_action.triggered.connect(partial(self.parent().sort_by, name))
            self.addAction(sort_action)
        sep3 = QAction(self)
        sep3.setSeparator(True)
        self.addAction(sep3)
        for name, icon in [('FantasticFiction', 'images/ms_ff.png'),
                           ('Goodreads', 'images/ms_goodreads.png'),
                           ('Google', 'images/ms_google.png'),
                           ('Wikipedia', 'images/ms_wikipedia.png')]:
            menu_action = QAction('Search %s' % name, self)
            menu_action.setIcon(get_icon(icon))
            menu_action.triggered.connect(
                partial(self.parent().search_web, name))
            self.addAction(menu_action)

    def populate_table(self, books):
        self.clear()
        self.setAlternatingRowColors(True)
        self.setRowCount(len(books))
        header_labels = [
            'Title', 'Author(s)', 'PubDate', 'Series', 'New Series'
        ]
        self.setColumnCount(len(header_labels))
        self.setHorizontalHeaderLabels(header_labels)
        self.verticalHeader().setDefaultSectionSize(24)
        self.horizontalHeader().setStretchLastSection(True)

        for row, book in enumerate(books):
            self.populate_table_row(row, book)

        self.resizeColumnToContents(0)
        self.setMinimumColumnWidth(0, 150)
        self.setColumnWidth(1, 100)
        self.resizeColumnToContents(2)
        self.setMinimumColumnWidth(2, 60)
        self.resizeColumnToContents(3)
        self.setMinimumColumnWidth(3, 120)
        self.setSortingEnabled(False)
        self.setMinimumSize(550, 0)
        self.selectRow(0)
        delegate = DateDelegate(self, self.fmt, default_to_today=False)
        self.setItemDelegateForColumn(2, delegate)

    def setMinimumColumnWidth(self, col, minimum):
        if self.columnWidth(col) < minimum:
            self.setColumnWidth(col, minimum)

    def populate_table_row(self, row, book):
        self.blockSignals(True)
        self.setItem(row, 0, TitleWidgetItem(book))
        self.setItem(row, 1, AuthorsTableWidgetItem(book.authors()))
        self.setItem(
            row, 2,
            DateTableWidgetItem(book.pubdate(),
                                is_read_only=False,
                                default_to_today=False,
                                fmt=self.fmt))
        self.setItem(
            row, 3,
            SeriesTableWidgetItem(book.orig_series_name(),
                                  book.orig_series_index(),
                                  is_original=True))
        self.setItem(
            row, 4,
            SeriesTableWidgetItem(book.series_name(),
                                  book.series_index(),
                                  assigned_index=book.assigned_index()))
        self.blockSignals(False)

    def swap_row_widgets(self, src_row, dest_row):
        self.blockSignals(True)
        self.insertRow(dest_row)
        for col in range(self.columnCount()):
            self.setItem(dest_row, col, self.takeItem(src_row, col))
        self.removeRow(src_row)
        self.blockSignals(False)

    def select_and_scroll_to_row(self, row):
        self.selectRow(row)
        self.scrollToItem(self.currentItem())

    def event_has_mods(self, event=None):
        mods = event.modifiers() if event is not None else \
                QApplication.keyboardModifiers()
        return mods & Qt.ControlModifier or mods & Qt.ShiftModifier

    def mousePressEvent(self, event):
        ep = event.pos()
        if self.indexAt(ep) not in self.selectionModel().selectedIndexes() and \
                event.button() == Qt.LeftButton and not self.event_has_mods():
            self.setDragEnabled(False)
        else:
            self.setDragEnabled(True)
        return QTableWidget.mousePressEvent(self, event)

    def dropEvent(self, event):
        rows = self.selectionModel().selectedRows()
        selrows = []
        for row in rows:
            selrows.append(row.row())
        selrows.sort()
        drop_row = self.rowAt(event.pos().y())
        if drop_row == -1:
            drop_row = self.rowCount() - 1
        rows_before_drop = [idx for idx in selrows if idx < drop_row]
        rows_after_drop = [idx for idx in selrows if idx >= drop_row]

        dest_row = drop_row
        for selrow in rows_after_drop:
            dest_row += 1
            self.swap_row_widgets(selrow + 1, dest_row)
            book = self.parent().books.pop(selrow)
            self.parent().books.insert(dest_row, book)

        dest_row = drop_row + 1
        for selrow in reversed(rows_before_drop):
            self.swap_row_widgets(selrow, dest_row)
            book = self.parent().books.pop(selrow)
            self.parent().books.insert(dest_row - 1, book)
            dest_row = dest_row - 1

        event.setDropAction(Qt.CopyAction)
        # Determine the new row selection
        self.selectRow(drop_row)
        self.parent().renumber_series()

    def set_series_column_headers(self, text):
        item = self.horizontalHeaderItem(3)
        if item is not None:
            item.setText('Old ' + text)
        item = self.horizontalHeaderItem(4)
        if item is not None:
            item.setText('New ' + text)