class TreeSymbolsWidget(QDialog):
    """ Class of Dialog for Tree Symbols """

    dockWidget = pyqtSignal('PyQt_PyObject')
    undockWidget = pyqtSignal('PyQt_PyObject')

    def __init__(self, parent=None):
        super(TreeSymbolsWidget, self).__init__(parent)
        vbox = QVBoxLayout(self)
        vbox.setContentsMargins(0, 0, 0, 0)
        vbox.setSpacing(0)
        self.tree = QTreeWidget()
        self.tree.setFrameShape(0)
        vbox.addWidget(self.tree)
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(self.tree.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.tree.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.tree.header().setStretchLastSection(False)
        self.actualSymbols = ('', {})
        self.docstrings = {}
        self.collapsedItems = {}
        self.__icons = {
            "function": QIcon(":img/function"),
            "attribute": QIcon(":img/statement"),
            "class": QIcon(":img/class")
        }

        self.tree.itemClicked.connect(self._go_to_definition)
        self.tree.itemActivated.connect(self._go_to_definition)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)

        self.customContextMenuRequested['const QPoint &'].connect(
            self._menu_context_tree)
        # self.connect(
        #    self,
        #    SIGNAL("customContextMenuRequested(const QPoint &)"),
        #    self._menu_context_tree)
        # self.connect(self, SIGNAL("itemCollapsed(QTreeWidgetItem *)"),
        #             self._item_collapsed)
        # self.connect(self, SIGNAL("itemExpanded(QTreeWidgetItem *)"),
        #             self._item_expanded)

        IDE.register_service('symbols_explorer', self)
        ExplorerContainer.register_tab(translations.TR_TAB_SYMBOLS, self)

    def install_tab(self):
        """ Connect signals for goingdown """

        ide = IDE.get_service('ide')
        ide.goingDown.connect(self.close)

    def _menu_context_tree(self, point):
        """Context menu"""
        index = self.tree.indexAt(point)
        if not index.isValid():
            return

        menu = QMenu(self)
        f_all = menu.addAction(translations.TR_FOLD_ALL)
        u_all = menu.addAction(translations.TR_UNFOLD_ALL)
        menu.addSeparator()
        u_class = menu.addAction(translations.TR_UNFOLD_CLASSES)
        u_class_method = menu.addAction(
            translations.TR_UNFOLD_CLASSES_AND_METHODS)
        u_class_attr = menu.addAction(
            translations.TR_UNFOLD_CLASSES_AND_ATTRIBUTES)
        menu.addSeparator()
        # save_state = menu.addAction(self.tr("Save State"))

        # self.connect(f_all, SIGNAL("triggered()"),
        #             lambda: self.tree.collapseAll())
        # self.connect(u_all, SIGNAL("triggered()"),
        #             lambda: self.tree.expandAll())
        # self.connect(u_class, SIGNAL("triggered()"), self._unfold_class)
        # self.connect(u_class_method, SIGNAL("triggered()"),
        #             self._unfold_class_method)
        # self.connect(u_class_attr, SIGNAL("triggered()"),
        #              self._unfold_class_attribute)
        # self.connect(save_state, SIGNAL("triggered()"),
        #    self._save_symbols_state)

        menu.exec_(QCursor.pos())

    def _get_classes_root(self):
        """Return the root of classes"""
        class_root = None
        for i in range(self.tree.topLevelItemCount()):
            item = self.tree.topLevelItem(i)
            if item.isClass and not item.isClickable:
                class_root = item
                break
        return class_root

    def _unfold_class(self):
        """Method to Unfold Classes"""
        self.tree.collapseAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return

        classes_root.setExpanded(True)

    def _unfold_class_method(self):
        """Method to Unfold Methods"""
        self.tree.expandAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return
        # for each class!
        for i in range(classes_root.childCount()):
            class_item = classes_root.child(i)
            # for each attribute or functions
            for j in range(class_item.childCount()):
                item = class_item.child(j)
                # METHODS ROOT!!
                if not item.isMethod and not item.isClickable:
                    item.setExpanded(False)
                    break

    def _unfold_class_attribute(self):
        """Method to Unfold Attributes"""
        self.tree.expandAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return
        # for each class!
        for i in range(classes_root.childCount()):
            class_item = classes_root.child(i)
            # for each attribute or functions
            for j in range(class_item.childCount()):
                item = class_item.child(j)
                # ATTRIBUTES ROOT!!
                if not item.isAttribute and not item.isClickable:
                    item.setExpanded(False)
                    break

    def _save_symbols_state(self):
        """Method to Save a persistent Symbols state"""
        # filename = self.actualSymbols[0]
        # TODO: persist self.collapsedItems[filename] in QSettings
        pass

    def _get_expand(self, item):
        """
        Returns True or False to be used as setExpanded() with the items
        It method is based on the click that the user made in the tree
        """
        name = self._get_unique_name(item)
        filename = self.actualSymbols[0]
        collapsed_items = self.collapsedItems.get(filename, [])
        can_check = (not item.isClickable) or item.isClass or item.isMethod
        if can_check and name in collapsed_items:
            return False
        return True

    @staticmethod
    def _get_unique_name(item):
        """
        Returns a string used as unique name
        """
        # className_Attributes/className_Functions
        parent = item.parent()
        if parent:
            return "%s_%s" % (parent.text(0), item.text(0))
        return "_%s" % item.text(0)

    def clear(self):
        self.tree.clear()

    def update_symbols_tree(self, symbols, filename='', parent=None):
        """Method to Update the symbols on the Tree"""
        TIP = "{} {}"
        if not parent:
            if filename == self.actualSymbols[0] and \
                    self.actualSymbols[1] and not symbols:
                return

            if symbols == self.actualSymbols[1]:
                # Nothing new then return
                return

            # we have new symbols refresh it
            self.tree.clear()
            self.actualSymbols = (filename, symbols)
            self.docstrings = symbols.get('docstrings', {})
            parent = self.tree
        if 'attributes' in symbols:
            globalAttribute = ItemTree(parent, [translations.TR_ATTRIBUTES])
            globalAttribute.isClickable = False
            globalAttribute.isAttribute = True
            globalAttribute.setExpanded(self._get_expand(globalAttribute))
            globalAttribute.setToolTip(
                0, TIP.format(len(symbols['attributes']),
                              translations.TR_ATTRIBUTES))
            for glob in sorted(symbols['attributes']):
                globItem = ItemTree(globalAttribute, [glob],
                                    lineno=symbols['attributes'][glob])
                globItem.isAttribute = True
                globItem.setIcon(0, self.__icons["attribute"])
                globItem.setExpanded(self._get_expand(globItem))

        if 'functions' in symbols and symbols['functions']:
            functionsItem = ItemTree(parent, [translations.TR_FUNCTIONS])
            functionsItem.isClickable = False
            functionsItem.isMethod = True
            functionsItem.setExpanded(self._get_expand(functionsItem))
            functionsItem.setToolTip(0, TIP.format(len(symbols['functions']),
                                                   translations.TR_FUNCTIONS))
            for func in sorted(symbols['functions']):
                item = ItemTree(functionsItem, [func],
                                lineno=symbols['functions'][func]['lineno'])
                tooltip = self.create_tooltip(
                    func, symbols['functions'][func]['lineno'])
                item.isMethod = True
                item.setIcon(0, self.__icons["function"])
                # item.setIcon(
                #    0, ui_tools.colored_icon(":img/function", "#9FA8DA"))
                item.setToolTip(0, tooltip)
                item.setExpanded(self._get_expand(item))
                self.update_symbols_tree(
                    symbols['functions'][func]['functions'], parent=item)
        if 'classes' in symbols and symbols['classes']:
            classItem = ItemTree(parent, [translations.TR_CLASSES])
            classItem.isClickable = False
            classItem.isClass = True
            classItem.setExpanded(self._get_expand(classItem))
            classItem.setToolTip(0, TIP.format(len(symbols['classes']),
                                               translations.TR_CLASSES))
            for claz in sorted(symbols['classes']):
                line_number = symbols['classes'][claz]['lineno']
                item = ItemTree(classItem, [claz], lineno=line_number)
                item.isClass = True
                tooltip = self.create_tooltip(claz, line_number)
                item.setToolTip(0, tooltip)
                # item.setIcon(0, ui_tools.colored_icon(":img/class", "#FFCC80"))
                # item.setIcon(0, ui_tools.get_icon('class', '#FFCC80'))
                item.setIcon(0, self.__icons["class"])
                item.setExpanded(self._get_expand(item))
                self.update_symbols_tree(symbols['classes'][claz]['members'],
                                         parent=item)

    def _go_to_definition(self, item):
        """ Takes and item object and goes to definition on the editor """

        main_container = IDE.get_service('main_container')
        if item.isClickable and main_container:
            main_container.editor_go_to_line(item.lineno - 1)

    def create_tooltip(self, name, lineno):
        """Takes a name and line number and returns a tooltip"""
        doc = self.docstrings.get(lineno, None)
        if doc is None:
            doc = ''
        else:
            doc = '\n' + doc
        tooltip = name + doc
        return tooltip

    def _item_collapsed(self, item):
        """When item collapsed"""
        super(TreeSymbolsWidget, self).collapseItem(item)

        can_check = (not item.isClickable) or item.isClass or item.isMethod
        if can_check:
            n = self._get_unique_name(item)
            filename = self.actualSymbols[0]
            self.collapsedItems.setdefault(filename, [])
            if n not in self.collapsedItems[filename]:
                self.collapsedItems[filename].append(n)

    def _item_expanded(self, item):
        """When item expanded"""
        super(TreeSymbolsWidget, self).expandItem(item)

        n = self._get_unique_name(item)
        filename = self.actualSymbols[0]
        if n in self.collapsedItems.get(filename, []):
            self.collapsedItems[filename].remove(n)
            if not len(self.collapsedItems[filename]):
                # no more items, free space
                del self.collapsedItems[filename]

    def clean(self):
        """
        Reset the tree and reset attributes
        """
        self.tree.clear()
        self.collapsedItems = {}

    def reject(self):
        if self.parent() is None:
            self.dockWidget.emit(self)

    def closeEvent(self, event):
        """On Close event handling"""

        self.dockWidget.emit(self)
        # self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self)
        event.ignore()
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        # 定义主界面
        self.setWindowIcon(QIcon('.\\clip.ico'))
        # 主窗口的默认有右键菜单,默认的右键菜单不满足要求,因此采用以下语句停用
        self.setContextMenuPolicy(Qt.NoContextMenu)
        self.setEnabled(True)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setStyleSheet('QMainWindow { background-color: #F0F0F0 }'
                           'QWidget { font-family: \'Microsoft YaHei UI\' }')

        # 桌面控件
        desktop_widget = QApplication.desktop()
        desk_height = desktop_widget.height()
        desk_width = desktop_widget.width()
        self.window_width = 400
        self.window_height = 300
        self.setGeometry(int((desk_width - self.window_width) / 2),
                         int((desk_height - self.window_height) / 2),
                         self.window_width, self.window_height)
        # self.setWindowState(Qt.WindowMaximized)
        self.setMinimumSize(QSize(self.window_width, self.window_height))
        # 获得系统得剪切板
        self.clip_board = QApplication.clipboard()
        # 连接数据库
        self.db_conn = sqlite3.connect('clip_board_database.db')
        self.db_cursor = self.db_conn.cursor()
        # 是否置顶
        self.is_top = False
        # 是否移动
        self.on_move = False
        # 窗口状态
        self.window_status = ''
        # 记录鼠标的世界坐标
        self.mouse_start_point = None
        # 记录窗体的形状数据
        self.window_geo = None
        # 托盘图标
        self.tray_icon = QSystemTrayIcon(QIcon('.\\clip.ico'), self)
        self.tray_icon.setToolTip('自定义粘贴板')
        # 托盘菜单
        self.tray_icon_menu = QMenu(self)
        restore_action = QAction('还原', self)
        restore_action.triggered.connect(self.showNormal)
        quit_action = QAction('退出', self)
        quit_action.triggered.connect(QApplication.quit)
        self.tray_icon.activated.connect(self.restore_win)
        self.tray_icon_menu.addActions([restore_action, quit_action])
        self.tray_icon.setContextMenu(self.tray_icon_menu)
        self.tray_icon.show()

        # 布局,创建子控件
        self.central_widget = QWidget(self)
        self.v_layout_main_window = QVBoxLayout(self.central_widget)
        self.v_layout_main_window.setContentsMargins(0, 0, 0, 0)
        self.v_layout_main_window.setSpacing(0)
        self.widget_title = QWidget(self.central_widget)
        self.horizontalLayout = QHBoxLayout(self.widget_title)
        spacer_item = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacer_item)
        self.horizontalLayout.setSpacing(0)
        self.tool_button_top = QToolButton(self.central_widget)
        self.tool_button_top.setIcon(QIcon('.\\top.ico'))
        self.tool_button_top.setIconSize(QSize(20, 20))
        self.tool_button_top.setStyleSheet(
            'QToolButton { background-color: transparent;'
            'height: 20px; width: 20px; }')
        self.tool_button_top.setFocusPolicy(Qt.NoFocus)
        self.horizontalLayout.addWidget(self.tool_button_top)
        # self.tool_button_back = QToolButton(self.central_widget)
        # self.tool_button_back.setIcon(QIcon('.\\back.ico'))
        # self.tool_button_back.setIconSize(QSize(20, 20))
        # self.tool_button_back.setStyleSheet('QToolButton { background-color: transparent;'
        #                                     'height: 20px; width: 20px; }')
        # self.tool_button_back.setFocusPolicy(Qt.NoFocus)
        # self.horizontalLayout.addWidget(self.tool_button_back)
        self.tool_button_min = QToolButton(self.central_widget)
        self.tool_button_min.setIcon(QIcon('.\\min.ico'))
        self.tool_button_min.setIconSize(QSize(20, 20))
        self.tool_button_min.setStyleSheet(
            'QToolButton { background-color: transparent;'
            'height: 20px; width: 20px; }')
        self.tool_button_min.setFocusPolicy(Qt.NoFocus)
        self.horizontalLayout.addWidget(self.tool_button_min)
        self.tool_button_max = QToolButton(self.central_widget)
        self.tool_button_max.setIcon(QIcon('.\\max.ico'))
        self.tool_button_max.setIconSize(QSize(20, 20))
        self.tool_button_max.setStyleSheet(
            'QToolButton { background-color: transparent;'
            'height: 20px; width: 20px; }')
        self.tool_button_max.setFocusPolicy(Qt.NoFocus)
        self.horizontalLayout.addWidget(self.tool_button_max)
        self.tool_button_exit = QToolButton(self.central_widget)
        self.tool_button_exit.setIcon(QIcon('.\\close.ico'))
        self.tool_button_exit.setIconSize(QSize(20, 20))
        self.tool_button_exit.setStyleSheet(
            'QToolButton { background-color: transparent;'
            'height: 20px; width: 20px; }')
        self.tool_button_exit.setFocusPolicy(Qt.NoFocus)
        self.horizontalLayout.addWidget(self.tool_button_exit)
        self.v_layout_main_window.addWidget(self.widget_title)
        self.v_layout_tree_view = QVBoxLayout()
        self.v_layout_tree_view.setContentsMargins(9, 0, 9, 9)
        self.v_layout_tree_view.setSpacing(6)
        self.h_layout_filter = QHBoxLayout()
        self.combo_box_group_name = QComboBox(self.central_widget)
        self.combo_box_group_name.setMinimumSize(QSize(120, 24))
        self.combo_box_group_name.setMaximumSize(QSize(120, 24))
        self.h_layout_filter.addWidget(self.combo_box_group_name)
        self.line_edit_key_filter = QLineEdit(self.central_widget)
        self.line_edit_key_filter.setMinimumSize(QSize(0, 24))
        self.line_edit_key_filter.setMaximumSize(QSize(16777215, 24))
        self.h_layout_filter.addWidget(self.line_edit_key_filter)
        self.combo_box_item_click_response = QComboBox(self.central_widget)
        self.combo_box_item_click_response.setMinimumSize(QSize(90, 24))
        self.combo_box_item_click_response.setMaximumSize(QSize(90, 24))
        self.combo_box_item_click_response.addItems(['复制', '复制并粘贴', '编辑'])
        self.h_layout_filter.addWidget(self.combo_box_item_click_response)
        self.v_layout_tree_view.addLayout(self.h_layout_filter)
        self.tree_widget_content_view = QTreeWidget(self.central_widget)
        self.tree_widget_content_view.header().setSectionResizeMode(
            QHeaderView.Stretch)
        self.tree_widget_content_view.setColumnCount(2)
        self.tree_widget_content_view.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.v_layout_tree_view.addWidget(self.tree_widget_content_view)
        self.v_layout_main_window.addLayout(self.v_layout_tree_view)
        self.setCentralWidget(self.central_widget)

        self.translate()

        self.tree_widget_content_view.itemClicked.connect(
            self.item_click_response)

        self.combo_box_group_name.currentIndexChanged.connect(
            self.group_filter)
        self.line_edit_key_filter.textChanged.connect(self.search_para)
        self.tool_button_top.clicked.connect(self.top_window)
        self.tool_button_max.clicked.connect(self.max_window)
        self.tool_button_min.clicked.connect(self.min_window)
        self.tool_button_exit.clicked.connect(self.close_window)

        self.display_clip_board_database()
        # self.create_clip_board_database()

    # 添加内容
    def add_clip_content(self):
        add_content = self.clip_board.text()
        if add_content:
            result = None
            try:
                result = self.db_cursor.execute(
                    '''SELECT KEY FROM CLIPBOARD WHERE CONTENT = \'%s\' ''' %
                    add_content)
            except sqlite3.OperationalError as error:
                QMessageBox.information(self, '提示', str(error))
            if result:
                # 判断结果中是否有内容
                result_info = ''
                for row in result:
                    result_info += row[0] + '\n'
                if not result_info:
                    group_list = [gp for gp in self.get_database_dict()]
                    dialog = CreateContentDialog(self, group_list, add_content)
                    return_signal = dialog.exec_()
                    if return_signal == QDialog.Accepted:
                        group, key, content = dialog.add_content
                        self.add_clip_content_to_db(group, key, content)
                        self.display_clip_board_database()
                else:
                    result_info = '内容已存在以下关键字中:\n' + result_info
                    QMessageBox.information(self, '提示', result_info)

    # 添加内容到数据库
    def add_clip_content_to_db(self, group, key, content):
        self.db_cursor.execute(
            '''INSERT INTO CLIPBOARD (CONTENT_GROUP,KEY,CONTENT)
            VALUES (\'%s\', \'%s\', \'%s\')''' % (group, key, content))
        self.db_conn.commit()

    def close_window(self):
        QMainWindow.close(self)

    # 重载窗口关闭事件
    def closeEvent(self, event: QCloseEvent):
        if self.tray_icon.isVisible():
            origin_status_top = False
            if self.is_top:
                origin_status_top = True
                self.top_window()
            dialog = ExitDialog()
            dialog.exec_()
            if dialog.status == 1:
                QApplication.quit()
            elif dialog.status == 2:
                if origin_status_top:
                    self.top_window()
                self.hide()
                event.ignore()
            else:
                if origin_status_top:
                    self.top_window()
                event.ignore()
        # message = QMessageBox.warning(self, '退出', '''<p>确定要退出吗?''',
        #                               QMessageBox.Yes | QMessageBox.No)
        # if message == QMessageBox.Yes:
        #     event.accept()
        #     self.db_conn.close()
        # else:
        #     event.ignore()

    def create_clip_board_database(self):
        self.db_cursor.execute('''CREATE TABLE CLIPBOARD(
            CONTENT_GROUP TEXT NOT NULL,
            KEY TEXT NOT NULL,
            CONTENT TEXT NOT NULL);''')
        self.db_conn.commit()
        self.db_cursor.execute(
            '''INSERT INTO CLIPBOARD (CONTENT_GROUP,KEY,CONTENT)
            VALUES (\'TEST_GROUP\', \'TEST_KEY\', \'TEST_CONTENT\')''')
        self.db_conn.commit()

    # 删除所选的内容
    def delete_contents(self):
        items = self.tree_widget_content_view.selectedItems()
        if items:
            message = QMessageBox.warning(self, '删除', '确定要删除所选组和内容吗?',
                                          QMessageBox.Yes | QMessageBox.No)
            if message == QMessageBox.Yes:
                for item in items:
                    if item.parent():
                        self.delete_content_in_database(
                            item.parent().text(0), item.text(0), item.text(1))
                    else:
                        self.delete_group_in_database(item.text(0))
                self.display_clip_board_database()

    # 删除数据库中的一条内容
    def delete_content_in_database(self, group, key, content):
        self.db_cursor.execute('''DELETE FROM CLIPBOARD WHERE
            CONTENT_GROUP = \'%s\' AND
            KEY = \'%s\' AND 
            CONTENT = \'%s\'''' % (group, key, content))
        self.db_conn.commit()

    # 删除数据库中的组
    def delete_group_in_database(self, group_name):
        self.db_cursor.execute('''DELETE FROM CLIPBOARD WHERE
            CONTENT_GROUP = \'%s\'''' % group_name)
        self.db_conn.commit()

    # 把数据库内容显示出来
    def display_clip_board_database(self):
        dict_content = self.get_database_dict()
        self.tree_widget_content_view.clear()
        self.combo_box_group_name.clear()
        if dict_content:
            grouplist = [gp for gp in dict_content]
            grouplist.insert(0, '全部组')
            self.combo_box_group_name.addItems(grouplist)
        for group_name in dict_content:
            top_item = QTreeWidgetItem(self.tree_widget_content_view)
            top_item.setText(0, group_name)
            for key_name, content in dict_content[group_name]:
                child_item = QTreeWidgetItem(top_item)
                child_item.setText(0, key_name)
                child_item.setText(1, content)
        if self.tree_widget_content_view.topLevelItemCount():
            self.tree_widget_content_view.expandAll()

    # 获得所有的数据存储在字典中
    def get_database_dict(self):
        dict_content = dict()
        data_rows = self.db_cursor.execute(
            '''SELECT CONTENT_GROUP,KEY,CONTENT FROM CLIPBOARD''')
        for row in data_rows:
            if row[0] not in dict_content:
                dict_content[row[0]] = list()
            dict_content[row[0]].append((row[1], row[2]))
        return dict_content

    # 按组过滤
    def group_filter(self, index):
        text = self.combo_box_group_name.itemText(index)
        count = self.tree_widget_content_view.topLevelItemCount()
        for i in range(count):
            item = self.tree_widget_content_view.topLevelItem(i)
            if text == '全部组':
                item.setHidden(False)
            else:
                if text != item.text(0):
                    item.setHidden(True)
                else:
                    item.setHidden(False)

    # 设置热键
    def keyPressEvent(self, event: QKeyEvent):
        if event.key() == Qt.Key_V:
            if event.modifiers() == Qt.ControlModifier:
                self.add_clip_content()
                event.accept()
        if event.key() == Qt.Key_R:
            if event.modifiers() == Qt.ControlModifier:
                if self.tree_widget_content_view.topLevelItemCount():
                    self.tree_widget_content_view.collapseAll()
                event.accept()
        if event.key() == Qt.Key_E:
            if event.modifiers() == Qt.ControlModifier:
                if self.tree_widget_content_view.topLevelItemCount():
                    self.tree_widget_content_view.expandAll()
                event.accept()
        if event.key() == Qt.Key_Delete:
            self.delete_contents()
        else:
            event.ignore()

    # 最大化窗口
    def max_window(self):
        if self.isMaximized():
            self.showNormal()
            self.tool_button_max.setIcon(QIcon('.\\max.ico'))
        else:
            self.showMaximized()
            self.tool_button_max.setIcon(QIcon('.\\normal.ico'))

    # 最小化窗口
    def min_window(self):
        if not self.isMinimized():
            self.showMinimized()

    # 实现窗口拖动
    def mousePressEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton:
            self.on_move = True
            self.mouse_start_point = event.globalPos()
            self.window_geo = self.frameGeometry()
            if self.mouse_start_point.x() <= self.window_geo.left() + 9:
                if self.mouse_start_point.y() <= self.window_geo.top() + 9:
                    self.window_status = 'top_left'
                    self.setCursor(Qt.SizeFDiagCursor)
                elif self.mouse_start_point.y(
                ) >= self.window_geo.bottom() - 9:
                    self.window_status = 'bottom_left'
                    self.setCursor(Qt.SizeBDiagCursor)
                else:
                    self.window_status = 'left'
                    self.setCursor(Qt.SizeHorCursor)
            elif self.mouse_start_point.x() >= self.window_geo.right() - 9:
                if self.mouse_start_point.y() <= self.window_geo.top() + 9:
                    self.window_status = 'top_right'
                    self.setCursor(Qt.SizeBDiagCursor)
                elif self.mouse_start_point.y(
                ) >= self.window_geo.bottom() - 9:
                    self.window_status = 'bottom_right'
                    self.setCursor(Qt.SizeFDiagCursor)
                else:
                    self.window_status = 'right'
                    self.setCursor(Qt.SizeHorCursor)
            elif self.mouse_start_point.y() <= self.window_geo.top() + 9:
                self.window_status = 'top'
                self.setCursor(Qt.SizeVerCursor)
            elif self.mouse_start_point.y() >= self.window_geo.bottom() - 9:
                self.window_status = 'bottom'
                self.setCursor(Qt.SizeVerCursor)
            else:
                self.window_status = 'move'
        QMainWindow.mousePressEvent(self, event)

    def mouseMoveEvent(self, event: QMouseEvent):
        if event.buttons() and Qt.LeftButton and self.on_move:
            relative_pos = event.globalPos() - self.mouse_start_point
            if self.window_status == 'left':
                width = self.window_geo.right() - self.window_geo.left(
                ) - relative_pos.x()
                if width > self.window_width:
                    self.setGeometry(self.window_geo.left() + relative_pos.x(),
                                     self.window_geo.top(), width,
                                     self.window_geo.height())
            if self.window_status == 'right':
                width = self.window_geo.width() + relative_pos.x()
                if width > self.window_width:
                    self.setGeometry(self.window_geo.left(),
                                     self.window_geo.top(), width,
                                     self.window_geo.height())
            if self.window_status == 'top':
                height = self.window_geo.bottom() - self.window_geo.top(
                ) - relative_pos.y()
                if height > self.window_height:
                    self.setGeometry(self.window_geo.left(),
                                     self.window_geo.top() + relative_pos.y(),
                                     self.window_geo.width(), height)
            if self.window_status == 'bottom':
                height = self.window_geo.height() + relative_pos.y()
                if height > self.window_height:
                    self.setGeometry(self.window_geo.left(),
                                     self.window_geo.top(),
                                     self.window_geo.width(), height)
            if self.window_status == 'top_left':
                width = self.window_geo.right() - self.window_geo.left(
                ) - relative_pos.x()
                height = self.window_geo.bottom() - self.window_geo.top(
                ) - relative_pos.y()
                if width > self.window_width and height > self.window_height:
                    self.setGeometry(self.window_geo.left() + relative_pos.x(),
                                     self.window_geo.top() + relative_pos.y(),
                                     width, height)
            if self.window_status == 'top_right':
                width = self.window_geo.width() + relative_pos.x()
                height = self.window_geo.bottom() - self.window_geo.top(
                ) - relative_pos.y()
                if width > self.window_width and height > self.window_height:
                    self.setGeometry(self.window_geo.left(),
                                     self.window_geo.top() + relative_pos.y(),
                                     width, height)
            if self.window_status == 'bottom_right':
                width = self.window_geo.width() + relative_pos.x()
                height = self.window_geo.height() + relative_pos.y()
                if width > self.window_width and height > self.window_height:
                    self.setGeometry(self.window_geo.left(),
                                     self.window_geo.top(), width, height)
            if self.window_status == 'bottom_left':
                width = self.window_geo.right() - self.window_geo.left(
                ) - relative_pos.x()
                height = self.window_geo.height() + relative_pos.y()
                if width > self.window_width and height > self.window_height:
                    self.setGeometry(self.window_geo.left() + relative_pos.x(),
                                     self.window_geo.top(), width, height)
            if self.window_status == 'move':
                self.move(self.window_geo.topLeft() + relative_pos)
        QMainWindow.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton:
            # 改变移动状态
            self.window_status = ''
            self.on_move = False
            self.mouse_start_point = None
            self.window_geo = None
            self.setCursor(Qt.ArrowCursor)
        QMainWindow.mouseReleaseEvent(self, event)

    # 单击托盘时的响应
    def restore_win(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            if self.isHidden():
                self.show()
            self.activateWindow()

    # 搜索参数并显示在参数窗口里
    def search_para(self, key_name):
        text = self.combo_box_group_name.currentText()
        index = self.combo_box_group_name.currentIndex() - 1
        pattern = re.compile('.*' + key_name + '.*', re.I)
        if text == '全部组':
            count = self.tree_widget_content_view.topLevelItemCount()
            for i in range(count):
                num_key_in_show = 0
                item = self.tree_widget_content_view.topLevelItem(i)
                child_count = item.childCount()
                for child_index in range(child_count):
                    kn = item.child(child_index).text(0)
                    if re.match(pattern, kn):
                        item.child(child_index).setHidden(False)
                        num_key_in_show += 1
                    else:
                        item.child(child_index).setHidden(True)
                if num_key_in_show == 0:
                    item.setHidden(True)
                else:
                    item.setHidden(False)
        else:
            num_key_in_show = 0
            item = self.tree_widget_content_view.topLevelItem(index)
            child_count = item.childCount()
            for child_index in range(child_count):
                kn = item.child(child_index).text(0)
                if re.match(pattern, kn):
                    item.child(child_index).setHidden(False)
                    num_key_in_show += 1
                else:
                    item.child(child_index).setHidden(True)
            if num_key_in_show == 0:
                item.setHidden(True)
            else:
                item.setHidden(False)
        self.tree_widget_content_view.expandAll()

    # 将选中的内容添加到剪贴板中
    def item_click_response(self, item):
        if self.combo_box_item_click_response.currentText() == '编辑':
            if item.parent():
                group_list = [gp for gp in self.get_database_dict()]
                old_content = (item.parent().text(0), item.text(0),
                               item.text(1))
                dialog = EditContentDialog(self, group_list, old_content)
                return_signal = dialog.exec_()
                if return_signal == QDialog.Accepted:
                    if old_content != dialog.add_content:
                        old_group, old_key, old_content = old_content
                        group, key, content = dialog.add_content
                        self.db_cursor.execute(
                            '''UPDATE CLIPBOARD SET CONTENT_GROUP = \'%s\', 
                            KEY = \'%s\', CONTENT = \'%s\' 
                            WHERE CONTENT_GROUP = \'%s\' AND 
                            KEY = \'%s\' AND 
                            CONTENT = \'%s\'''' %
                            (group, key, content, old_group, old_key,
                             old_content))
                        self.db_conn.commit()
                        self.display_clip_board_database()
        elif self.combo_box_item_click_response.currentText() == '复制':
            if item.parent():
                self.clip_board.setText(item.text(1))
        elif self.combo_box_item_click_response.currentText() == '复制并粘贴':
            if item.parent():
                self.clip_board.setText(item.text(1))
                focus_win_hwnd = xx = win32gui.GetFocus()
                hwnd_title = dict()

                def get_all_window(hwnd, mouse):

                    if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and\
                            win32gui.IsWindowVisible(hwnd):
                        hwnd_title.update({hwnd: win32gui.GetWindowText(hwnd)})

                win32gui.EnumWindows(get_all_window, 1)
                if hwnd_title:
                    hwnd_list = [h for h, t in hwnd_title.items()]
                    index = hwnd_list.index(focus_win_hwnd)
                    if self.is_top:
                        if index < len(hwnd_list) - 2:
                            focus_win_hwnd = hwnd_list[index + 2]
                            win32gui.SetForegroundWindow(focus_win_hwnd)
                            win32api.keybd_event(17, 0, 0, 0)
                            win32api.keybd_event(86, 0, 0, 0)
                            win32api.keybd_event(86, 0,
                                                 win32con.KEYEVENTF_KEYUP, 0)
                            win32api.keybd_event(17, 0,
                                                 win32con.KEYEVENTF_KEYUP, 0)
                            win32api.keybd_event(13, 0, 0, 0)
                            win32api.keybd_event(13, 0,
                                                 win32con.KEYEVENTF_KEYUP, 0)
                    else:
                        if index < len(hwnd_list) - 1:
                            focus_win_hwnd = hwnd_list[index + 1]
                            win32gui.SetForegroundWindow(focus_win_hwnd)
                            win32api.keybd_event(17, 0, 0, 0)
                            win32api.keybd_event(86, 0, 0, 0)
                            win32api.keybd_event(86, 0,
                                                 win32con.KEYEVENTF_KEYUP, 0)
                            win32api.keybd_event(17, 0,
                                                 win32con.KEYEVENTF_KEYUP, 0)
                            win32api.keybd_event(13, 0, 0, 0)
                            win32api.keybd_event(13, 0,
                                                 win32con.KEYEVENTF_KEYUP, 0)
        else:
            pass

    def top_window(self):
        if self.is_top:
            self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint
                                | Qt.MSWindowsOwnDC)
            self.show()
            self.is_top = False
            self.tool_button_top.setIcon(QIcon('.\\top.ico'))
        else:
            self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint
                                | Qt.WindowStaysOnTopHint)
            self.show()
            self.is_top = True
            self.tool_button_top.setIcon(QIcon('.\\un_top.ico'))

    # 汉化
    def translate(self):
        self.setWindowTitle("MainWindow")
        self.tool_button_top.setToolTip('置顶')
        # self.tool_button_back.setToolTip('后台运行')
        self.tool_button_min.setToolTip('最小化')
        self.tool_button_max.setToolTip('最大化')
        self.tool_button_exit.setToolTip('关闭')
        self.line_edit_key_filter.setPlaceholderText("筛选器")
        self.tree_widget_content_view.headerItem().setText(0, '关键字')
        self.tree_widget_content_view.headerItem().setText(1, '内容')