import sys import os import re import datetime from PyQt6.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QPushButton, QLabel, QListWidget, QFileDialog, QMessageBox, QLineEdit, QFormLayout, QDialog, QDialogButtonBox ) from PyQt6.QtGui import QIcon from PyQt6 import uic import config from exportbooknotes import BookNotesExporter from booklist_parse import BookListManager class ConfigDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("配置参数") layout = QFormLayout(self) self.inputs = {} for attr in dir(config): if attr.isupper(): val = getattr(config, attr) inp = QLineEdit(str(val)) layout.addRow(attr, inp) self.inputs[attr] = inp buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) buttons.accepted.connect(self.accept) buttons.rejected.connect(self.reject) layout.addWidget(buttons) def get_config(self): return {k: v.text() for k, v in self.inputs.items()} class IBookExportApp(QWidget): def __init__(self): super().__init__() # 加载 UI 文件 ui_file = os.path.join(os.path.dirname(__file__), 'ibook_export_app.ui') uic.loadUi(ui_file, self) # 设置窗口标题 self.setWindowTitle("notesExporter") # 设置窗口图标 if os.path.exists(config.APP_ICON): self.setWindowIcon(QIcon(config.APP_ICON)) # 初始化数据 self.exporter = BookNotesExporter(config) self.manager = BookListManager(plist_path=config.LOCAL_BOOKS_PLIST, db_path=config.LOCAL_LIBRARY_DB) self.booksinfo = self.manager.get_books_info() self.last_open_times = self.manager.get_books_last_open() self.assetid2name = {} self.assetid2lastopen = {} for assetid, info in self.booksinfo.items(): name = info.get('displayname') or info.get('itemname') or assetid if '-' in name: name = name.split('-', 1)[0].strip() self.assetid2name[assetid] = name ts = self.last_open_times.get(assetid, {}).get('last_open', 0) self.assetid2lastopen[assetid] = ts sorted_assetids = sorted(self.assetid2name.keys(), key=lambda aid: self.assetid2lastopen[aid], reverse=True) self.sorted_assetids = sorted_assetids # 填充书籍列表 for aid in sorted_assetids: self.listwidget.addItem(f"{self.assetid2name[aid]} [{self.assetid2lastopen[aid]}]") # 连接信号 self.export_btn.clicked.connect(self.export_notes) self.config_btn.clicked.connect(self.show_config) # 回车直接导出(使用事件过滤器) self.listwidget.installEventFilter(self) def eventFilter(self, obj, event): from PyQt6.QtCore import QEvent, Qt if obj == self.listwidget and event.type() == QEvent.Type.KeyPress: # 检查回车键(Enter/Return) if event.key() in (0x01000004, 0x01000005): # Qt.Key_Return, Qt.Key_Enter self.export_notes() return True return super().eventFilter(obj, event) def show_config(self): dlg = ConfigDialog(self) if dlg.exec(): new_config = dlg.get_config() # 这里只是演示,实际可写入config.py或动态加载 QMessageBox.information(self, "提示", "配置已更新(仅本次运行有效)") def export_notes(self): from exportbooknotes import sync_source_files sync_source_files(config) idx = self.listwidget.currentRow() if idx < 0: QMessageBox.warning(self, "提示", "请先选择一本书") return assetid = self.sorted_assetids[idx] selected_booksnote = self.exporter.build_booksnote(bookid=assetid) selected_booksinfo = {assetid: self.booksinfo.get(assetid, {})} bookname = selected_booksinfo[assetid].get("displayname") or selected_booksinfo[assetid].get("itemname") or assetid ts = datetime.datetime.now().strftime('%m%d%H%M') shortname = re.split(r'[.::_\【\[\((]', bookname)[0].strip() export_dir = getattr(config, "EXPORT_NOTES_DIR", os.getcwd()) if not os.path.exists(export_dir): os.makedirs(export_dir) out_path = os.path.join(export_dir, f"notes_{shortname}-{ts}.md") self.exporter.export_booksnote_to_md(selected_booksnote, selected_booksinfo, out_path) QMessageBox.information(self, "导出成功", f"已导出到:{out_path}") if __name__ == "__main__": app = QApplication(sys.argv) # 设置应用程序名称和组织信息 app.setApplicationName("notesExporter") app.setApplicationDisplayName("notesExporter") app.setOrganizationName("iBook Tools") # 设置应用程序图标 if os.path.exists(config.APP_ICON): app.setWindowIcon(QIcon(config.APP_ICON)) win = IBookExportApp() win.show() sys.exit(app.exec())