From 9008089570640ba133d1ac4061801db11e322a37 Mon Sep 17 00:00:00 2001 From: tonquer Date: Sun, 13 Aug 2023 19:10:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E6=BC=AB=E7=94=BB=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/list/comic_list_widget.py | 17 +++- src/config/config.py | 6 +- src/interface/ui_local.py | 53 +++++++---- src/interface/ui_local_eps.py | 72 +++++++++++++++ src/interface/ui_main.py | 4 + src/interface/ui_main_windows.py | 4 + src/qt_owner.py | 11 ++- src/task/task_local.py | 113 ++++++++++++++++++++++-- src/tools/str.py | 13 +-- src/view/read/read_tool.py | 14 ++- src/view/read/read_view.py | 39 +++++--- src/view/tool/local_read_db.py | 23 ++++- src/view/tool/local_read_eps_view.py | 106 ++++++++++++++++++++++ src/view/tool/local_read_view.py | 57 ++++++++++-- ui/ui_local.ui | 46 ++++++---- ui/ui_local_eps.ui | 74 ++++++++++++++++ ui/ui_main.ui | 55 +++++++----- ui/ui_main_windows.ui | 67 +++++++------- 18 files changed, 643 insertions(+), 131 deletions(-) create mode 100644 src/interface/ui_local_eps.py create mode 100644 src/view/tool/local_read_eps_view.py create mode 100644 ui/ui_local_eps.ui diff --git a/src/component/list/comic_list_widget.py b/src/component/list/comic_list_widget.py index e5e8647..d53fe94 100644 --- a/src/component/list/comic_list_widget.py +++ b/src/component/list/comic_list_widget.py @@ -31,6 +31,7 @@ def __init__(self, parent): self.isDelMenu = False self.isGame = False self.isLocal = False + self.isLocalEps = False self.openMenu = False def SelectMenuBook(self, pos): @@ -86,7 +87,7 @@ def AddBookItemByBook(self, v, isShowHistory=False): categories = ",".join(v.baseInfo.category) self.AddBookItem(_id, title, categories, url) - def AddBookByLocal(self, v, isFirstAdd=False): + def AddBookByLocal(self, v, category=""): from task.task_local import LocalData assert isinstance(v, LocalData) index = self.count() @@ -98,17 +99,23 @@ def AddBookByLocal(self, v, isFirstAdd=False): widget.title = v.title widget.picNum = v.picCnt widget.url = v.file - title += "{}".format("(" + str(v.picCnt) + "P)") + if len(v.eps) > 0: + title += "{}".format("(" + str(len(v.eps)) + "E)") + else: + title += "{}".format("(" + str(v.picCnt) + "P)") if v.lastReadTime: categories = "{} {}".format(ToolUtil.GetUpdateStrByTick(v.lastReadTime), Str.GetStr(Str.Looked)) widget.timeLabel.setText(categories) else: widget.timeLabel.setVisible(False) + widget.starButton.setVisible(False) - # widget.toolButton.setVisible(False) widget.categoryLabel.setVisible(False) - widget.starButton.setVisible(False) + if category: + widget.categoryLabel.setText(category) + widget.categoryLabel.setVisible(True) + widget.nameLable.setText(title) item = QListWidgetItem(self) item.setFlags(item.flags() & ~Qt.ItemIsSelectable) @@ -200,6 +207,8 @@ def SelectItem(self, item): assert isinstance(widget, ComicItemWidget) if self.isGame: QtOwner().OpenGameInfo(widget.id) + elif self.isLocalEps: + QtOwner().OpenLocalEpsBook(widget.id) elif self.isLocal: QtOwner().OpenLocalBook(widget.id) else: diff --git a/src/config/config.py b/src/config/config.py index ed76ae4..0cbf674 100644 --- a/src/config/config.py +++ b/src/config/config.py @@ -42,9 +42,9 @@ UpdateUrl3Api = "https://api.fastgit.xyz/repos/tonquer/JMComic-qt/releases" UpdateUrl3Back = "https://hub.fastgit.xyz/tonquer/JMComic-qt" -UpdateVersion = "v1.1.3" -RealVersion = "v1.1.3" -VersionTime = "2023-7-27" +UpdateVersion = "v1.1.4" +RealVersion = "v1.1.4" +VersionTime = "2023-8-13" Waifu2xVersion = "1.1.6" LoginUserName = "" diff --git a/src/interface/ui_local.py b/src/interface/ui_local.py index c35fe65..23533ab 100644 --- a/src/interface/ui_local.py +++ b/src/interface/ui_local.py @@ -16,8 +16,9 @@ QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) from PySide6.QtWidgets import (QApplication, QComboBox, QFrame, QGridLayout, - QHBoxLayout, QLabel, QListWidgetItem, QPushButton, - QSizePolicy, QSpacerItem, QSpinBox, QWidget) + QHBoxLayout, QLabel, QLineEdit, QListWidgetItem, + QPushButton, QSizePolicy, QSpacerItem, QSpinBox, + QWidget) from component.list.comic_list_widget import ComicListWidget from component.list.tag_list_widget import TagListWidget @@ -29,6 +30,17 @@ def setupUi(self, Local): Local.resize(628, 334) self.gridLayout_2 = QGridLayout(Local) self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout_3 = QGridLayout() + self.gridLayout_3.setObjectName(u"gridLayout_3") + self.bookList = ComicListWidget(Local) + self.bookList.setObjectName(u"bookList") + self.bookList.setStyleSheet(u"") + + self.gridLayout_3.addWidget(self.bookList, 0, 0, 1, 1) + + + self.gridLayout_2.addLayout(self.gridLayout_3, 3, 0, 1, 1) + self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.tagsList = TagListWidget(Local) @@ -43,13 +55,13 @@ def setupUi(self, Local): " border-color:rgb(196, 95, 125);\n" "}\n" "/* \u9f20\u6807\u5728\u6309\u94ae\u4e0a\u65f6\uff0c\u6309\u94ae\u989c\u8272 */\n" -" QListWidget::item:hover\n" +" QListWidget::item:hover \n" "{\n" " background-color:rgb(21, 85, 154);\n" " border-radius: 10px;\n" " color: rgb(0, 0, 0);\n" "}\n" -" QListWidget::item:selected\n" +" QListWidget::item:selected \n" "{\n" " background-color:rgb(21, 85, 154);\n" " border-radius: 10px;\n" @@ -67,18 +79,7 @@ def setupUi(self, Local): self.horizontalLayout_2.addWidget(self.toolButton, 0, Qt.AlignRight) - self.gridLayout_2.addLayout(self.horizontalLayout_2, 0, 0, 1, 1) - - self.gridLayout_3 = QGridLayout() - self.gridLayout_3.setObjectName(u"gridLayout_3") - self.bookList = ComicListWidget(Local) - self.bookList.setObjectName(u"bookList") - self.bookList.setStyleSheet(u"") - - self.gridLayout_3.addWidget(self.bookList, 0, 0, 1, 1) - - - self.gridLayout_2.addLayout(self.gridLayout_3, 2, 0, 1, 1) + self.gridLayout_2.addLayout(self.horizontalLayout_2, 1, 0, 1, 1) self.gridLayout_4 = QGridLayout() self.gridLayout_4.setObjectName(u"gridLayout_4") @@ -168,7 +169,24 @@ def setupUi(self, Local): self.gridLayout_4.addLayout(self.horizontalLayout, 0, 0, 1, 1) - self.gridLayout_2.addLayout(self.gridLayout_4, 3, 0, 1, 1) + self.gridLayout_2.addLayout(self.gridLayout_4, 4, 0, 1, 1) + + self.widget = QWidget(Local) + self.widget.setObjectName(u"widget") + self.horizontalLayout_3 = QHBoxLayout(self.widget) + self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") + self.label = QLabel(self.widget) + self.label.setObjectName(u"label") + + self.horizontalLayout_3.addWidget(self.label) + + self.lineEdit = QLineEdit(self.widget) + self.lineEdit.setObjectName(u"lineEdit") + + self.horizontalLayout_3.addWidget(self.lineEdit) + + + self.gridLayout_2.addWidget(self.widget, 0, 0, 1, 1) self.retranslateUi(Local) @@ -194,5 +212,6 @@ def retranslateUi(self, Local): #if QT_CONFIG(shortcut) self.jumpButton.setShortcut(QCoreApplication.translate("Local", u"Return", None)) #endif // QT_CONFIG(shortcut) + self.label.setText(QCoreApplication.translate("Local", u"\u641c\u7d22\uff1a", None)) # retranslateUi diff --git a/src/interface/ui_local_eps.py b/src/interface/ui_local_eps.py new file mode 100644 index 0000000..48356ab --- /dev/null +++ b/src/interface/ui_local_eps.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'ui_local_eps.ui' +## +## Created by: Qt User Interface Compiler version 6.2.4 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QGridLayout, QHBoxLayout, QLabel, + QListWidgetItem, QRadioButton, QSizePolicy, QSpacerItem, + QWidget) + +from component.list.comic_list_widget import ComicListWidget + +class Ui_LocalEps(object): + def setupUi(self, LocalEps): + if not LocalEps.objectName(): + LocalEps.setObjectName(u"LocalEps") + LocalEps.resize(646, 391) + self.gridLayout_2 = QGridLayout(LocalEps) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout_3 = QGridLayout() + self.gridLayout_3.setObjectName(u"gridLayout_3") + self.bookList = ComicListWidget(LocalEps) + self.bookList.setObjectName(u"bookList") + self.bookList.setStyleSheet(u"") + + self.gridLayout_3.addWidget(self.bookList, 0, 0, 1, 1) + + + self.gridLayout_2.addLayout(self.gridLayout_3, 4, 0, 1, 1) + + self.name = QLabel(LocalEps) + self.name.setObjectName(u"name") + + self.gridLayout_2.addWidget(self.name, 0, 0, 1, 1) + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.showWaifu2x = QRadioButton(LocalEps) + self.showWaifu2x.setObjectName(u"showWaifu2x") + + self.horizontalLayout.addWidget(self.showWaifu2x) + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout.addItem(self.horizontalSpacer) + + + self.gridLayout_2.addLayout(self.horizontalLayout, 2, 0, 1, 1) + + + self.retranslateUi(LocalEps) + + QMetaObject.connectSlotsByName(LocalEps) + # setupUi + + def retranslateUi(self, LocalEps): + LocalEps.setWindowTitle(QCoreApplication.translate("LocalEps", u"\u672c\u5730\u6f2b\u753b\u7ae0\u8282", None)) + self.name.setText("") + self.showWaifu2x.setText(QCoreApplication.translate("LocalEps", u"\u53ea\u663e\u793aWaifu2x", None)) + # retranslateUi + diff --git a/src/interface/ui_main.py b/src/interface/ui_main.py index 40cc8e0..e7bdada 100644 --- a/src/interface/ui_main.py +++ b/src/interface/ui_main.py @@ -37,6 +37,7 @@ from view.read.read_view import ReadView from view.search.search_view import SearchView from view.setting.setting_view import SettingView +from view.tool.local_read_eps_view import LocalReadEpsView from view.tool.local_read_view import LocalReadView from view.tool.waifu2x_tool_view import Waifu2xToolView from view.user.favorite_view import FavoriteView @@ -96,6 +97,9 @@ def setupUi(self, Main): self.indexView = IndexView() self.indexView.setObjectName(u"indexView") self.subStackWidget.addWidget(self.indexView) + self.localReadEpsView = LocalReadEpsView() + self.localReadEpsView.setObjectName(u"localReadEpsView") + self.subStackWidget.addWidget(self.localReadEpsView) self.localReadView = LocalReadView() self.localReadView.setObjectName(u"localReadView") self.subStackWidget.addWidget(self.localReadView) diff --git a/src/interface/ui_main_windows.py b/src/interface/ui_main_windows.py index 2ce219f..ea6f81d 100644 --- a/src/interface/ui_main_windows.py +++ b/src/interface/ui_main_windows.py @@ -38,6 +38,7 @@ from view.read.read_view import ReadView from view.search.search_view import SearchView from view.setting.setting_view import SettingView +from view.tool.local_read_eps_view import LocalReadEpsView from view.tool.local_read_view import LocalReadView from view.tool.waifu2x_tool_view import Waifu2xToolView from view.user.favorite_view import FavoriteView @@ -103,6 +104,9 @@ def setupUi(self, MainWindows): self.indexView = IndexView() self.indexView.setObjectName(u"indexView") self.subStackWidget.addWidget(self.indexView) + self.localReadEpsView = LocalReadEpsView() + self.localReadEpsView.setObjectName(u"localReadEpsView") + self.subStackWidget.addWidget(self.localReadEpsView) self.localFavoriteView = LocalFavoriteView() self.localFavoriteView.setObjectName(u"localFavoriteView") self.subStackWidget.addWidget(self.localFavoriteView) diff --git a/src/qt_owner.py b/src/qt_owner.py index b102077..1125451 100644 --- a/src/qt_owner.py +++ b/src/qt_owner.py @@ -174,6 +174,10 @@ def OpenSubComment(self, commentId, widget, commentList): self.owner.subCommentView.SetWidget(widget) self.owner.SwitchWidget(self.owner.subCommentView, **arg) + def OpenLocalEpsView(self, bookId): + arg = {"bookId": bookId} + self.owner.SwitchWidget(self.owner.localReadEpsView, **arg) + def OpenSearch(self, text): arg = {"text": text} if text.isdigit() and len(text) == 6: @@ -206,9 +210,9 @@ def OpenReadView(self, bookId, index, pageIndex, isOffline=False): self.owner.totalStackWidget.setCurrentIndex(1) self.owner.readView.OpenPage(bookId, index, pageIndex=pageIndex, isOffline=isOffline) - def OpenLocalReadView(self, v): + def OpenLocalReadView(self, v, epsId=0): self.owner.totalStackWidget.setCurrentIndex(1) - self.owner.readView.OpenLocalPage(v) + self.owner.readView.OpenLocalPage(v, epsId) def CloseReadView(self): self.owner.totalStackWidget.setCurrentIndex(0) @@ -226,6 +230,9 @@ def OpenBookInfo(self, bookId, bookName=""): def OpenLocalBook(self, bookId): self.owner.localReadView.OpenLocalBook(bookId) + def OpenLocalEpsBook(self, bookId): + self.owner.localReadEpsView.OpenLocalBook(bookId) + def OpenEpsInfo(self, bookId): # self.owner.subCommentView.SetOpenEvent(commentId, widget) arg = {"bookId": bookId} diff --git a/src/task/task_local.py b/src/task/task_local.py index 402374b..d5a199e 100644 --- a/src/task/task_local.py +++ b/src/task/task_local.py @@ -36,7 +36,7 @@ def __init__(self, taskId=0): class LocalData(object): Type1 = 1 # 加载目录 Type2 = 2 # 加载文件 - Type3 = 3 # + Type3 = 3 # 加载目录所有 Type4 = 4 # Type5 = 5 # 批量加载 @@ -61,6 +61,10 @@ def __init__(self) -> None: self.pic = [] # 图片数 self.eps = [] # 多章节 + @property + def isWaifu2x(self): + return "waifu2x" in self.file or "waifu2x" in self.path + def CopyData(self, o): assert isinstance(o, LocalData) self.cover = o.cover @@ -68,6 +72,20 @@ def CopyData(self, o): self.pic = [] self.pic.extend(o.pic) + oldDict = {} + + for v in self.eps: + oldDict[v.id] = v + + self.eps.clear() + for v in o.eps: + if v.id in oldDict: + newV = oldDict[v.id] + newV.CopyData(v) + self.eps.append(newV) + else: + self.eps.append(v) + @property def sumPicCnt(self): a = 0 @@ -82,6 +100,15 @@ def SortFilePic(self): self.cover = self.pic[0] return + def SortEps(self): + self.eps = natsorted(self.eps, key=lambda a:a.title) + if self.eps: + first = self.eps[0] + path = first.file.replace(self.file, "").strip("\\").strip("/") + self.cover = os.path.join(path, os.path.join(first.path, first.cover)) + for v in self.eps: + v.main_id = self.id + return class TaskLocal(TaskBase, QtTaskBase): def __init__(self) -> None: @@ -191,7 +218,8 @@ def _LoadRead(self, taskId): st, data = self.ParseBookInfoByFile(dir) datas = [data] elif type == LocalData.Type3: - st, datas = self.ParseBookInfoByFile(dir) + st, data = self.ParseBookInfoByDirRecursion(dir) + datas = [data] elif type == LocalData.Type4: st, datas = self.ParseBookInfoByFile(dir) elif type == LocalData.Type5: @@ -222,9 +250,13 @@ def AddLoadRead(self, type, path, backParam, callBack, cleanFlag): self._inQueue.put(self.taskId) return self.taskId - def AddLoadReadPicture(self, v, index, backParam, callBack, cleanFlag): + def AddLoadReadPicture(self, v2, index, backParam, callBack, cleanFlag): self.taskId += 1 - assert isinstance(v, LocalData) + assert isinstance(v2, LocalData) + if index == -1 and v2.eps: + v = v2.eps[0] + else: + v = v2 info = QLocalTask(self.taskId) info.callBack = callBack @@ -306,6 +338,77 @@ def ParseBookInfoByDir(self, dirName): return Str.ErrorPath, "" return Status.Ok, l + def ParseBookInfoByDirRecursion(self, dirName): + # 解析递归目录 + + # 获取目录名称 + path = dirName + + try: + if not os.path.isdir(dirName): + return Str.ErrorPath, "" + nextPath = "" + allData = self.ParseBookInfoByDirRecursion2(dirName) + if not allData: + return Str.ErrorPath, "" + if len(allData) <= 1 : + return self.ParseBookInfoByDir(dirName) + l = LocalData() + l.eps = allData + l.title = os.path.basename(dirName) + l.file = dirName + l.id = hashlib.md5(l.file.encode("utf-8")).hexdigest() + l.SortEps() + l.path = "" + + l.main_id = l.id + l.isZipFile = False + l.addTime = int(time.time()) + + except Exception as es: + Log.Error(es) + return Str.ErrorPath, "" + return Status.Ok, l + + def ParseBookInfoByDirRecursion2(self, dirName): + allData = [] + try: + if not os.path.isdir(dirName): + return [] + allDir = [] + zipFile = [] + picNum = 0 + for v in os.scandir(dirName): + isinstance(v, os.DirEntry) + + if v.is_dir(): + allDir.append(v.name) + elif v.is_file(): + data = v.name.split(".") + if len(data) < 2: + continue + mat = data[-1] + if mat == "zip": + zipFile.append(v.name) + if mat in LocalData.AllPictureFormat: + picNum += 1 + for zipName in zipFile: + st, l = self.ParseBookInfoByFile(os.path.join(dirName, zipName)) + if st == Status.Ok: + allData.append(l) + if picNum > 1: + st, l = self.ParseBookInfoByDir(dirName) + if st == Status.Ok: + allData.append(l) + else: + for file in allDir: + newAllData = self.ParseBookInfoByDirRecursion2(os.path.join(dirName, file)) + allData.extend(newAllData) + except Exception as es: + Log.Error(es) + return allData + + def ParseBookInfoByFile(self, fileName): # 解析 # 判断ZIP是否存在 @@ -376,7 +479,7 @@ def ParseBookInfoByFileAll(self, fileNames): if os.path.isfile(url): st, v = self.ParseBookInfoByFile(url) elif os.path.isdir(url): - st, v = self.ParseBookInfoByDir(url) + st, v = self.ParseBookInfoByDirRecursion(url) else: st = Status.Error if st == Status.Ok: diff --git a/src/tools/str.py b/src/tools/str.py index 79308de..d3a0a41 100644 --- a/src/tools/str.py +++ b/src/tools/str.py @@ -45,7 +45,6 @@ class Str: AccountAlready = 1029 # "账号已被注册" NotAdult = 1030 # "未成年禁止注册" SpaceEps = 1031 # "空白章节" - SpacePic = 1032 # "空白图片" Success = 2001 # "下载完成" Reading = 2002 # "获取信息" @@ -229,7 +228,9 @@ class Str: AlreadyHave = 149 # 已存在 SameWight = 150 # 等宽模式 CopyFileLast = 151 # 保存上次路径 - + ImportDouble = 152 # 导入多章节目录 + + @classmethod def Reload(cls): cls.obj = QtStrObj() @@ -265,7 +266,6 @@ def Reload(cls): cls.strDict[cls.AccountAlready] = QCoreApplication.translate("cls.obj", "账号已被注册", None) cls.strDict[cls.NotAdult] = QCoreApplication.translate("cls.obj", "未成年禁止注册", None) cls.strDict[cls.SpaceEps] = QCoreApplication.translate("cls.obj", "空白章节", None) - cls.strDict[cls.SpacePic] = QCoreApplication.translate("cls.obj", "空白图片", None) cls.strDict[cls.LoadingPicture] = QCoreApplication.translate("cls.obj", "图片加载中...", None) cls.strDict[cls.LoadingFail] = QCoreApplication.translate("cls.obj", "图片加载失败", None) @@ -435,7 +435,6 @@ def Reload(cls): cls.strDict[cls.Copy] = QCoreApplication.translate("cls.obj", "复制", None) cls.strDict[cls.CopyPicture] = QCoreApplication.translate("cls.obj", "复制图片到剪贴板", None) cls.strDict[cls.CopyFile] = QCoreApplication.translate("cls.obj", "保存文件", None) - cls.strDict[cls.CopyFileLast] = QCoreApplication.translate("cls.obj", "保存上次路径", None) cls.strDict[cls.MainUi] = QCoreApplication.translate("cls.obj", "主界面", None) cls.strDict[cls.ShowMin] = QCoreApplication.translate("cls.obj", "最小化", None) cls.strDict[cls.DownloadAll] = QCoreApplication.translate("cls.obj", "批量下载", None) @@ -446,10 +445,12 @@ def Reload(cls): cls.strDict[cls.SupportDrop] = QCoreApplication.translate("cls.obj", "支持拖拽文件导入", None) cls.strDict[cls.AlreadyHave] = QCoreApplication.translate("cls.obj", "已存在", None) cls.strDict[cls.SameWight] = QCoreApplication.translate("cls.obj", "等宽模式", None) + cls.strDict[cls.CopyFileLast] = QCoreApplication.translate("cls.obj", "保存上次路径", None) + cls.strDict[cls.ImportDouble] = QCoreApplication.translate("cls.obj", "导入多章节目录", None) @classmethod - def GetStr(cls, enumType): - return cls.strDict.get(enumType, "") + def GetStr(cls, enumType, defualt=""): + return cls.strDict.get(enumType, defualt) @classmethod def CheckStr(cls): diff --git a/src/view/read/read_tool.py b/src/view/read/read_tool.py index ceb8267..bfceae4 100644 --- a/src/view/read/read_tool.py +++ b/src/view/read/read_tool.py @@ -178,7 +178,7 @@ def _NextPage(self): if self.curIndex >= self.maxPic - 1: if self.readImg.isLocal: - QtOwner().ShowMsg(Str.GetStr(Str.AlreadyNextPage)) + self.OpenNextEps() return elif self.readImg.isOffline: if not QtOwner().downloadView.IsDownloadEpsId(self.readImg.bookId, self.readImg.epsId + 1): @@ -226,7 +226,7 @@ def _LastPage(self): if self.curIndex <= 0: if self.readImg.isLocal: - QtOwner().ShowMsg(Str.GetStr(Str.AlreadyLastPage)) + self.OpenLastEps() return elif self.readImg.isOffline: if not QtOwner().downloadView.IsDownloadEpsId(self.readImg.bookId, self.readImg.epsId - 1): @@ -349,7 +349,10 @@ def OpenLastEps(self): epsId -= 1 if self.readImg.isLocal: - QtOwner().ShowMsg(Str.GetStr(Str.AlreadyLastChapter)) + if epsId < 0: + QtOwner().ShowMsg(Str.GetStr(Str.AlreadyLastChapter)) + return + self.readImg.OpenLocalPage(self.readImg._cacheBook, epsId, 9999) return elif self.readImg.isOffline: if not QtOwner().downloadView.IsDownloadEpsId(self.readImg.bookId, self.readImg.epsId - 1): @@ -374,7 +377,10 @@ def OpenNextEps(self): bookInfo = BookMgr().books.get(bookId) epsId += 1 if self.readImg.isLocal: - QtOwner().ShowMsg(Str.GetStr(Str.AlreadyNextChapter)) + if epsId >= len(self.readImg._cacheBook.eps): + QtOwner().ShowMsg(Str.GetStr(Str.AlreadyNextChapter)) + return + self.readImg.OpenLocalPage(self.readImg._cacheBook, epsId, 0) return elif self.readImg.isOffline: if not QtOwner().downloadView.IsDownloadEpsId(self.readImg.bookId, self.readImg.epsId + 1): diff --git a/src/view/read/read_view.py b/src/view/read/read_view.py index be07d74..5efbb22 100644 --- a/src/view/read/read_view.py +++ b/src/view/read/read_view.py @@ -63,10 +63,18 @@ def __init__(self): self.pageIndex = -1 self.isOffline = False self.isLocal = False - self.cacheBook = None + self._cacheBook = None self.lastPath = "" # QtOwner().owner.WindowsSizeChange.connect(self.qtTool.ClearQImage) + @property + def cacheBook(self): + if self._cacheBook: + if self._cacheBook.eps: + if self.epsId >= 0 and self.epsId < len(self._cacheBook.eps): + return self._cacheBook.eps[self.epsId] + return self._cacheBook + @property def scrollArea(self): return self.frame.scrollArea @@ -201,7 +209,7 @@ def OpenPage(self, bookId, epsId, pageIndex=-1, isOffline=False): return self.isOffline = isOffline self.isLocal = False - self.cacheBook = None + self._cacheBook = None self.Clear() info = BookMgr().books.get(bookId) if info: @@ -232,14 +240,19 @@ def OpenPage(self, bookId, epsId, pageIndex=-1, isOffline=False): config.IsTips = 0 self.frame.InitHelp() - def OpenLocalPage(self, v): + def OpenLocalPage(self, v, epsId=0, pageIndex=-1): if not v: return + self.Clear() assert isinstance(v, LocalData) - self.cacheBook = v + self.epsId = epsId + self._cacheBook = v + self.pageIndex = self.cacheBook.lastIndex + if pageIndex >= 0: + self.pageIndex = pageIndex + self.isOffline = False self.isLocal = True - self.Clear() self.qtTool.checkBox.setChecked(Setting.IsOpenWaifu.value) self.qtTool.preDownWaifu2x.setChecked(Setting.PreDownWaifu2x.value) @@ -248,10 +261,7 @@ def OpenLocalPage(self, v): self.qtTool.SetData() # self.qtTool.show() - self.bookId = v.id - self.epsId = 0 - - self.pageIndex = v.lastIndex + self.bookId = self.cacheBook.id self.qtTool.isMaxFull = self.window().isMaximized() if Setting.LookReadFull.value: @@ -436,8 +446,6 @@ def CompleteDownloadPic(self, data, st, index): self.pictureData[index] = p if st == Status.FileError: QtOwner().ShowError(Str.GetStr(st)) - # elif st == Str.SpacePic: - # QtOwner().ShowError(Str.GetStr(st)+"{}".format(index+1)) elif st != Status.Ok: p.state = p.DownloadReset if QtOwner().owner.totalStackWidget.currentIndex == 0: @@ -734,7 +742,12 @@ def AddHistory(self): assert isinstance(self.cacheBook, LocalData) self.cacheBook.lastIndex = self.curIndex self.cacheBook.lastReadTime = int(time.time()) - QtOwner().localReadView.AddDataToDB(self.cacheBook.id) + if self._cacheBook.eps: + self._cacheBook.lastReadTime = int(time.time()) + QtOwner().localReadView.UpdateLastTick(self._cacheBook.id) + QtOwner().localReadView.AddEpsDataToDB(self._cacheBook.id, self.cacheBook.id) + else: + QtOwner().localReadView.AddDataToDB(self.cacheBook.id) else: bookName = QtOwner().bookInfoView.bookName url = QtOwner().bookInfoView.url @@ -801,7 +814,7 @@ def AddCovertData(self, i): else: filePath = "" if self.isLocal: - info.waifu2xTaskId = self.AddConvertTask(path, info.data, info.model, self.Waifu2xBack, i, noSaveCache=True, preDownPath=filePath) + info.waifu2xTaskId = self.AddConvertTask(path, info.data, info.model, self.Waifu2xBack, i, noSaveCache=True) else: info.waifu2xTaskId = self.AddConvertTask(path, info.data, info.model, self.Waifu2xBack, i, saveParams=info.saveParams, preDownPath=filePath) diff --git a/src/view/tool/local_read_db.py b/src/view/tool/local_read_db.py index dfac03d..d15bf4e 100644 --- a/src/view/tool/local_read_db.py +++ b/src/view/tool/local_read_db.py @@ -93,21 +93,38 @@ def LoadCategory(self): def GetSaveStr(self, name): return name.replace("'", "''") - def AddLoadLocalBook(self, info): + def AddLoadLocalBook(self, info2): + info = info2 + assert isinstance(info, LocalData) + self.AddLoadLocalBook2(info) + for info in info2.eps: + self.AddLoadLocalBook2(info) + self.cur.execute("COMMIT") + return + + def AddLoadLocalEpsBook(self, info2): + info = info2 + assert isinstance(info, LocalData) + self.AddLoadLocalBook2(info) + self.cur.execute("COMMIT") + return + + def AddLoadLocalBook2(self, info2): + info = info2 assert isinstance(info, LocalData) sql = "INSERT INTO local_book(id, title, file, path, cover, epsId, isZipFile, lastIndex, lastEpsId, addTime, lastReadTime, picCnt, main_id) " \ "VALUES ('{0}', '{1}', '{2}', '{3}', '{4}', {5}, {6}, {7}, {8}, {9}, {10}, {11}, '{12}') " \ "ON CONFLICT(id) DO UPDATE SET lastIndex='{7}', file='{2}', path='{3}', lastEpsId={8}, addTime={9}, lastReadTime={10}, picCnt={11}, cover='{4}' ".\ format(info.id, self.GetSaveStr(info.title), self.GetSaveStr(info.file), self.GetSaveStr(info.path), self.GetSaveStr(info.cover), info.epsId, int(info.isZipFile), info.lastIndex , info.lastEpsId, info.addTime, info.lastReadTime, info.picCnt, info.main_id) - suc = self.cur.execute(sql) - self.cur.execute("COMMIT") return def DelDownloadDB(self, bookId): sql = "delete from local_book where id='{}'".format(bookId) suc = self.cur.execute(sql) + sql = "delete from local_book where main_id='{}'".format(bookId) + suc = self.cur.execute(sql) sql = "delete from local_category where book_id='{}'".format(bookId) suc = self.cur.execute(sql) self.cur.execute("COMMIT") diff --git a/src/view/tool/local_read_eps_view.py b/src/view/tool/local_read_eps_view.py new file mode 100644 index 0000000..a54eb2f --- /dev/null +++ b/src/view/tool/local_read_eps_view.py @@ -0,0 +1,106 @@ +import json +import os +from this import d + +from PySide6.QtCore import Signal, QUrl +from PySide6.QtGui import QAction, Qt, QDesktopServices +from PySide6.QtWidgets import QWidget, QMenu, QFileDialog +from natsort import natsorted + +from interface.ui_index import Ui_Index +from interface.ui_local import Ui_Local +from interface.ui_local_eps import Ui_LocalEps +from qt_owner import QtOwner +from task.qt_task import QtTaskBase +from task.task_local import LocalData +from tools.str import Str +from view.tool.local_read_db import LocalReadDb + + +class LocalReadEpsView(QWidget, Ui_LocalEps, QtTaskBase): + ReloadHistory = Signal(int) + + def __init__(self, parent=None): + QWidget.__init__(self, parent) + Ui_Index.__init__(self) + QtTaskBase.__init__(self) + self.setupUi(self) + self.isInit = False + self.bookId = "" + self.cacheBook = None + self.bookIdToIndex = {} + self.bookList.isLocal = True + self.bookList.isLocalEps = True + self.bookList.LoadingPicture = self.LoadingPicture + self.bookList.ReDownloadPicture = self.LoadingPicture + self.showWaifu2x.clicked.connect(self.Init) + + @property + def localReadView(self): + return QtOwner().localReadView + + def Init(self): + book = self.localReadView.allBookInfos.get(self.bookId) + if not book: + return + self.name.setText(book.title) + self.bookIdToIndex.clear() + self.cacheBook = book + assert isinstance(book, LocalData) + self.bookList.clear() + for i, v in enumerate(book.eps): + assert isinstance(v, LocalData) + self.bookIdToIndex[v.id] = i + categroup = [] + if v.isWaifu2x: + categroup.append("waifu2x") + else: + if self.showWaifu2x.isChecked(): + continue + + if v.isZipFile: + categroup.append("zip") + self.bookList.AddBookByLocal(v, "".join(categroup)) + pass + + def SwitchCurrent(self, **kwargs): + bookId = kwargs.get("bookId") + if bookId == self.bookId: + return + self.bookId = bookId + self.Init() + return + + def LoadingPicture(self, index): + if isinstance(index, int): + item = self.bookList.item(index) + widget = self.bookList.itemWidget(item) + else: + widget = self.bookList.indexWidget(index) + + bookId = widget.id + if bookId not in self.bookIdToIndex: + return + i = self.bookIdToIndex.get(bookId) + v = self.cacheBook.eps[i] + self.AddLocalTaskLoadPicture(v, -1, index, self.bookList.LoadingPictureComplete) + + def OpenLocalBook(self, bookId): + if bookId not in self.bookIdToIndex: + return + newV = LocalData() + newV.id = self.cacheBook.id + newV.CopyData(self.cacheBook) + newV.eps = [] + eps = 0 + i = 0 + for v in self.cacheBook.eps: + assert isinstance(v, LocalData) + if v.id == bookId: + eps = i + if not v.isWaifu2x: + if self.showWaifu2x.isChecked(): + continue + i += 1 + newV.eps.append(v) + QtOwner().OpenLocalReadView(newV, eps) diff --git a/src/view/tool/local_read_view.py b/src/view/tool/local_read_view.py index 8c47313..3025c54 100644 --- a/src/view/tool/local_read_view.py +++ b/src/view/tool/local_read_view.py @@ -10,7 +10,7 @@ from interface.ui_index import Ui_Index from interface.ui_local import Ui_Local from qt_owner import QtOwner -from server import req, Log, Status +from server import Status, time from task.qt_task import QtTaskBase from task.task_local import LocalData from tools.str import Str @@ -32,6 +32,7 @@ def __init__(self, parent=None): self.action1 = QAction(Str.GetStr(Str.ImportSimple), self.toolMenu, triggered=self.CheckAction1) self.action2 = QAction(Str.GetStr(Str.ImportSimpleZip), self.toolMenu, triggered=self.CheckAction2) + self.action4 = QAction(Str.GetStr(Str.ImportDouble), self.toolMenu, triggered=self.CheckAction3) self.action3 = QAction(Str.GetStr(Str.SupportDrop), self.toolMenu) self.action3.setEnabled(False) # self.action3 = QAction(Str.GetStr(Str.ImportSimpleDir), self.toolMenu, triggered=self.CheckAction3) @@ -39,6 +40,7 @@ def __init__(self, parent=None): self.toolMenu.addAction(self.action1) self.toolMenu.addAction(self.action2) + self.toolMenu.addAction(self.action4) self.toolMenu.addAction(self.action3) # self.toolMenu.addAction(self.action3) # self.toolMenu.addAction(self.action4) @@ -71,6 +73,12 @@ def __init__(self, parent=None): self.bookList.MoveHandler = self.MoveCallBack self.bookList.openMenu = True self.bookList.OpenDirHandler = self.OpenDirCallBack + self.lineEdit.textChanged.connect(self.SearchTextChange) + self.searchText = "" + + def SearchTextChange(self, text): + self.searchText = text + self.InitBook() def Init(self): self.categoryBook, self.bookCategory = self.db.LoadCategory() @@ -105,7 +113,8 @@ def InitBook(self): if v.id in allBookId: categoryList = self.bookCategory.get(v.id, []) categoryStr = ",".join(categoryList) - self.bookList.AddBookByLocal(v, categoryStr) + if not self.searchText or self.searchText in v.title: + self.bookList.AddBookByLocal(v, categoryStr) return def ClickTagsItem(self, modelIndex): @@ -129,7 +138,7 @@ def ToSortData(self, value): datas = list(value) sortId = self.sortIdCombox.currentIndex() sortKeyID = self.sortKeyCombox.currentIndex() - isRevert = (sortId != 0) + isRevert = (sortId == 0) if sortKeyID == 0: datas.sort(key=lambda a: a.lastReadTime, reverse=isRevert) elif sortKeyID == 2: @@ -184,11 +193,19 @@ def OpenLocalBook(self, bookId): return v = self.allBookInfos[bookId] assert isinstance(v, LocalData) - type = LocalData.Type1 if not v.isZipFile else LocalData.Type2 + if v.eps != []: + type = LocalData.Type3 + elif v.isZipFile: + type = LocalData.Type2 + else: + type = LocalData.Type1 + + QtOwner().ShowLoading() self.AddLocalTaskLoad(type, v.file, bookId, callBack=self.OpenLocalBookBack) return def OpenLocalBookBack(self, st, books, bookId): + QtOwner().CloseLoading() if st != Status.Ok: QtOwner().ShowError(Str.GetStr(st)) return @@ -201,6 +218,10 @@ def OpenLocalBookBack(self, st, books, bookId): assert isinstance(v, LocalData) newV = books[0] v.CopyData(newV) + if v.eps != []: + QtOwner().OpenLocalEpsView(v.id) + return + if v.picCnt <= 0: QtOwner().ShowError(Str.GetStr(Str.NotPictureFile)) return @@ -215,6 +236,22 @@ def AddDataToDB(self, taskId): self.db.AddLoadLocalBook(v) return + def UpdateLastTick(self, taskId): + if taskId not in self.allBookInfos: + return + v = self.allBookInfos[taskId] + v.lastReadTime = int(time.time()) + self.db.AddLoadLocalBook(v) + return + + def AddEpsDataToDB(self, taskId, subId): + if taskId not in self.allBookInfos: + return + for v in self.allBookInfos[taskId].eps: + if v.id == subId: + self.db.AddLoadLocalEpsBook(v) + return + def AddBookByDir(self): return @@ -252,6 +289,9 @@ def CheckAction1LoadBack(self, st, books, url): self.bookList.AddBookByLocal(v, category) self.AddDataToDB(v.id) QtOwner().ShowMsg("已添加{}本到书架, {}本存在已忽略".format(addNum, alreadyNum)) + self.lineEdit.setText("") + self.sortIdCombox.setCurrentIndex(0) + self.sortKeyCombox.setCurrentIndex(1) return # 导入单本Zip @@ -268,8 +308,15 @@ def CheckAction2(self): self.AddLocalTaskLoad(LocalData.Type2, name, path, self.CheckAction1LoadBack) return - # 批量导入目录 + # 导入单本目录 def CheckAction3(self): + if self.lastPath: + url = QFileDialog.getExistingDirectory(self, Str.GetStr(Str.SelectFold), dir=self.lastPath) + else: + url = QFileDialog.getExistingDirectory(self, Str.GetStr(Str.SelectFold)) + if url: + QtOwner().ShowLoading() + self.AddLocalTaskLoad(LocalData.Type3, url, os.path.dirname(url), self.CheckAction1LoadBack) return # 批量导入带章节的目录 diff --git a/ui/ui_local.ui b/ui/ui_local.ui index bd45158..017d5be 100644 --- a/ui/ui_local.ui +++ b/ui/ui_local.ui @@ -14,7 +14,18 @@ 本地漫画 - + + + + + + + + + + + + @@ -34,13 +45,13 @@ QListWidget::item { border-color:rgb(196, 95, 125); } /* 鼠标在按钮上时,按钮颜色 */ - QListWidget::item:hover + QListWidget::item:hover { background-color:rgb(21, 85, 154); border-radius: 10px; color: rgb(0, 0, 0); } - QListWidget::item:selected + QListWidget::item:selected { background-color:rgb(21, 85, 154); border-radius: 10px; @@ -70,18 +81,7 @@ QListWidget::item { - - - - - - - - - - - - + @@ -234,6 +234,22 @@ QListWidget::item { + + + + + + + 搜索: + + + + + + + + + diff --git a/ui/ui_local_eps.ui b/ui/ui_local_eps.ui new file mode 100644 index 0000000..9bf3818 --- /dev/null +++ b/ui/ui_local_eps.ui @@ -0,0 +1,74 @@ + + + LocalEps + + + + 0 + 0 + 646 + 391 + + + + 本地漫画章节 + + + + + + + + + + + + + + + + + + + + + + + + + + 只显示Waifu2x + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + ComicListWidget + QListWidget +
component.list.comic_list_widget.h
+
+
+ + + + JumpPage() + RefreshDataFocus() + +
diff --git a/ui/ui_main.ui b/ui/ui_main.ui index b16ba78..9a8c19f 100644 --- a/ui/ui_main.ui +++ b/ui/ui_main.ui @@ -87,6 +87,7 @@ + @@ -126,15 +127,15 @@ 1 - IndexView + SettingView QWidget -
view.index.index_view.h
+
view.setting.setting_view.h
1
- SettingView + DownloadView QWidget -
view.setting.setting_view.h
+
view.download.download_view.h
1
@@ -161,6 +162,12 @@
view.user.favorite_view.h
1
+ + HistoryView + QWidget +
view.history.history_view.h
+ 1 +
BookInfoView QWidget @@ -174,15 +181,15 @@ 1 - BookEpsView + HelpView QWidget -
view.info.book_eps_view.h
+
view.help.help_view.h
1
- HelpView + LocalReadView QWidget -
view.help.help_view.h
+
view.tool.local_read_view.h
1
@@ -192,51 +199,51 @@ 1 - SubCommentView + LocalReadEpsView QWidget -
view.comment.sub_comment_view.h
+
view.tool.local_read_eps_view.h
1
- DownloadView + IndexView QWidget -
view.download.download_view.h
+
view.index.index_view.h
1
- AllCommentView + BookEpsView QWidget -
view.comment.all_comment_view.h
+
view.info.book_eps_view.h
1
- CategoryView + SubCommentView QWidget -
view.category.category_view.h
+
view.comment.sub_comment_view.h
1
- HistoryView + AllCommentView QWidget -
view.history.history_view.h
+
view.comment.all_comment_view.h
1
- MyCommentView + CategoryView QWidget -
view.comment.my_comment_view.h
+
view.category.category_view.h
1
- RemoteHistoryView + MyCommentView QWidget -
view.history.remote_history_view.h
+
view.comment.my_comment_view.h
1
- LocalReadView + RemoteHistoryView QWidget -
view.tool.local_read_view.h
+
view.history.remote_history_view.h
1
diff --git a/ui/ui_main_windows.ui b/ui/ui_main_windows.ui index a8267a0..9e1a1b2 100644 --- a/ui/ui_main_windows.ui +++ b/ui/ui_main_windows.ui @@ -105,6 +105,7 @@ + @@ -143,15 +144,15 @@ 1 - IndexView + SettingView QWidget -
view.index.index_view.h
+
view.setting.setting_view.h
1
- SettingView + DownloadView QWidget -
view.setting.setting_view.h
+
view.download.download_view.h
1
@@ -178,6 +179,12 @@
view.user.favorite_view.h
1
+ + HistoryView + QWidget +
view.history.history_view.h
+ 1 +
BookInfoView QWidget @@ -191,15 +198,15 @@ 1 - BookEpsView + HelpView QWidget -
view.info.book_eps_view.h
+
view.help.help_view.h
1
- HelpView + LocalReadView QWidget -
view.help.help_view.h
+
view.tool.local_read_view.h
1
@@ -209,69 +216,69 @@ 1 - SubCommentView + LocalReadEpsView QWidget -
view.comment.sub_comment_view.h
+
view.tool.local_read_eps_view.h
1
- DownloadView + TitleBarWidget QWidget -
view.download.download_view.h
+
component.widget.title_bar_widget.h
1
- AllCommentView + IndexView QWidget -
view.comment.all_comment_view.h
+
view.index.index_view.h
1
- CategoryView + BookEpsView QWidget -
view.category.category_view.h
+
view.info.book_eps_view.h
1
- HistoryView + SubCommentView QWidget -
view.history.history_view.h
+
view.comment.sub_comment_view.h
1
- MyCommentView + AllCommentView QWidget -
view.comment.my_comment_view.h
+
view.comment.all_comment_view.h
1
- RemoteHistoryView + CategoryView QWidget -
view.history.remote_history_view.h
+
view.category.category_view.h
1
- LocalReadView + MyCommentView QWidget -
view.tool.local_read_view.h
+
view.comment.my_comment_view.h
1
- DownloadAllView + RemoteHistoryView QWidget -
view.download.download_all_view.h
+
view.history.remote_history_view.h
1
- LocalFavoriteView + DownloadAllView QWidget -
view.user.local_favorite_view.h
+
view.download.download_all_view.h
1
- TitleBarWidget + LocalFavoriteView QWidget -
component.widget.title_bar_widget.h
+
view.user.local_favorite_view.h
1