コード例 #1
0
ファイル: qt_notification.py プロジェクト: jojoelfe/napari
            def show_tb(parent):
                tbdialog = QDialog(parent=parent.parent())
                tbdialog.setModal(True)
                # this is about the minimum width to not get rewrap
                # and the minimum height to not have scrollbar
                tbdialog.resize(650, 270)
                tbdialog.setLayout(QVBoxLayout())

                text = QTextEdit()
                theme = get_theme(
                    get_settings().appearance.theme, as_dict=False
                )
                _highlight = Pylighter(  # noqa: F841
                    text.document(), "python", theme.syntax_style
                )
                text.setText(notification.as_text())
                text.setReadOnly(True)
                btn = QPushButton(trans._('Enter Debugger'))

                def _enter_debug_mode():
                    btn.setText(
                        trans._(
                            'Now Debugging. Please quit debugger in console to continue'
                        )
                    )
                    _debug_tb(notification.exception.__traceback__)
                    btn.setText(trans._('Enter Debugger'))

                btn.clicked.connect(_enter_debug_mode)
                tbdialog.layout().addWidget(text)
                tbdialog.layout().addWidget(btn, 0, Qt.AlignRight)
                tbdialog.show()
コード例 #2
0
            def show_tb(parent):
                tbdialog = QDialog(parent=parent.parent())
                tbdialog.setModal(True)
                # this is about the minimum width to not get rewrap
                # and the minimum height to not have scrollbar
                tbdialog.resize(650, 270)
                tbdialog.setLayout(QVBoxLayout())

                text = QTextEdit()
                text.setHtml(notification.as_html())
                text.setReadOnly(True)
                btn = QPushButton('Enter Debugger')

                def _enter_debug_mode():
                    btn.setText(
                        'Now Debugging. Please quit debugger in console '
                        'to continue'
                    )
                    _debug_tb(notification.exception.__traceback__)
                    btn.setText('Enter Debugger')

                btn.clicked.connect(_enter_debug_mode)
                tbdialog.layout().addWidget(text)
                tbdialog.layout().addWidget(btn, 0, Qt.AlignRight)
                tbdialog.show()
コード例 #3
0
ファイル: flow_node.py プロジェクト: hzyrc6011/pmgwidgets
    def on_edit_ports(self):
        from pmgwidgets import PMGPanel
        from qtpy.QtWidgets import QDialog, QVBoxLayout
        dlg = QDialog(self.base_rect.scene().flow_widget)
        sp = PMGPanel()
        p: 'CustomPort' = None
        input_ids, output_ids = [], []
        input_texts, output_texts = [], []
        self._last_var = 0

        def new_id_input():
            node_id = self.id
            max_val = 0
            for p in self.input_ports:
                n, t, p = p.parse_id()
                if max_val < int(p):
                    max_val = int(p)
            self._last_var += 1
            return '%s:input:%d' % (node_id, max_val + self._last_var)

        def new_id_output():
            node_id = self.id
            max_val = 0
            for p in self.output_ports:
                n, t, p = p.parse_id()
                if max_val < int(p):
                    max_val = int(p)
            self._last_var += 1
            return '%s:output:%d' % (node_id, max_val + self._last_var)

        for p in self.input_ports:
            input_ids.append(p.id)
            input_texts.append(p.text)

        for p in self.output_ports:
            output_ids.append(p.id)
            output_texts.append(p.text)

        views = []
        # views += self.content.get_settings_params()
        views += [
            ('line_ctrl', 'text', 'Node Text', self.text),
        ]
        if self.content.ports_changable[0]:
            views.append(('list_ctrl', 'inputs', 'Set Inputs',
                          [input_ids, input_texts], new_id_input))
        if self.content.ports_changable[1]:
            views.append(('list_ctrl', 'outputs', 'Set Outputs',
                          [output_ids, output_texts], new_id_output))
        sp.set_items(views)
        dlg.setLayout(QVBoxLayout())
        dlg.layout().addWidget(sp)
        dlg.exec_()

        dic = sp.get_value()
        self.change_ports_property(dic)
コード例 #4
0
ファイル: flow_items.py プロジェクト: hzyrc6011/pmgwidgets
 def on_value_show_requested(self):
     from qtpy.QtWidgets import QDialog, QVBoxLayout
     val_dlg = QDialog()
     val_dlg.setLayout(QVBoxLayout())
     text_show = QTextEdit()
     text = 'inputs:\n' + repr(
         self.node.content.input_args) + '\n' + 'results:\n' + repr(
             self.node.content.results)
     text_show.setText(text)
     val_dlg.layout().addWidget(text_show)
     val_dlg.exec_()
コード例 #5
0
            def show_tb(parent):
                tbdialog = QDialog(parent=parent.parent())
                tbdialog.setModal(True)
                # this is about the minimum width to not get rewrap
                # and the minimum height to not have scrollbar
                tbdialog.resize(650, 270)
                tbdialog.setLayout(QVBoxLayout())

                text = QTextEdit()
                text.setHtml(notification.as_html())
                text.setReadOnly(True)
                tbdialog.layout().addWidget(text)
                tbdialog.show()
コード例 #6
0
 def verify():
     try:
         text = input_widget.document().toPlainText()
         l = eval(text)
         if isinstance(l, list):
             dialog2 = QDialog(dialog)
             sp2 = PMGPanel(parent=None, views=l)
             dialog2.setLayout(QHBoxLayout())
             dialog2.layout().addWidget(sp2)
             dialog2.layout().addLayout(edit_layout)
             dialog2.exec_()
     except:
         import traceback
         traceback.print_exc()
コード例 #7
0
ファイル: orbit_register.py プロジェクト: lnls-sirius/hla
    def _open_matrix_sel(self):
        wid = QDialog(self)
        wid.setObjectName(self._csorb.acc + 'App')
        wid.setLayout(QVBoxLayout())

        cbbox = QComboBox(wid)
        cbbox.setEditable(True)
        cbbox.setMaxVisibleItems(10)
        corrnames = self._csorb.ch_names + self._csorb.cv_names
        if self._csorb.acc in {'SI', 'BO'}:
            corrnames.append('RF')
        cbbox.addItems(corrnames)
        wid.layout().addWidget(QLabel('Choose the corrector:', wid))
        wid.layout().addWidget(cbbox)

        ledit = QDoubleSpinBoxPlus(wid)
        ledit.setMinimum(float('-inf'))
        ledit.setMaximum(float('inf'))
        ledit.setValue(1.0)
        wid.layout().addWidget(QLabel('Choose the Kick [urad]:', wid))
        wid.layout().addWidget(ledit)
        ledit.valueChanged.connect(_part(self._accept_mat_sel, ledit, cbbox))
        cbbox.currentIndexChanged.connect(
            _part(self._accept_mat_sel, ledit, cbbox))

        hlay = QHBoxLayout()
        cancel = QPushButton('Cancel', wid)
        confirm = QPushButton('Ok', wid)
        cancel.clicked.connect(wid.reject)
        confirm.clicked.connect(wid.accept)
        confirm.clicked.connect(_part(self._accept_mat_sel, ledit, cbbox))
        confirm.setDefault(True)
        hlay.addStretch()
        hlay.addWidget(cancel)
        hlay.addStretch()
        hlay.addWidget(confirm)
        hlay.addStretch()
        wid.layout().addItem(hlay)
        res = wid.exec_()

        if res != QDialog.Accepted:
            self._reset_orbit()
コード例 #8
0
ファイル: widgets.py プロジェクト: slactjohnson/typhos
class SignalDialogButton(QPushButton):
    """QPushButton to launch a QDialog with a PyDMWidget"""
    text = NotImplemented
    icon = NotImplemented
    parent_widget_class = QtWidgets.QWidget

    def __init__(self, init_channel, text=None, icon=None, parent=None):
        self.text = text or self.text
        self.icon = icon or self.icon
        super().__init__(qta.icon(self.icon), self.text, parent=parent)
        self.clicked.connect(self.show_dialog)
        self.dialog = None
        self.channel = init_channel
        self.setIconSize(QSize(15, 15))

    def widget(self, channel):
        """Return a widget created with channel"""
        raise NotImplementedError

    def show_dialog(self):
        """Show the channel in a QDialog"""
        # Dialog Creation
        if not self.dialog:
            logger.debug("Creating QDialog for %r", self.channel)
            # Set up the QDialog
            parent = utils.find_parent_with_class(self,
                                                  self.parent_widget_class)
            self.dialog = QDialog(parent)
            self.dialog.setWindowTitle(self.channel)
            self.dialog.setLayout(QVBoxLayout())
            self.dialog.layout().setContentsMargins(2, 2, 2, 2)
            # Add the widget
            widget = self.widget()
            self.dialog.layout().addWidget(widget)
        # Handle a lost dialog
        else:
            logger.debug("Redisplaying QDialog for %r", self.channel)
            self.dialog.close()
        # Show the dialog
        logger.debug("Showing QDialog for %r", self.channel)
        self.dialog.show()
コード例 #9
0
ファイル: orbit_register.py プロジェクト: lnls-sirius/hla
    def _create_bump(self):
        def _add_entry(index):
            cbox = self.sender()
            text = cbox.itemText(index)
            if not text.startswith('other'):
                return
            win = LoadConfigDialog(self._config_type, self)
            confname, status = win.exec_()
            if not status:
                cbox.setCurrentIndex(0)
                return
            cbox.insertItem(index, confname)
            cbox.setCurrentIndex(index)

        wid = QDialog(self)
        wid.setObjectName(self._csorb.acc + 'App')
        lay = QGridLayout()
        wid.setLayout(lay)

        row = 0
        lay.addWidget(QLabel('Base Orbit ', wid), row, 0)
        orbcombo = QComboBox(wid)
        orbcombo.addItems(['Register', 'ref_orb', 'bba_orb', 'other...'])
        orbcombo.setCurrentIndex(1)
        orbcombo.activated.connect(_add_entry)
        lay.addWidget(orbcombo, row, 1)

        row += 1
        lay.addWidget(QLabel('Subsection', wid), row, 0)
        sscombo = QComboBox(wid)
        sub = ['SA', 'SB', 'SP', 'SB']
        ssnames = [f'{d+1:02d}{sub[d%len(sub)]}' for d in range(20)]
        bcnames = [f'{d+1:02d}BC' for d in range(20)]
        names = []
        for aaa, bbb in zip(ssnames, bcnames):
            names.extend([aaa, bbb])
        sscombo.addItems(names)
        lay.addWidget(sscombo, row, 1)

        row += 1
        lay.addWidget(QLabel('\u03B8<sub>x</sub> [urad]', wid), row, 0)
        angx = QLineEdit(wid)
        angx.setValidator(QDoubleValidator())
        angx.setText('0.0')
        angx.setAlignment(Qt.AlignCenter)
        angx.setStyleSheet('max-width:5em;')
        lay.addWidget(angx, row, 1)

        row += 1
        lay.addWidget(QLabel('X [um] ', wid), row, 0)
        posx = QLineEdit(wid)
        posx.setValidator(QDoubleValidator())
        posx.setText('0.0')
        posx.setAlignment(Qt.AlignCenter)
        posx.setStyleSheet('max-width:5em;')
        lay.addWidget(posx, row, 1)

        row += 1
        lay.addWidget(QLabel('\u03B8<sub>y</sub> [urad]', wid), row, 0)
        angy = QLineEdit(wid)
        angy.setValidator(QDoubleValidator())
        angy.setText('0.0')
        angy.setAlignment(Qt.AlignCenter)
        angy.setStyleSheet('max-width:5em;')
        lay.addWidget(angy, row, 1)

        row += 1
        lay.addWidget(QLabel('Y [um] ', wid), row, 0)
        posy = QLineEdit(wid)
        posy.setValidator(QDoubleValidator())
        posy.setText('0.0')
        posy.setAlignment(Qt.AlignCenter)
        posy.setStyleSheet('max-width:5em;')
        lay.addWidget(posy, row, 1)

        row += 1
        hlay = QHBoxLayout()
        cancel = QPushButton('Cancel', wid)
        confirm = QPushButton('Ok', wid)
        confirm.setDefault(True)
        cancel.clicked.connect(wid.reject)
        confirm.clicked.connect(wid.accept)
        hlay.addStretch()
        hlay.addWidget(cancel)
        hlay.addStretch()
        hlay.addWidget(confirm)
        hlay.addStretch()
        wid.layout().addItem(hlay, row, 0, 1, 2)
        res = wid.exec_()
        if res != QDialog.Accepted:
            return

        index = orbcombo.currentIndex()
        confname = orbcombo.itemText(index)
        if not index:
            orbx = _np.array(self.orbx)
            orby = _np.array(self.orby)
        elif index == orbcombo.count() - 1:
            return
        else:
            orbs = self._client.get_config_value(confname)
            orbx = _np.array(orbs['x'])
            orby = _np.array(orbs['y'])

        agx = float(angx.text())
        agy = float(angy.text())
        psx = float(posx.text())
        psy = float(posy.text())
        sub = sscombo.currentText()
        orbx, orby = _calculate_bump(orbx, orby, sub, agx, agy, psx, psy)

        txt = f'Bump@{sub}: ref={confname}\n'
        txt += f'ax={agx:.1f} ay={agy:.1f} dx={psx:.1f} dy={psy:.1f}'
        self._update_and_emit(txt, orbx, orby)
コード例 #10
0
ファイル: orbit_register.py プロジェクト: lnls-sirius/hla
    def _edit_orbit(self):
        orbx = self.orbx
        orby = self.orby

        wid = QDialog(self)
        wid.setObjectName(self._csorb.acc + 'App')
        wid.setLayout(QVBoxLayout())

        hbl = QHBoxLayout()
        wid.layout().addItem(hbl)
        hbl.addWidget(QLabel('X = ', wid))
        multx = QLineEdit(wid)
        multx.setValidator(QDoubleValidator())
        multx.setText('1.0')
        # multx.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        multx.setAlignment(Qt.AlignCenter)
        multx.setStyleSheet('max-width:5em;')
        hbl.addWidget(multx)
        hbl.addWidget(QLabel('*X   +   ', wid))
        addx = QLineEdit(wid)
        addx.setValidator(QDoubleValidator())
        addx.setText('0.0')
        addx.setAlignment(Qt.AlignCenter)
        addx.setStyleSheet('max-width:5em;')
        hbl.addWidget(addx)
        hbl.addWidget(QLabel(' [um]', wid))

        hbl = QHBoxLayout()
        wid.layout().addItem(hbl)
        hbl.addWidget(QLabel('Y = ', wid))
        multy = QLineEdit(wid)
        multy.setValidator(QDoubleValidator())
        multy.setText('1.0')
        # multy.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        multy.setAlignment(Qt.AlignCenter)
        multy.setStyleSheet('max-width:5em;')
        hbl.addWidget(multy)
        hbl.addWidget(QLabel('*Y   +   ', wid))
        addy = QLineEdit(wid)
        addy.setValidator(QDoubleValidator())
        addy.setText('0.0')
        addy.setAlignment(Qt.AlignCenter)
        addy.setStyleSheet('max-width:5em;')
        hbl.addWidget(addy)
        hbl.addWidget(QLabel(' [um]', wid))

        hlay = QHBoxLayout()
        cancel = QPushButton('Cancel', wid)
        confirm = QPushButton('Ok', wid)
        confirm.setDefault(True)
        cancel.clicked.connect(wid.reject)
        confirm.clicked.connect(wid.accept)
        hlay.addStretch()
        hlay.addWidget(cancel)
        hlay.addStretch()
        hlay.addWidget(confirm)
        hlay.addStretch()
        wid.layout().addItem(hlay)
        res = wid.exec_()

        if res != QDialog.Accepted:
            return
        mltx = float(multx.text())
        mlty = float(multy.text())
        plusx = float(addx.text())
        plusy = float(addy.text())
        orbx = mltx * orbx + plusx
        orby = mlty * orby + plusy
        txt = ''
        txt += f'multx = {mltx:5.1f} offx = {plusx:7.1f}\n'
        txt += f'multy = {mlty:5.1f} offy = {plusy:7.1f}'
        self._update_and_emit(txt, orbx, orby)
コード例 #11
0
ファイル: flow_node.py プロジェクト: hzyrc6011/pmgwidgets
    def on_edit_properties_requested(self):
        """
        Show Settings Panel.
        If It was customized node,it will call the function of the content.
        Or the default settings parameters will be got.
        Returns:

        """
        from pmgwidgets import PMGPanel
        from qtpy.QtWidgets import QDialog, QVBoxLayout

        if isinstance(self.content, FlowContentForFunction):
            dlg = QDialog(self.base_rect.scene().flow_widget)
            sp = PMGPanel()
            p: 'CustomPort' = None
            input_ids, output_ids = [], []
            input_texts, output_texts = [], []
            self._last_var = 0

            def new_id_input():
                node_id = self.id
                max_val = 0
                for p in self.input_ports:
                    n, t, p = p.parse_id()
                    if max_val < int(p):
                        max_val = int(p)
                self._last_var += 1
                return '%s:input:%d' % (node_id, max_val + self._last_var)

            def new_id_output():
                node_id = self.id
                max_val = 0
                for p in self.output_ports:
                    n, t, p = p.parse_id()
                    if max_val < int(p):
                        max_val = int(p)
                self._last_var += 1
                return '%s:output:%d' % (node_id, max_val + self._last_var)

            for p in self.input_ports:
                input_ids.append(p.id)
                input_texts.append(p.text)

            for p in self.output_ports:
                output_ids.append(p.id)
                output_texts.append(p.text)

            views = []
            views += self.content.get_settings_params()
            views += [
                ('line_ctrl', 'text', 'Node Text', self.text),
            ]
            if self.content.ports_changable[0]:
                views.append(('list_ctrl', 'inputs', 'Set Inputs',
                              [input_ids, input_texts], new_id_input))
            if self.content.ports_changable[1]:
                views.append(('list_ctrl', 'outputs', 'Set Outputs',
                              [output_ids, output_texts], new_id_output))
            sp.set_items(views)
            dlg.setLayout(QVBoxLayout())
            dlg.layout().addWidget(sp)
            dlg.exec_()

            dic = sp.get_value()
            self.change_property(dic)
        else:
            try:
                self.content.settings_window_requested(self.canvas.flow_widget)
            except Exception as e:
                import traceback
                exc = traceback.format_exc()
                print(exc)
                QMessageBox.warning(self.canvas.flow_widget, 'Error', str(e))
コード例 #12
0
    def on_edit(self):
        list_widget = self.toolbox.currentWidget()
        curr_row = list_widget.currentRow()

        if curr_row >= 0:
            group_name = self.toolbox.itemText(self.toolbox.currentIndex())
            curr_text = list_widget.currentItem().text()
            dic = self.node_info_dic[group_name][curr_text]
            edit_layout = QHBoxLayout()
            input_widget = QTextEdit()
            edit_layout.addWidget(input_widget)
            check_button = QPushButton(text='check')
            edit_layout.addWidget(check_button)
            input_widget.setText(repr(dic['params']))
            views = [('line_ctrl', 'text', 'Node Text', dic['text']),
                     ('check_ctrl', 'inputs_changeable',
                      'Input Ports Changeable', dic['ports_changeable'][0]),
                     ('check_ctrl', 'outputs_changeable',
                      'Output Ports Changeble', dic['ports_changeable'][1]),
                     ('editor_ctrl', 'code', 'Input Python Code', dic['code'],
                      'python'),
                     ('list_ctrl', 'inputs', 'Set Inputs',
                      [[None] * len(dic['inputs']),
                       dic['inputs']], lambda: None),
                     ('list_ctrl', 'outputs', 'Set Outputs',
                      [[None] * len(dic['outputs']),
                       dic['outputs']], lambda: None),
                     ('file_ctrl', 'icon', 'Set Icon', dic['icon']),
                     ('combo_ctrl', 'group', 'Group Name', dic['group'],
                      self.groups)]
            sp = PMGPanel(parent=None, views=views)
            dialog = QDialog(self)

            def verify():
                try:
                    text = input_widget.document().toPlainText()
                    l = eval(text)
                    if isinstance(l, list):
                        dialog2 = QDialog(dialog)
                        sp2 = PMGPanel(parent=None, views=l)
                        dialog2.setLayout(QHBoxLayout())
                        dialog2.layout().addWidget(sp2)
                        dialog2.layout().addLayout(edit_layout)
                        dialog2.exec_()
                except:
                    import traceback
                    traceback.print_exc()

            check_button.clicked.connect(verify)
            dialog.setLayout(QVBoxLayout())
            dialog.layout().addWidget(sp)
            dialog.layout().addLayout(edit_layout)
            dialog.exec_()
            dic = sp.get_value()
            params = None
            try:
                params = eval(input_widget.document().toPlainText())
            except:
                import traceback
                traceback.print_exc()
            group = self.get_current_list_widget_group()
            if isinstance(params, list):
                self.node_info_dic[group][curr_text]['params'] = params
            self.node_info_dic[group][curr_text]['text'] = dic['text']
            self.node_info_dic[group][curr_text]['icon'] = dic['icon']
            self.node_info_dic[group][curr_text]['code'] = dic['code']
            self.node_info_dic[group][curr_text]['inputs'] = dic['inputs'][1]
            self.node_info_dic[group][curr_text]['outputs'] = dic['outputs'][1]
            self.node_info_dic[group][curr_text]['group'] = dic['group']
            self.node_info_dic[group][curr_text]['ports_changeable'] = [
                dic['inputs_changeable'], dic['outputs_changeable']
            ]
            list_widget.item(curr_row).setText(dic['text'])
            self.save_node_templetes()
            self.load_nodes()
        else:
            return
コード例 #13
0
ファイル: filetree.py プロジェクト: hzyrc6011/pmgwidgets
class PMGFilesTreeview(QTreeView):
    """
        文件树
    """
    open_signal = Signal(str)
    open_folder_signal = Signal(str)
    new_file_signal = Signal(str)
    new_folder_signal = Signal(str)
    delete_file_signal = Signal(str)
    rename_file_signal = Signal(str, str)

    signal_ext_filter_adapt = Signal(bool)
    signal_ext_filter_changed = Signal(dict)

    def __init__(self, initial_dir: str = '', parent=None):
        super().__init__(parent)
        self.initial_dir = initial_dir
        self.setup_ui()
        self.bind_events()

        self.filter_exts = True
        self.exts_to_filter = {
            'Program Scripts': {
                '.pyx': True,
                '.py': True,
                '.c': True,
                '.pyi': True,
                '.dll': True,
                '.h': True,
                '.cpp': True,
                '.ipynb': True,
                '.sh': True,
                '.cmd': True,
                '.bat': True
            },
            'Documents': {
                '.txt': True,
                '.md': True,
                '.doc': True,
                '.docx': True,
                '.ppt': True,
                '.pptx': True,
                '.html': True
            },
            'Data Files': {
                '.csv': True,
                '.xls': True,
                '.xlsx': True,
                '.tab': True,
                '.dat': True,
                '.tsv': True,
                '.sav': True,
                '.zsav': True,
                '.sas7bdat': True,
                '.pkl': True,
                '.json': True,
                '.mat': True,
                '.pmjson': True,
                '.pmd': True
            },
            'Medias': {
                '.mp3': False,
                '.mp4': False,
                '.avi': False,
                '.wma': False,
                '.png': True,
                '.jpg': True,
                '.svg': True
            },
            'Resources': {
                '.qm': True,
                '.ts': True
            }
        }

    def setup_ui(self):
        """
        界面初始化
        :return:
        """

        self.translator = create_translator(path=os.path.join(
            os.path.dirname(__file__), 'translations',
            'qt_{0}.qm'.format(QLocale.system().name())))  # translator

        self.setTabKeyNavigation(True)
        self.setDragEnabled(True)
        self.setDragDropOverwriteMode(True)
        self.setAlternatingRowColors(False)
        self.setUniformRowHeights(True)
        self.setSortingEnabled(True)
        self.setAnimated(True)
        self.setAllColumnsShowFocus(False)
        self.setWordWrap(False)
        self.setHeaderHidden(False)
        self.setObjectName("treeView_files")
        self.header().setSortIndicatorShown(True)

        self.model = PMFileSystemModel()
        self.model.setRootPath(self.initial_dir)

        self.setModel(self.model)
        self.setRootIndex(self.model.index(self.initial_dir))
        self.setAnimated(False)
        self.setSortingEnabled(True)  # 启用排序
        self.header().setSortIndicatorShown(True)  # 启用标题排序
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)
        self.init_context_menu()

    def bind_events(self):
        """
        回调、事件与信号初始化
        :return:
        """
        self.doubleClicked.connect(lambda index: self.on_open())

        self.openAction.triggered.connect(self.on_open)
        self.importAction.triggered.connect(self.on_import)
        self.renameAction.triggered.connect(self.on_rename)
        self.deleteAction.triggered.connect(self.on_delete)

        self.copyAction.triggered.connect(self.on_copy)
        self.pasteAction.triggered.connect(self.on_paste)
        self.filterAction.triggered.connect(
            self.show_ext_filter_selection_dialog)

        self.copyPathAction.triggered.connect(self.copy_path)
        self.new_file_action.triggered.connect(lambda: self.on_new_file(''))
        self.new_python_file_action.triggered.connect(
            lambda: self.on_new_file('py'))
        self.new_folder_action.triggered.connect(self.on_new_folder)
        self.open_file_manager_action.triggered.connect(
            self.on_open_file_manager)

        self.rename_shortcut.activated.connect(self.on_rename)
        self.paste_shortcut.activated.connect(self.on_paste)
        self.copy_shortcut.activated.connect(self.on_copy)
        self.open_shortcut.activated.connect(self.on_open)
        self.delete_shortcut.activated.connect(self.on_delete)
        self.goto_parent_path_shortcut.activated.connect(
            self.slot_goto_parent_path)

        self.customContextMenuRequested.connect(self.show_context_menu)

    def init_context_menu(self):
        """
        初始化右键菜单
        :return:
        """
        self.contextMenu = QMenu(self)
        self.openAction = self.contextMenu.addAction(self.tr('Open'))

        self.importAction = self.contextMenu.addAction(self.tr('Import'))
        self.importAction.setEnabled(False)

        self.new_file_or_folder_menu = QMenu(self.tr('New..'))
        self.contextMenu.addMenu(self.new_file_or_folder_menu)
        self.new_file_action = self.new_file_or_folder_menu.addAction(
            self.tr('File..'))
        self.new_python_file_action = self.new_file_or_folder_menu.addAction(
            self.tr('Python File'))
        self.new_folder_action = self.new_file_or_folder_menu.addAction(
            self.tr('Folder'))
        self.new_file_or_folder_menu.addSeparator()

        self.copyAction = self.contextMenu.addAction(self.tr("Copy"))
        self.pasteAction = self.contextMenu.addAction(self.tr("Paste"))
        self.pasteAction.setEnabled(False)

        self.renameAction = self.contextMenu.addAction(self.tr('Rename'))
        self.deleteAction = self.contextMenu.addAction(self.tr('Delete'))

        self.filterAction = self.contextMenu.addAction(self.tr('Filter'))
        self.copyPathAction = self.contextMenu.addAction(self.tr('Copy Path'))

        self.open_file_manager_action = self.contextMenu.addAction(
            self.tr('Open Explorer'))

        self.renameAction.setShortcut(QKeySequence('F2'))
        self.copyAction.setShortcut(QKeySequence('Ctrl+C'))
        self.pasteAction.setShortcut(QKeySequence('Ctrl+V'))
        self.deleteAction.setShortcut(QKeySequence('Delete'))

        self.rename_shortcut = QShortcut(QKeySequence('F2'),
                                         self,
                                         context=Qt.WidgetShortcut)
        self.copy_shortcut = QShortcut(QKeySequence.Copy,
                                       self,
                                       context=Qt.WidgetShortcut)
        self.paste_shortcut = QShortcut(QKeySequence.Paste,
                                        self,
                                        context=Qt.WidgetShortcut)
        self.delete_shortcut = QShortcut(QKeySequence('Delete'),
                                         self,
                                         context=Qt.WidgetShortcut)
        self.open_shortcut = QShortcut(QKeySequence('Return'),
                                       self,
                                       context=Qt.WidgetShortcut)
        self.goto_parent_path_shortcut = QShortcut(QKeySequence('Backspace'),
                                                   self,
                                                   context=Qt.WidgetShortcut)

    def show_context_menu(self):
        """
        显示上下文右键菜单
        :return:
        """
        self.contextMenu.popup(QCursor.pos())
        self.contextMenu.show()

    def get_current_file_path(self):
        """
        获取当前选中文件的路径。
        如果当前没有选中的文件,就返回根路径。
        :return:
        """
        if len(self.selectedIndexes()) > 0:
            index = self.currentIndex()
            file_info = self.model.fileInfo(index)
            return file_info.absoluteFilePath()
        else:
            return self.get_root_path()

    def get_root_path(self):
        """
        获取根路径
        :return:
        """
        return self.model.rootPath()

    def set_item_focus(self, file_path: str):
        """
        set item focus in TreeView
        :param file_path: File or Dir
        :return:
        """
        self.setCurrentIndex(self.model.index(file_path))

    def on_open_file_manager(self):
        path = self.get_current_file_path()
        print(path)
        if os.path.isdir(path):
            open_file_manager(path)
        else:
            open_file_manager(os.path.dirname(path))

        # if os.path.exists(new_folder_path):
        #     self.set_item_focus(new_folder_path)  # 设置focus liugang 200923
        #     QMessageBox.critical(self, self.tr('Error'),
        #                          self.tr('Folder %s already exists!' % name))
        #     return
        # else:
        #     os.mkdir(new_folder_path)
        #     self.new_folder_signal[str].emit(new_folder_path)
        #     self.set_item_focus(new_folder_path)  # 设置focus liugang 200923

    def on_new_folder(self):
        """
        新建文件夹时出发的回调
        :return:
        """
        path = self.get_current_file_path()
        name, stat = QInputDialog.getText(self,
                                          self.tr('Please Input folder name'),
                                          '', QLineEdit.Normal, '')
        if name.find('.') != -1:
            QMessageBox.critical(self, self.tr('Error'),
                                 self.tr('Folder name %s is illeagal!' % name))
            return
        if stat:
            if os.path.isdir(path):
                new_folder_path = os.path.join(path, name)
            else:
                new_folder_path = os.path.join(os.path.dirname(path), name)

            if os.path.exists(new_folder_path):
                self.set_item_focus(new_folder_path)  # 设置focus liugang 200923
                QMessageBox.critical(
                    self, self.tr('Error'),
                    self.tr('Folder %s already exists!' % name))
                return
            else:
                os.mkdir(new_folder_path)
                self.new_folder_signal[str].emit(new_folder_path)
                self.set_item_focus(new_folder_path)  # 设置focus liugang 200923

    def on_new_file(self, ext: str = ''):
        """
        新建文件时触发的回调
        :return:
        """
        path = self.get_current_file_path()
        dlg = InputFilenameDialog(parent=self,
                                  title=self.tr('Please input file name'),
                                  ext=ext)

        dlg.exec_()
        name = dlg.name_input.text()
        stat = dlg.status
        if stat:
            if os.path.isdir(path):
                new_file_path = os.path.join(path, name)
            else:
                new_file_path = os.path.join(os.path.dirname(path), name)

            if os.path.exists(new_file_path):
                self.set_item_focus(new_file_path)  # 设置focus  liugang 200923
                QMessageBox.critical(self, self.tr('Error'),
                                     self.tr('File %s already exists!' % name))
                return
            with open(new_file_path, 'wb') as f:
                f.close()
                self.new_file_signal[str].emit(new_file_path)

            self.set_item_focus(new_file_path)
            self.on_open()  # 创建文件后打开  liugang 200923

    def on_open(self):
        """
        点击‘open’时候触发的回调, 等效的方式还有双击以及按下回车键。
        :return:
        """
        path = self.get_current_file_path()
        if os.path.isdir(path):
            self.open_folder_signal.emit(path)
        else:
            self.open_signal[str].emit(path)

    def on_import(self):
        """

        :return:
        """
        pass

    def on_rename(self):
        """
        点击’重命名‘时候的回调。
        :return:
        """
        from pmgwidgets import rename_file
        path = self.get_current_file_path()
        basename = os.path.basename(path)
        dir_name = os.path.dirname(path)
        name, stat = QInputDialog.getText(self,
                                          self.tr('Please Input file name'),
                                          '', QLineEdit.Normal, basename)
        if stat:
            new_absolute_path = os.path.join(dir_name, name)
            rename_result = rename_file(path, new_absolute_path)
            if not rename_result:
                QMessageBox.critical(self, self.tr('Error'),
                                     self.tr('Unable to Rename this file.'))
            else:
                self.rename_file_signal[str, str].emit(path, new_absolute_path)

    def on_delete(self):
        """
        点击’删除‘时的回调
        :return:
        """
        from pmgwidgets import move_to_trash
        path = self.get_current_file_path()

        moved_successful = move_to_trash(path)
        if not moved_successful:
            QMessageBox.critical(
                self, self.tr('Error'),
                self.tr('Unable to Move this file to recycle bin.'))
        else:
            self.delete_file_signal[str].emit(path)

    def on_copy(self):
        """
        copy file or dir , save path in pasteAction data.
        :return:
        """
        path = self.get_current_file_path()
        self.pasteAction.setEnabled(True)
        self.pasteAction.setData(path)

        data = QMimeData()
        data.setUrls([QUrl.fromLocalFile(path)])  # 复制到系统剪贴板

        clip = QApplication.clipboard()
        clip.setMimeData(data)

    def on_paste(self):
        """
        Paste file or dir in pasteAction data
        :return:
        """
        from pmgwidgets import copy_paste
        path = self.get_current_file_path()
        target_dir_name = path if os.path.isdir(path) else os.path.dirname(
            path)
        url: QUrl = None

        mimedata = QApplication.clipboard().mimeData(mode=QClipboard.Clipboard)
        print(mimedata)
        urls: List[QUrl] = mimedata.urls()
        for url in urls:
            source_path = url.toLocalFile()  # self.pasteAction.data()
            # File
            if os.path.isfile(source_path):
                source_file_name = os.path.basename(source_path)
                # if exist ,rename to copy_xxx
                if os.path.isfile(
                        os.path.join(target_dir_name, source_file_name)):
                    target_file_name = "copy_{0}".format(source_file_name)
                else:
                    target_file_name = source_file_name
                target_path = os.path.join(target_dir_name, target_file_name)
            # Directory
            else:
                last_dir_name = os.path.split(source_path)[-1]
                # if exist , rename dir copy_xxxx
                if os.path.isdir(os.path.join(target_dir_name, last_dir_name)):
                    target_name = "copy_{0}".format(last_dir_name)
                else:
                    target_name = last_dir_name
                target_path = os.path.join(target_dir_name, target_name)

            copy_succ = copy_paste(source_path, target_path)
            if not copy_succ:
                QMessageBox.critical(self, self.tr('Error'),
                                     self.tr('Copy File or Directory Error.'))
            else:
                self.set_item_focus(target_path)

    def show_ext_filter_selection_dialog(self):

        self.dlg = QDialog(self)
        self.dlg.setWindowTitle(self.tr('Extension Name To Show'))
        self.dlg.setLayout(QVBoxLayout())
        self.dlg.layout().addWidget(QLabel('过滤文件名'))
        check_box = QCheckBox()
        self.dlg.check_box = check_box
        check_box.setChecked(self.filter_exts)
        self.dlg.layout().addWidget(check_box)
        check_box.stateChanged.connect(
            lambda stat: self.signal_ext_filter_adapt.emit(stat))
        check_widget = PMCheckTree(data=self.exts_to_filter)
        self.dlg.check_widget = check_widget
        self.dlg.layout().addWidget(check_widget)
        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)

        buttonBox.accepted.connect(self.on_ext_filter_changed)
        buttonBox.rejected.connect(self.dlg.deleteLater)
        # 清除选择功能不完善目前禁用
        # button_clear = buttonBox.addButton(self.tr('Clear Filter'), QDialogButtonBox.ApplyRole)
        # button_clear.clicked.connect(self.clear_ext_filter)
        self.dlg.layout().addWidget(buttonBox)
        self.dlg.exec_()

    def on_ext_filter_changed(self):
        """
        当扩展名过滤改变的时候。
        :return:
        """
        self.exts_to_filter = self.dlg.check_widget.get_data()
        self.filter_exts = self.dlg.check_box.isChecked()
        self.update_ext_filter()
        self.dlg.deleteLater()
        self.signal_ext_filter_changed.emit(self.exts_to_filter)

    def clear_ext_filter(self):
        self.set_ext_filter(None)
        self.dlg.deleteLater()

    def update_ext_filter(self):
        """
        刷新扩展名过滤。
        :return:
        """
        ext_list = []
        for key in self.exts_to_filter.keys():
            for name in self.exts_to_filter[key].keys():
                if self.exts_to_filter[key][name]:
                    ext_list.append('*' + name)
        self.set_ext_filter(ext_list)

    def set_ext_filter(self, ext_names: List[str]):
        """
        文件名过滤
        例如要过滤出.py和.pyx文件,就是ext_names=['*.py','*.pyx']
        discard功能不太完善,目前先禁用。
        :param ext_names:
        :return:
        """
        if ext_names is not None and self.filter_exts:
            self.model.setNameFilterDisables(False)
            self.model.setNameFilters(ext_names)
        else:
            self.model.setNameFilterDisables(True)
            self.model.setNameFilters(["*"])

    def slot_goto_parent_path(self):
        """

        Returns:

        """
        root = self.get_root_path()
        parent = os.path.dirname(root)
        if os.path.exists(parent):
            pass
        self.open_folder_signal.emit(parent)

    def copy_path(self):
        """
        复制当前文件的路径的回调
        Returns:

        """
        path = self.get_current_file_path()
        # data = QMimeData()
        clipboard = QApplication.clipboard()
        clipboard.setText(path)