#!/usr/bin/env python3
"""
TopHub数据查看器 - PySide5界面应用程序
用于显示SQLite数据库中的TopHub抓取数据
"""

import sys
import os
import sqlite3
import webbrowser
from datetime import datetime
from loguru import logger
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QVBoxLayout, 
    QHBoxLayout, QWidget, QLabel, QLineEdit, QPushButton, QComboBox, 
    QGroupBox, QStatusBar, QMenuBar, QMenu, QMessageBox, QHeaderView,
    QAbstractItemView, QDialog, QFormLayout, QTextEdit, QInputDialog
)
from PySide6.QtCore import Qt, QUrl, QTimer, QEvent
from PySide6.QtGui import QAction, QFont, QIcon, QDesktopServices, QClipboard


class DatabaseViewer(QMainWindow):
    """主窗口类，用于显示数据库内容"""
    
    def __init__(self):
        super().__init__()
        # 获取当前脚本所在目录的数据库文件路径
        script_dir = os.path.dirname(os.path.abspath(__file__))
        self.db_path = os.path.join(script_dir, "tophub_data.db")
        
        # 检查数据库文件是否存在
        if not os.path.exists(self.db_path):
            QMessageBox.critical(self, "错误", f"数据库文件不存在: {self.db_path}")
            sys.exit(1)
            
        self.init_ui()
        self.load_data()
        
    def init_ui(self):
        """初始化用户界面"""
        # 设置窗口属性
        self.setWindowTitle("TopHub数据查看器")
        self.setGeometry(100, 100, 1200, 800)
        
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 创建搜索和筛选区域
        filter_group = QGroupBox("搜索和筛选")
        filter_layout = QHBoxLayout(filter_group)
        
        # 搜索框
        self.search_edit = QLineEdit()
        self.search_edit.setPlaceholderText("输入搜索关键词...")
        self.search_edit.textChanged.connect(self.filter_data)
        filter_layout.addWidget(QLabel("搜索:"))
        filter_layout.addWidget(self.search_edit)
        
        # 分类筛选
        self.category_combo = QComboBox()
        self.category_combo.addItem("全部分类")
        self.category_combo.currentTextChanged.connect(self.filter_data)
        filter_layout.addWidget(QLabel("分类:"))
        filter_layout.addWidget(self.category_combo)
        
        # 刷新按钮
        self.refresh_button = QPushButton("刷新数据")
        self.refresh_button.clicked.connect(self.load_data)
        filter_layout.addWidget(self.refresh_button)
        
        # 批量删除相关控件
        self.select_by_keyword_button = QPushButton("按关键字选中")
        self.select_by_keyword_button.clicked.connect(self.select_by_keyword)
        filter_layout.addWidget(self.select_by_keyword_button)
        
        self.delete_selected_button = QPushButton("删除选中项")
        self.delete_selected_button.clicked.connect(self.delete_selected_items)
        filter_layout.addWidget(self.delete_selected_button)
        
        # 标记感兴趣按钮
        self.mark_interested_button = QPushButton("标记为感兴趣")
        self.mark_interested_button.clicked.connect(self.mark_as_interested)
        filter_layout.addWidget(self.mark_interested_button)
        
        # 添加筛选区域到主布局
        main_layout.addWidget(filter_group)
        
        # 创建分类统计显示区域
        self.category_stats_group = QGroupBox("分类统计")
        self.category_stats_layout = QHBoxLayout(self.category_stats_group)
        self.category_stats_label = QLabel("暂无数据")
        self.category_stats_layout.addWidget(self.category_stats_label)
        main_layout.addWidget(self.category_stats_group)
        
        # 创建表格
        self.table = QTableWidget()
        self.table.setColumnCount(6)  # 保留6列，最后一列显示评分
        self.table.setHorizontalHeaderLabels(["ID", "标题", "链接", "分类", "来源日期", "评分"])
        
        # 设置表格属性
        self.table.setAlternatingRowColors(True)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.setSortingEnabled(True)
        
        # 设置表格选择模式
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        
        # 设置列宽
        header = self.table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeToContents)  # ID列
        header.setSectionResizeMode(1, QHeaderView.Interactive)  # 标题列 - 允许用户调整
        self.table.setColumnWidth(1, 400)  # 设置标题列默认宽度为400像素
        header.setSectionResizeMode(2, QHeaderView.ResizeToContents)  # 链接列
        header.setSectionResizeMode(3, QHeaderView.ResizeToContents)  # 分类列
        header.setSectionResizeMode(4, QHeaderView.ResizeToContents)  # 时间列
        header.setSectionResizeMode(5, QHeaderView.ResizeToContents)  # 评分列
        
        # 启用链接点击
        self.table.cellClicked.connect(self.on_cell_clicked)
        
        # 安装事件过滤器以处理链接点击
        self.table.viewport().installEventFilter(self)
        
        # 启用右键菜单
        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(self.show_context_menu)
        
        # 添加表格到主布局
        main_layout.addWidget(self.table)
        
        # 创建状态栏
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        
        # 创建菜单栏
        self.create_menu_bar()
        
    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = self.menuBar()
        
        # 文件菜单
        file_menu = menubar.addMenu("文件")
        
        # 刷新动作
        refresh_action = QAction("刷新数据", self)
        refresh_action.setShortcut("F5")
        refresh_action.triggered.connect(self.load_data)
        file_menu.addAction(refresh_action)
        
        # 退出动作
        exit_action = QAction("退出", self)
        exit_action.setShortcut("Ctrl+Q")
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)
        
        # 帮助菜单
        help_menu = menubar.addMenu("帮助")
        
        # 关于动作
        about_action = QAction("关于", self)
        about_action.triggered.connect(self.show_about)
        help_menu.addAction(about_action)
        
    def load_data(self):
        """从数据库加载数据"""
        try:
            # 连接数据库
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 检查表是否存在
            cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='articles'")
            if not cursor.fetchone():
                QMessageBox.critical(self, "错误", "数据库中不存在articles表")
                conn.close()
                return
            
            # 查询数据 - 修改为查询score字段而不是is_interested
            cursor.execute('''
            SELECT id, title, url, category, source_date, score 
            FROM articles 
            ORDER BY id DESC
            ''')
            
            rows = cursor.fetchall()
            conn.close()
            
            # 更新表格
            self.table.setRowCount(len(rows))
            
            # 获取所有分类和统计信息
            categories = set()
            category_counts = {}  # 用于存储每个分类的数量
            
            for row_idx, row in enumerate(rows):
                id_val, title, url, category, source_date, score = row
                
                # 添加到分类集合和统计字典
                if category:
                    categories.add(category)
                    category_counts[category] = category_counts.get(category, 0) + 1
                else:
                    # 处理空分类的情况
                    category_counts["未分类"] = category_counts.get("未分类", 0) + 1
                
                # 设置表格项
                self.table.setItem(row_idx, 0, QTableWidgetItem(str(id_val)))
                self.table.setItem(row_idx, 1, QTableWidgetItem(title))
                
                # 链接项 - 设置为蓝色并加下划线
                link_item = QTableWidgetItem(url if url else "")
                if url:
                    link_item.setForeground(Qt.blue)
                    link_item.setFont(QFont("", -1, QFont.Bold))
                self.table.setItem(row_idx, 2, link_item)
                
                self.table.setItem(row_idx, 3, QTableWidgetItem(category if category else "未分类"))
                self.table.setItem(row_idx, 4, QTableWidgetItem(source_date))
                
                # 感兴趣状态项
                score_item = QTableWidgetItem(str(score))
                # 根据分数设置颜色
                if score >= 8:
                    score_item.setForeground(Qt.green)
                    score_item.setFont(QFont("", -1, QFont.Bold))
                elif score >= 6:
                    score_item.setForeground(Qt.blue)
                elif score <= 3:
                    score_item.setForeground(Qt.red)
                self.table.setItem(row_idx, 5, score_item)
            
            # 更新分类下拉框
            current_category = self.category_combo.currentText()
            self.category_combo.clear()
            self.category_combo.addItem("全部分类")
            for cat in sorted(categories):
                self.category_combo.addItem(cat)
            
            # 恢复之前选择的分类
            index = self.category_combo.findText(current_category)
            if index >= 0:
                self.category_combo.setCurrentIndex(index)
            
            # 更新分类统计显示
            self.update_category_stats(category_counts)
            
            # 更新状态栏
            self.status_bar.showMessage(f"已加载 {len(rows)} 条记录")
            
        except sqlite3.Error as e:
            logger.error(f"数据库操作出错: {str(e)}")
            QMessageBox.critical(self, "数据库错误", f"数据库操作出错: {str(e)}")
            self.status_bar.showMessage("加载数据失败")
        except Exception as e:
            logger.error(f"加载数据时出错: {str(e)}")
            QMessageBox.critical(self, "错误", f"加载数据时出错: {str(e)}")
            self.status_bar.showMessage("加载数据失败")
            
    def update_category_stats(self, category_counts):
        """更新分类统计显示"""
        if not category_counts:
            self.category_stats_label.setText("暂无数据")
            return
        
        # 按数量降序排列分类
        sorted_categories = sorted(category_counts.items(), key=lambda x: x[1], reverse=True)
        
        # 构建统计信息文本
        stats_text = " | ".join([f"{category}: {count}" for category, count in sorted_categories])
        
        # 如果文本过长，进行截断并添加提示
        if len(stats_text) > 200:
            stats_text = stats_text[:200] + "... (更多分类请查看完整数据)"
        
        self.category_stats_label.setText(stats_text)
        self.category_stats_label.setToolTip(" | ".join([f"{category}: {count}" for category, count in sorted_categories]))
            
    def update_category_stats_after_filter(self):
        """在筛选后更新分类统计显示"""
        # 统计可见行的分类
        category_counts = {}
        
        for row in range(self.table.rowCount()):
            # 跳过隐藏的行
            if self.table.isRowHidden(row):
                continue
                
            # 获取分类项
            category_item = self.table.item(row, 3)
            if category_item:
                category = category_item.text()
                category_counts[category] = category_counts.get(category, 0) + 1
            else:
                category_counts["未分类"] = category_counts.get("未分类", 0) + 1
        
        # 更新分类统计显示
        self.update_category_stats(category_counts)
            
    def filter_data(self):
        """根据搜索条件和分类筛选数据"""
        search_text = self.search_edit.text().lower()
        selected_category = self.category_combo.currentText()
        
        # 遍历所有行
        for row in range(self.table.rowCount()):
            show_row = True
            
            # 检查搜索条件
            if search_text:
                text_match = False
                for col in range(1, 6):  # 检查标题、链接、分类、日期、感兴趣列
                    item = self.table.item(row, col)
                    if item and search_text in item.text().lower():
                        text_match = True
                        break
                show_row = show_row and text_match
            
            # 检查分类条件
            if selected_category != "全部分类":
                category_item = self.table.item(row, 3)
                category_match = category_item and category_item.text() == selected_category
                show_row = show_row and category_match
            
            # 显示或隐藏行
            self.table.setRowHidden(row, not show_row)
        
        # 计算可见行数
        visible_count = sum(1 for row in range(self.table.rowCount()) 
                           if not self.table.isRowHidden(row))
        self.status_bar.showMessage(f"显示 {visible_count}/{self.table.rowCount()} 条记录")
        
        # 重新计算并显示分类统计
        self.update_category_stats_after_filter()
        
    def eventFilter(self, obj, event):
        """事件过滤器，用于处理链接点击而不触发行选择"""
        if obj == self.table.viewport() and event.type() == QEvent.MouseButtonPress:
            # 获取点击位置
            pos = event.position()
            # 获取点击位置的行和列
            row = self.table.rowAt(int(pos.y()))
            column = self.table.columnAt(int(pos.x()))
            
            # 如果点击的是链接列（第2列，索引为2）
            if column == 2 and row >= 0:
                item = self.table.item(row, column)
                if item and item.text() and item.text().startswith("http"):
                    # 直接打开链接
                    webbrowser.open(item.text())
                    # 返回True表示事件已处理，不再传递给原始处理器
                    # 这样就不会触发行选择，避免鼠标跳动
                    return True
        
        # 其他事件交给原始处理器处理
        return super().eventFilter(obj, event)
        
    def on_cell_clicked(self, row, column):
        """处理单元格点击事件"""
        # 链接列的点击已经由eventFilter处理，这里不再处理
        # 只处理非链接列的点击，保持原有选择行为
        if column != 2:
            # 可以在这里添加其他列的点击处理逻辑
            pass
                    
    def show_context_menu(self, position):
        """显示右键菜单"""
        # 获取点击位置的行
        row = self.table.rowAt(position.y())
        if row < 0:
            return
            
        # 选中该行
        self.table.selectRow(row)
        
        # 创建右键菜单
        menu = QMenu(self)
        
        # 添加"增加评分(+1)"动作
        increase_score_action = QAction("增加评分(+1)", self)
        increase_score_action.triggered.connect(self.increase_score)
        menu.addAction(increase_score_action)
        
        # 添加"减少评分(-1)"动作
        decrease_score_action = QAction("减少评分(-1)", self)
        decrease_score_action.triggered.connect(self.decrease_score)
        menu.addAction(decrease_score_action)
        
        # 添加分隔线
        menu.addSeparator()
        
        # 添加"复制信息"动作
        copy_info_action = QAction("复制信息", self)
        copy_info_action.triggered.connect(self.copy_info)
        menu.addAction(copy_info_action)
        
        # 添加分隔线
        menu.addSeparator()
        
        # 添加"删除"动作
        delete_action = QAction("删除选中项", self)
        delete_action.triggered.connect(self.delete_selected_items)
        menu.addAction(delete_action)
        
        # 显示菜单
        menu.exec_(self.table.mapToGlobal(position))
        
    def copy_info(self):
        """复制选中行的标题、链接、日期等信息"""
        # 获取选中的行
        selected_rows = set()
        for item in self.table.selectedItems():
            selected_rows.add(item.row())
            
        # 如果没有选中的行，直接返回
        if not selected_rows:
            QMessageBox.information(self, "提示", "请先选中要复制信息的行")
            return
            
        # 收集所有选中行的信息
        all_info = []
        for row in sorted(selected_rows):
            # 获取标题、链接、日期
            title_item = self.table.item(row, 1)
            url_item = self.table.item(row, 2)
            date_item = self.table.item(row, 4)
            
            title = title_item.text() if title_item else ""
            url = url_item.text() if url_item else ""
            date = date_item.text() if date_item else ""
            
            # 按照要求的格式组合信息："日期 标题\n链接"
            info = f"{date} {title}\n{url}".strip()
            all_info.append(info)
            
        # 将所有信息用换行符连接
        clipboard_text = "\n".join(all_info)
        
        # 复制到剪贴板
        clipboard = QApplication.clipboard()
        clipboard.setText(clipboard_text)
        
        # 更新状态栏
        self.status_bar.showMessage(f"已复制 {len(selected_rows)} 行信息到剪贴板")
        
    def show_about(self):
        """显示关于对话框"""
        about_text = """
        <h3>TopHub数据查看器</h3>
        <p>版本: 1.0</p>
        <p>用于查看TopHub网站抓取数据的PySide5应用程序</p>
        <p>功能特性:</p>
        <ul>
            <li>显示SQLite数据库中的抓取数据</li>
            <li>支持点击链接在浏览器中打开</li>
            <li>支持搜索和分类筛选</li>
            <li>支持排序功能</li>
            <li>支持标记感兴趣的项目</li>
        </ul>
        """
        QMessageBox.about(self, "关于", about_text)
        
    def select_by_keyword(self):
        """按关键字选中行"""
        # 弹出输入对话框获取关键字
        keyword, ok = QInputDialog.getText(self, "按关键字选中", "请输入关键字:")
        
        if not ok or not keyword:
            return
            
        keyword = keyword.lower()
        selected_count = 0
        
        # 遍历所有可见行
        for row in range(self.table.rowCount()):
            # 跳过隐藏的行
            if self.table.isRowHidden(row):
                continue
                
            # 检查该行是否包含关键字
            match = False
            for col in range(self.table.columnCount()):
                item = self.table.item(row, col)
                if item and keyword in item.text().lower():
                    match = True
                    break
            
            # 如果匹配，则选中该行
            if match:
                self.table.selectRow(row)
                selected_count += 1
                
        # 更新状态栏
        self.status_bar.showMessage(f"已选中 {selected_count} 行")
        
    def delete_selected_items(self):
        """删除选中的项目"""
        # 获取选中的行
        selected_rows = set()
        for item in self.table.selectedItems():
            selected_rows.add(item.row())
            
        # 如果没有选中的行，直接返回
        if not selected_rows:
            QMessageBox.information(self, "提示", "请先选中要删除的行")
            return
            
        # 弹出确认对话框
        reply = QMessageBox.question(
            self, 
            "确认删除", 
            f"确定要删除选中的 {len(selected_rows)} 行数据吗？此操作不可撤销！",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )
        
        if reply == QMessageBox.No:
            return
            
        try:
            # 连接数据库
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 删除选中的行
            deleted_count = 0
            for row in sorted(selected_rows, reverse=True):  # 从后往前删除，避免索引变化
                # 获取ID
                id_item = self.table.item(row, 0)
                if id_item:
                    article_id = id_item.text()
                    # 从数据库中删除
                    cursor.execute("DELETE FROM articles WHERE id = ?", (article_id,))
                    # 从表格中移除行
                    self.table.removeRow(row)
                    deleted_count += 1
                    
            # 提交更改
            conn.commit()
            conn.close()
            
            # 更新状态栏
            self.status_bar.showMessage(f"已删除 {deleted_count} 行数据")
            
            # 重新加载数据以更新分类统计
            self.load_data()
            
        except sqlite3.Error as e:
            logger.error(f"删除数据时出错: {str(e)}")
            QMessageBox.critical(self, "数据库错误", f"删除数据时出错: {str(e)}")
            self.status_bar.showMessage("删除失败")
        except Exception as e:
            logger.error(f"删除数据时出错: {str(e)}")
            QMessageBox.critical(self, "错误", f"删除数据时出错: {str(e)}")
            self.status_bar.showMessage("删除失败")
            
    def mark_as_interested(self):
        """将选中的项目标记为感兴趣"""
        # 获取选中的行
        selected_rows = set()
        for item in self.table.selectedItems():
            selected_rows.add(item.row())
            
        # 如果没有选中的行，直接返回
        if not selected_rows:
            QMessageBox.information(self, "提示", "请先选中要标记的行")
            return
            
        # 弹出确认对话框
        reply = QMessageBox.question(
            self, 
            "确认标记", 
            f"确定要将选中的 {len(selected_rows)} 行标记为感兴趣吗？",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.Yes
        )
        
        if reply == QMessageBox.No:
            return
            
        try:
            # 连接数据库
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 更新选中的行
            updated_count = 0
            for row in selected_rows:
                # 获取ID
                id_item = self.table.item(row, 0)
                if id_item:
                    article_id = id_item.text()
                    # 更新数据库中的is_interested字段
                    cursor.execute("UPDATE articles SET is_interested = 1 WHERE id = ?", (article_id,))
                    
                    # 更新表格中的显示
                    interested_item = QTableWidgetItem("是")
                    interested_item.setForeground(Qt.green)
                    interested_item.setFont(QFont("", -1, QFont.Bold))
                    self.table.setItem(row, 5, interested_item)
                    
                    updated_count += 1
                    
            # 提交更改
            conn.commit()
            conn.close()
            
            # 更新状态栏
            self.status_bar.showMessage(f"已标记 {updated_count} 行为感兴趣")
            
        except sqlite3.Error as e:
            logger.error(f"标记数据时出错: {str(e)}")
            QMessageBox.critical(self, "数据库错误", f"标记数据时出错: {str(e)}")
            self.status_bar.showMessage("标记失败")
        except Exception as e:
            logger.error(f"标记数据时出错: {str(e)}")
            QMessageBox.critical(self, "错误", f"标记数据时出错: {str(e)}")
            self.status_bar.showMessage("标记失败")


    def mark_as_not_interested(self):
        """将选中的项目标记为不感兴趣"""
        # 获取选中的行
        selected_rows = set()
        for item in self.table.selectedItems():
            selected_rows.add(item.row())
            
        # 如果没有选中的行，直接返回
        if not selected_rows:
            QMessageBox.information(self, "提示", "请先选中要标记的行")
            return
            
        # 弹出确认对话框
        reply = QMessageBox.question(
            self, 
            "确认标记", 
            f"确定要将选中的 {len(selected_rows)} 行标记为不感兴趣吗？",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.Yes
        )
        
        if reply == QMessageBox.No:
            return
            
        try:
            # 连接数据库
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 更新选中的行
            updated_count = 0
            for row in selected_rows:
                # 获取ID
                id_item = self.table.item(row, 0)
                if id_item:
                    article_id = id_item.text()
                    # 更新数据库中的is_interested字段
                    cursor.execute("UPDATE articles SET is_interested = 0 WHERE id = ?", (article_id,))
                    
                    # 更新表格中的显示
                    interested_item = QTableWidgetItem("否")
                    # 不感兴趣项使用普通字体和颜色
                    self.table.setItem(row, 5, interested_item)
                    
                    updated_count += 1
                    
            # 提交更改
            conn.commit()
            conn.close()
            
            # 更新状态栏
            self.status_bar.showMessage(f"已标记 {updated_count} 行为不感兴趣")
            
        except sqlite3.Error as e:
            logger.error(f"标记数据时出错: {str(e)}")
            QMessageBox.critical(self, "数据库错误", f"标记数据时出错: {str(e)}")
            self.status_bar.showMessage("标记失败")
        except Exception as e:
            logger.error(f"标记数据时出错: {str(e)}")
            QMessageBox.critical(self, "错误", f"标记数据时出错: {str(e)}")
            self.status_bar.showMessage("标记失败")


    def increase_score(self):
        """增加选中项目的评分(+1)"""
        # 获取选中的行
        selected_rows = set()
        for item in self.table.selectedItems():
            selected_rows.add(item.row())
            
        # 如果没有选中的行，直接返回
        if not selected_rows:
            QMessageBox.information(self, "提示", "请先选中要增加评分的行")
            return
            
        try:
            # 连接数据库
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 更新选中的行
            updated_count = 0
            for row in selected_rows:
                # 获取ID
                id_item = self.table.item(row, 0)
                if id_item:
                    article_id = id_item.text()
                    # 获取当前分数
                    cursor.execute("SELECT score FROM articles WHERE id = ?", (article_id,))
                    result = cursor.fetchone()
                    if result:
                        current_score = result[0]
                        # 增加分数，但不超过10
                        new_score = min(current_score + 1, 10)
                        # 更新数据库中的score字段
                        cursor.execute("UPDATE articles SET score = ? WHERE id = ?", (new_score, article_id))
                        
                        # 更新表格中的显示
                        score_item = QTableWidgetItem(str(new_score))
                        # 根据分数设置颜色
                        if new_score >= 8:
                            score_item.setForeground(Qt.green)
                            score_item.setFont(QFont("", -1, QFont.Bold))
                        elif new_score >= 6:
                            score_item.setForeground(Qt.blue)
                        elif new_score <= 3:
                            score_item.setForeground(Qt.red)
                        self.table.setItem(row, 5, score_item)
                        
                        updated_count += 1
                    
            # 提交更改
            conn.commit()
            conn.close()
            
            # 更新状态栏
            self.status_bar.showMessage(f"已增加 {updated_count} 行的评分")
            
        except sqlite3.Error as e:
            logger.error(f"增加评分时出错: {str(e)}")
            QMessageBox.critical(self, "数据库错误", f"增加评分时出错: {str(e)}")
            self.status_bar.showMessage("增加评分失败")
        except Exception as e:
            logger.error(f"增加评分时出错: {str(e)}")
            QMessageBox.critical(self, "错误", f"增加评分时出错: {str(e)}")
            self.status_bar.showMessage("增加评分失败")

    def decrease_score(self):
        """减少选中项目的评分(-1)"""
        # 获取选中的行
        selected_rows = set()
        for item in self.table.selectedItems():
            selected_rows.add(item.row())
            
        # 如果没有选中的行，直接返回
        if not selected_rows:
            QMessageBox.information(self, "提示", "请先选中要减少评分的行")
            return
            
        try:
            # 连接数据库
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 更新选中的行
            updated_count = 0
            for row in selected_rows:
                # 获取ID
                id_item = self.table.item(row, 0)
                if id_item:
                    article_id = id_item.text()
                    # 获取当前分数
                    cursor.execute("SELECT score FROM articles WHERE id = ?", (article_id,))
                    result = cursor.fetchone()
                    if result:
                        current_score = result[0]
                        # 减少分数，但不低于0
                        new_score = max(current_score - 1, 0)
                        # 更新数据库中的score字段
                        cursor.execute("UPDATE articles SET score = ? WHERE id = ?", (new_score, article_id))
                        
                        # 更新表格中的显示
                        score_item = QTableWidgetItem(str(new_score))
                        # 根据分数设置颜色
                        if new_score >= 8:
                            score_item.setForeground(Qt.green)
                            score_item.setFont(QFont("", -1, QFont.Bold))
                        elif new_score >= 6:
                            score_item.setForeground(Qt.blue)
                        elif new_score <= 3:
                            score_item.setForeground(Qt.red)
                        self.table.setItem(row, 5, score_item)
                        
                        updated_count += 1
                    
            # 提交更改
            conn.commit()
            conn.close()
            
            # 更新状态栏
            self.status_bar.showMessage(f"已减少 {updated_count} 行的评分")
            
        except sqlite3.Error as e:
            logger.error(f"减少评分时出错: {str(e)}")
            QMessageBox.critical(self, "数据库错误", f"减少评分时出错: {str(e)}")
            self.status_bar.showMessage("减少评分失败")
        except Exception as e:
            logger.error(f"减少评分时出错: {str(e)}")
            QMessageBox.critical(self, "错误", f"减少评分时出错: {str(e)}")
            self.status_bar.showMessage("减少评分失败")


def main():
    """主函数"""
    app = QApplication(sys.argv)
    
    # 设置应用程序属性
    app.setApplicationName("TopHub数据查看器")
    app.setOrganizationName("TopHub")
    
    # 创建并显示主窗口
    viewer = DatabaseViewer()
    viewer.show()
    
    # 运行应用程序
    sys.exit(app.exec())


if __name__ == "__main__":
    main()