diff --git a/.DS_Store b/.DS_Store index 247f9c5..6795c1f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.exclude b/.exclude new file mode 100644 index 0000000..d0f8fee --- /dev/null +++ b/.exclude @@ -0,0 +1,4 @@ +backup +mobiparse +.git +My Clippings.txt.bk diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..4444b22 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/cui.win.bat b/cui.win.bat index a681294..1ae2708 100755 --- a/cui.win.bat +++ b/cui.win.bat @@ -1,4 +1,4 @@ -pyside2-uic mainwindow.ui -o mainwindow.py -pyside2-rcc kmanapp.qrc -o kmanapp_rc.py +pyside6-uic mainwindow.ui -o mainwindow.py +pyside6-rcc kmanapp.qrc -o kmanapp_rc.py cp -fr icons *py *md *ico *qrc *ui ~/penv/kman/ diff --git a/kmanapp.py b/kmanapp.py index 5ce3d3e..2501831 100644 --- a/kmanapp.py +++ b/kmanapp.py @@ -18,10 +18,10 @@ import threading if hasattr(sys, 'frozen'): os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH'] -from PySide2.QtWidgets import (QMainWindow, QApplication, QMessageBox, +from PySide6.QtWidgets import (QMainWindow, QApplication, QMessageBox, QFileDialog, QLabel, QAbstractItemView, QHeaderView, QMenu) -from PySide2.QtCore import (QAbstractTableModel, Signal, QSize, QTimer, Qt) -from PySide2.QtGui import (QPalette, QStandardItemModel, QStandardItem, QIcon) +from PySide6.QtCore import (QAbstractTableModel, Signal, QSize, QTimer, Qt) +from PySide6.QtGui import (QPalette, QStandardItemModel, QStandardItem, QIcon) from mainwindow import Ui_MainWindow from kman import * diff --git a/kmanapp.spec b/kmanapp.spec index de922d4..0c935ca 100644 --- a/kmanapp.spec +++ b/kmanapp.spec @@ -1,37 +1,52 @@ # -*- mode: python ; coding: utf-8 -*- -block_cipher = None +a = Analysis( + ['kmanapp.py'], + pathex=[], + binaries=[], + datas=[ + ('icons/Cbb20.png', 'icons'), + ('icons/*.png', 'icons'), + ('kmanapp.qrc', '.'), + ('kmanapp_rc.py', '.'), + ('vocab.db', '.'), + # 如有其他资源请补充 + ], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) -a = Analysis(['kmanapp.spec\r'], - pathex=['/Users/mark/kman'], - binaries=[], - datas=[], - hiddenimports=[], - hookspath=[], - runtime_hooks=[], - excludes=[], - win_no_prefer_redirects=False, - win_private_assemblies=False, - cipher=block_cipher, - noarchive=False) -pyz = PYZ(a.pure, a.zipped_data, - cipher=block_cipher) -exe = EXE(pyz, - a.scripts, - [], - exclude_binaries=True, - name='kmanapp', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - console=True ) -coll = COLLECT(exe, - a.binaries, - a.zipfiles, - a.datas, - strip=False, - upx=True, - upx_exclude=[], - name='kmanapp') +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='kmanapp', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon=['icons/Cbb20.png'], +) +app = BUNDLE( + exe, + name='kmanapp.app', + icon='icons/Cbb20.png', + bundle_identifier=None, +) diff --git a/kmanapp_rc.py b/kmanapp_rc.py index fe96fec..35c60cd 100644 --- a/kmanapp_rc.py +++ b/kmanapp_rc.py @@ -3,7 +3,7 @@ # Created by: The Resource Compiler for Qt version 5.15.0 # WARNING! All changes made in this file will be lost! -from PySide2 import QtCore +from PySide6 import QtCore qt_resource_data = b"\ \x00\x00\x05\x8e\ diff --git a/mainwindow.py b/mainwindow.py index 9885276..1d56c8c 100644 --- a/mainwindow.py +++ b/mainwindow.py @@ -3,80 +3,115 @@ ################################################################################ ## Form generated from reading UI file 'mainwindow.ui' ## -## Created by: Qt User Interface Compiler version 5.15.0 +## Created by: Qt User Interface Compiler version 6.9.1 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ -from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject, - QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) -from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, - QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter, - QPixmap, QRadialGradient) -from PySide2.QtWidgets import * - +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, + QCursor, QFont, QFontDatabase, QGradient, + QIcon, QImage, QKeySequence, QLinearGradient, + QPainter, QPalette, QPixmap, QRadialGradient, + QTransform) +from PySide6.QtWidgets import (QApplication, QComboBox, QGridLayout, QHBoxLayout, + QHeaderView, QLabel, QLineEdit, QMainWindow, + QMenuBar, QSizePolicy, QSplitter, QStatusBar, + QTableView, QTextBrowser, QToolBar, QToolButton, + QTreeView, QWidget) import kmanapp_rc class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") - MainWindow.resize(774, 410) + MainWindow.resize(837, 622) + icon = QIcon() + icon.addFile(u":/icons/Cbb20.png", QSize(), QIcon.Mode.Normal, QIcon.State.On) + MainWindow.setWindowIcon(icon) MainWindow.setIconSize(QSize(40, 40)) self.actionimportlocal = QAction(MainWindow) self.actionimportlocal.setObjectName(u"actionimportlocal") - icon = QIcon() - icon.addFile(u":/icons/downr.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionimportlocal.setIcon(icon) + icon1 = QIcon() + icon1.addFile(u":/icons/downr.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionimportlocal.setIcon(icon1) self.actionimportkindle = QAction(MainWindow) self.actionimportkindle.setObjectName(u"actionimportkindle") - icon1 = QIcon() - icon1.addFile(u":/icons/kindle.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionimportkindle.setIcon(icon1) + icon2 = QIcon() + icon2.addFile(u":/icons/kindle.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionimportkindle.setIcon(icon2) self.actionconfig = QAction(MainWindow) self.actionconfig.setObjectName(u"actionconfig") - icon2 = QIcon() - icon2.addFile(u":/icons/config.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionconfig.setIcon(icon2) + icon3 = QIcon() + icon3.addFile(u":/icons/config.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionconfig.setIcon(icon3) self.actionflush = QAction(MainWindow) self.actionflush.setObjectName(u"actionflush") - icon3 = QIcon() - icon3.addFile(u":/icons/refresh.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionflush.setIcon(icon3) + icon4 = QIcon() + icon4.addFile(u":/icons/refresh.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionflush.setIcon(icon4) self.actionwords = QAction(MainWindow) self.actionwords.setObjectName(u"actionwords") - icon4 = QIcon() - icon4.addFile(u":/icons/books.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionwords.setIcon(icon4) + icon5 = QIcon() + icon5.addFile(u":/icons/books.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionwords.setIcon(icon5) self.actionstatistic = QAction(MainWindow) self.actionstatistic.setObjectName(u"actionstatistic") - icon5 = QIcon() - icon5.addFile(u":/icons/statistics.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionstatistic.setIcon(icon5) + icon6 = QIcon() + icon6.addFile(u":/icons/statistics.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionstatistic.setIcon(icon6) self.actionhomepage = QAction(MainWindow) self.actionhomepage.setObjectName(u"actionhomepage") - icon6 = QIcon() - icon6.addFile(u":/icons/web.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionhomepage.setIcon(icon6) + icon7 = QIcon() + icon7.addFile(u":/icons/web.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionhomepage.setIcon(icon7) self.actionabout = QAction(MainWindow) self.actionabout.setObjectName(u"actionabout") - icon7 = QIcon() - icon7.addFile(u":/icons/question.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionabout.setIcon(icon7) + icon8 = QIcon() + icon8.addFile(u":/icons/question.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionabout.setIcon(icon8) self.actionsearch = QAction(MainWindow) self.actionsearch.setObjectName(u"actionsearch") - icon8 = QIcon() - icon8.addFile(u":/icons/Pixadex.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionsearch.setIcon(icon8) + icon9 = QIcon() + icon9.addFile(u":/icons/Pixadex.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionsearch.setIcon(icon9) self.actionexport = QAction(MainWindow) self.actionexport.setObjectName(u"actionexport") - icon9 = QIcon() - icon9.addFile(u":/icons/md2.png", QSize(), QIcon.Normal, QIcon.Off) - self.actionexport.setIcon(icon9) + icon10 = QIcon() + icon10.addFile(u":/icons/md2.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.actionexport.setIcon(icon10) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout.setObjectName(u"gridLayout") + self.splitter_2 = QSplitter(self.centralwidget) + self.splitter_2.setObjectName(u"splitter_2") + self.splitter_2.setOrientation(Qt.Orientation.Horizontal) + self.treeView = QTreeView(self.splitter_2) + self.treeView.setObjectName(u"treeView") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.treeView.sizePolicy().hasHeightForWidth()) + self.treeView.setSizePolicy(sizePolicy) + self.treeView.setMaximumSize(QSize(401, 16777215)) + self.splitter_2.addWidget(self.treeView) + self.treeView.header().setVisible(False) + self.splitter = QSplitter(self.splitter_2) + self.splitter.setObjectName(u"splitter") + self.splitter.setOrientation(Qt.Orientation.Vertical) + self.tableView = QTableView(self.splitter) + self.tableView.setObjectName(u"tableView") + self.splitter.addWidget(self.tableView) + self.textEdit = QTextBrowser(self.splitter) + self.textEdit.setObjectName(u"textEdit") + self.splitter.addWidget(self.textEdit) + self.splitter_2.addWidget(self.splitter) + + self.gridLayout.addWidget(self.splitter_2, 1, 0, 1, 1) + self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName(u"horizontalLayout") self.searchLabel = QLabel(self.centralwidget) @@ -96,57 +131,26 @@ class Ui_MainWindow(object): self.searchToolButton = QToolButton(self.centralwidget) self.searchToolButton.setObjectName(u"searchToolButton") - icon10 = QIcon() - icon10.addFile(u":/icons/search.jpeg", QSize(), QIcon.Normal, QIcon.Off) - self.searchToolButton.setIcon(icon10) + icon11 = QIcon() + icon11.addFile(u":/icons/search.jpeg", QSize(), QIcon.Mode.Normal, QIcon.State.Off) + self.searchToolButton.setIcon(icon11) self.horizontalLayout.addWidget(self.searchToolButton) self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) - self.splitter_2 = QSplitter(self.centralwidget) - self.splitter_2.setObjectName(u"splitter_2") - self.splitter_2.setOrientation(Qt.Horizontal) - self.treeView = QTreeView(self.splitter_2) - self.treeView.setObjectName(u"treeView") - sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.treeView.sizePolicy().hasHeightForWidth()) - self.treeView.setSizePolicy(sizePolicy) - self.treeView.setMaximumSize(QSize(401, 16777215)) - self.splitter_2.addWidget(self.treeView) - self.treeView.header().setVisible(False) - self.splitter = QSplitter(self.splitter_2) - self.splitter.setObjectName(u"splitter") - self.splitter.setOrientation(Qt.Vertical) - self.tableView = QTableView(self.splitter) - self.tableView.setObjectName(u"tableView") - sizePolicy1 = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) - sizePolicy1.setHorizontalStretch(0) - sizePolicy1.setVerticalStretch(0) - sizePolicy1.setHeightForWidth(self.tableView.sizePolicy().hasHeightForWidth()) - self.tableView.setSizePolicy(sizePolicy1) - self.splitter.addWidget(self.tableView) - self.textEdit = QTextBrowser(self.splitter) - self.textEdit.setObjectName(u"textEdit") - self.splitter.addWidget(self.textEdit) - self.splitter_2.addWidget(self.splitter) - - self.gridLayout.addWidget(self.splitter_2, 1, 0, 1, 1) - MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(u"statusbar") MainWindow.setStatusBar(self.statusbar) self.menuBar = QMenuBar(MainWindow) self.menuBar.setObjectName(u"menuBar") - self.menuBar.setGeometry(QRect(0, 0, 774, 22)) + self.menuBar.setGeometry(QRect(0, 0, 837, 32)) MainWindow.setMenuBar(self.menuBar) self.toolBar = QToolBar(MainWindow) self.toolBar.setObjectName(u"toolBar") - MainWindow.addToolBar(Qt.TopToolBarArea, self.toolBar) + MainWindow.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.toolBar) self.toolBar.addAction(self.actionimportkindle) self.toolBar.addAction(self.actionimportlocal) diff --git a/mainwindow.ui b/mainwindow.ui index 57aae4d..7fd0cfa 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,13 +6,17 @@ 0 0 - 774 - 410 + 837 + 622 Kindle Management + + + :/icons/Cbb20.png:/icons/Cbb20.png + 40 @@ -21,6 +25,37 @@ + + + + Qt::Orientation::Horizontal + + + + + 0 + 0 + + + + + 401 + 16777215 + + + + false + + + + + Qt::Orientation::Vertical + + + + + + @@ -57,44 +92,6 @@ - - - - Qt::Horizontal - - - - - 0 - 0 - - - - - 401 - 16777215 - - - - false - - - - - Qt::Vertical - - - - - 0 - 0 - - - - - - - @@ -103,8 +100,8 @@ 0 0 - 774 - 22 + 837 + 32 diff --git a/rungit.bat b/rungit.bat index f006901..3126f1d 100755 --- a/rungit.bat +++ b/rungit.bat @@ -1,3 +1,3 @@ git add . git commit -m "kindle manager" -git push origin master +git push origin main diff --git a/setup.py b/setup.py index 0a2d3c6..9defe95 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ from setuptools import setup APP = ['kmanapp.py'] DATA_FILES = ['kman.py', 'kmanapp.py', 'kmanapp_rc.py', 'mainwindow.py', 'parseweb.py', 'unitest.kman.py'] -OPTIONS = {'includes':['PySide2', 'pandas', 'requests',], +OPTIONS = {'includes':['PySide6', 'pandas', 'requests',], 'iconfile':'/Users/mark/kman/kmanapp.ico'} setup( diff --git a/打包MacBook指南.md b/打包MacBook指南.md new file mode 100644 index 0000000..7ef368d --- /dev/null +++ b/打包MacBook指南.md @@ -0,0 +1,43 @@ +# MacBook 打包 PySide6 应用指南 + +## 1. 安装 PyInstaller + +```zsh +pip install pyinstaller +``` + +## 2. 打包命令(推荐单文件) + +```zsh +pyinstaller --noconfirm --windowed --onefile --icon=icons/Cbb20.png kmanapp.py +``` + +- `--windowed`:无控制台窗口(GUI应用必选) +- `--onefile`:生成单一可执行文件 +- `--icon=...`:指定应用图标 + +## 3. 资源文件处理 +如有图片、qrc、数据库等资源,需在 `kmanapp.spec` 的 `datas` 字段添加: + +```python +# 在 .spec 文件的 a = Analysis(...) 里 datas= 加入: +('icons/Cbb20.png', 'icons'), +('kmanapp.qrc', '.'), +('kmanapp_rc.py', '.'), +('vocab.db', '.'), +# 其他资源... +``` + +## 4. 重新打包 + +```zsh +pyinstaller kmanapp.spec +``` + +## 5. 运行 + +打包后在 `dist/` 目录下生成可执行文件,双击即可运行。 + +--- + +如需自动化脚本或遇到打包报错,请告知具体需求。