From 9d98b8d19ba77047d9c50ee9a6730ce9cef7a494 Mon Sep 17 00:00:00 2001 From: 15000rpm Date: Sun, 7 Sep 2025 23:44:30 +0900 Subject: [PATCH] Update DataClass_Pupil.py, MgrCalibreUI.py, and 2 more files... --- DataClass_Pupil.py | 30 ++++---- MgrCalibreUI.py | 36 +++++++--- MgrPupilColDB.py | 170 ++++++++++++++++++++++++++++++++++++++++++--- main.py | 2 + 4 files changed, 206 insertions(+), 32 deletions(-) diff --git a/DataClass_Pupil.py b/DataClass_Pupil.py index bd5dda1..15fb466 100644 --- a/DataClass_Pupil.py +++ b/DataClass_Pupil.py @@ -16,9 +16,6 @@ JTITLE = "japanese_title" #print_json_tree(data) #print(data['galleryInfo']['tags']) -# pupil : Json -# Caribre : text -# Me : CSV class PupilData: m_data = None @@ -172,19 +169,22 @@ class PupilData: return len(self.m_data[GALINFO]["files"]) # pupil 의 JSON 을 파싱해서 ImageFileList 를 반환한다. - def GetImgFileList(self): - if None == self.m_data: - return None + def GetImgFileList(self) -> list[info.ImageFileInfo]: + listRet = set(info.ImageFileInfo) - listRet = set() - listFiles = self.m_data[GALINFO]["files"] - for item in listFiles: - tempInfo = info.ImageFileInfo(item["name"], - item["height"], - item["width"], - item["hash"], - item["haswebp"]) - listRet.append(tempInfo) + if None != self.m_data: + listFiles = self.m_data[GALINFO]["files"] + for item in listFiles: + tempInfo = info.ImageFileInfo(item["name"], + item["height"], + item["width"], + item["hash"], + item["haswebp"]) + listRet.append(tempInfo) return listRet + + # + def GetText(self) -> str: + return util.PrintJSONTree(self.m_data) diff --git a/MgrCalibreUI.py b/MgrCalibreUI.py index 4a475ac..613393b 100644 --- a/MgrCalibreUI.py +++ b/MgrCalibreUI.py @@ -18,13 +18,13 @@ from PyQt5.QtGui import QResizeEvent, QCloseEvent, QColor class MyApp(QMainWindow): m_DictDuplicate: dict[int, list[str]] = {} - m_ListIncomplMngas: list[str] = [] + m_ListIncompleteMangas: list[str] = [] def __init__(self): super().__init__() + self.initUI() self.loadINI() self.initDB() - self.initUI() # def closeEvent(self, a0: 'QCloseEvent | None'): @@ -65,6 +65,8 @@ class MyApp(QMainWindow): if False == os.path.exists(self.pathDB): os.makedirs(self.pathDB, exist_ok=True) + self.edit_DB.setText(self.pathLastCalibre) + self.fileNamePupilDB = "MyMangaData.db" self.fileNameCallibreDB = "metadata.db" @@ -92,6 +94,7 @@ class MyApp(QMainWindow): settings.setValue(f'folders/{idx}', item.text()) settings.setValue('folders/count', self.listWidget_Folders.count()) + settings.setValue('LastCalibrePath', self.edit_DB.text()) # def initDB(self): @@ -167,7 +170,7 @@ class MyApp(QMainWindow): layout_top = QHBoxLayout() self.edit_DB = QLineEdit(self) self.edit_DB.setReadOnly(True) - self.edit_DB.setText(self.pathLastCalibre) + self.edit_DB.setText("...") btn_DB = QPushButton("...") btn_DB.setFixedWidth(50) btn_DB.clicked.connect(self.on_btnDB_clicked) @@ -282,12 +285,23 @@ class MyApp(QMainWindow): # JSon 데이터의 파일 개수와 실제 다운받은 파일 개수가 다르면 리스트에 저장, 표시한다. if 0 >= nImgFileCnt or 0 >= nImgListLen or nImgFileCnt != nImgListLen: - self.m_ListNotCompleteMngas.append(pathDir) + self.m_ListIncompleteMangas.append(pathDir) self.SrcTableRowBgColor(nRow, Qt.GlobalColor.lightGray) nRow += 1 del data + # + def LoadPupilJson(self, path:str) -> None: + itemPathFull = os.path.join(path, ".metadata") + if False == os.path.exists(itemPathFull): + util.DbgOut(f"JSon File not found: {itemPathFull}", True) + return + + data = pupil.PupilData(itemPathFull) + print(data.GetText()) + + ## metadata.db def LoadCalibreDB(self, path:str ) -> None: pathDB = path @@ -321,7 +335,7 @@ class MyApp(QMainWindow): self.tableWidget_DB.setItem(nRow, 2, itemCover) # format, uncompressed_size, name - tupleData = DB.GetDataByBookID(int(strID)) + tupleData = self.DBCalibre.GetDataByBookID(int(strID)) itemExt = QTableWidgetItem(tupleData[0]) pathArc = os.path.join(path, strBookPath, f"{tupleData[2]}.{tupleData[0]}") if False == os.path.exists(pathArc): @@ -361,7 +375,7 @@ class MyApp(QMainWindow): # 중복 검사을 위한 딕셔너리 초기화 self.m_DictDuplicate.clear() # 다운로드가 완료되지 않은 만화 목록 초기화 - self.m_ListNotCompleteMngas.clear() + self.m_ListIncompleteMangas.clear() # 테이블 위젯 비우기 self.tableWidget_Src.setRowCount(0) @@ -412,7 +426,7 @@ class MyApp(QMainWindow): def on_btn_Emptyfolder_clicked(self): folder_path = QFileDialog.getExistingDirectory(self, '폴더 선택', '') - for pathItem in self.m_ListNotCompleteMngas: + for pathItem in self.m_ListIncompleteMangas: # 유효하지 않은 경로면 건드리지 말자 if False == os.path.exists(pathItem): continue @@ -451,7 +465,13 @@ class MyApp(QMainWindow): # def on_btn_Archive_clicked(self): - pass + itemCount = self.tableWidget_Src.rowCount() + if 0 >= itemCount: + return + + for idx in range(itemCount): + item = self.tableWidget_Src.item(idx, 0) + self.LoadPupilJson(item.text()) # def on_btn_EnterCalibre_clicked(self): diff --git a/MgrPupilColDB.py b/MgrPupilColDB.py index 3786a3b..41f2c9d 100644 --- a/MgrPupilColDB.py +++ b/MgrPupilColDB.py @@ -32,28 +32,180 @@ class MgrPupilColDB(MyDB.MgrSQLiteDB): def GetGroupByID(self, nID: int) -> list[str]: pass - def AddBook(self, strHitomiID: str, strArchiveID: str, strTitle: str, listAuthors: list[str], + # + def GetIDByName(self, strTableName : str, strName: str) -> int: + if True == util.IsEmptyStr(strName) or True == util.IsEmptyStr(strTableName): + return -1 + + strSQL = f"SELECT id FROM \'{strTableName}\' WHERE name = \'{strName}\';" + self.SQLExecute(self.cursor, strSQL, True) + result = self.cursor.fetchone() + + if result is None: + return -1 + + return result[0] + + # + def GetAuthorIDByName(self, strName: str) -> int: + return self.GetIDByName("authors", strName) + + # + def GetGroupIDByName(self, strName: str) -> int: + return self.GetIDByName("groups", strName) + + # + def GetLanguageIDByName(self, strName: str) -> int: + return self.GetIDByName("languages", strName) + + # + def GetTagIDByName(self, strTag: str) -> int: + return self.GetIDByName("tags", strTag) + + # + ["id"] + ["title"] + ["language"] + ["type"] + ["date"] + ["artists"] + ["artist"] + ["groups"] + ["group"] + ["url"] + ["parodys"] + ["parody"] + ["url"] + ["tags"] + ["tag"] + ["url"] + ["female"] + ["male"] + ["related"] + ["languages"] + ["galleryid"] + ["url"] + ["language_localname"] + ["name"] + ["characters"] + ["character"] + ["url"] + ["files"] + def AddBook(self, nHitomiID: int, strArchiveID: str, strTitle: str, listAuthors: list[str], listGroups: list[str], listSeries: list[str], strType: str, strLanguage: str, listTags: list[str], strDescription: str) -> int: pass - def AddAuthor(self, strName: str) -> int: - pass + # 작가 정보 + # Language 는 작가가 작품을 주로 작성하는 언어다. 한국인이라도 일본어로 작품을 내면 일본어로 설정 + def AddAuthor(self, strName: str, strGroup: str, strLanguage: str, strDesc: str) -> int: + if True == util.IsEmptyStr(strName): + return -1 + + # 이미 들어있나? + nAuthorID = self.GetAuthorIDByName(strName) + if nAuthorID > 0: + util.DbgOut(f"이미 존재하는 작가: {strName}", True) + return nAuthorID + + # 그룹이 없으면 추가 + nGroupID = self.GetGroupIDByName(strGroup) + if nGroupID <= 0: + util.DbgOut(f"그룹이 존재하지 않음: {strGroup}", True) + nGroupID = self.AddGroup(strGroup) + # 그룹 추가 확인, 여기서 잘못되면 더 위에서 잘못된 것. + if nGroupID <= 0: + util.DbgOut(f"그룹 추가 실패: {strGroup}", True) + return -1 + + # 언어는 오타가 나거나 모르면 unknown : 0 으로 설정 + nLanguageID = self.GetLanguageIDByName(strLanguage) + if nLanguageID <= 0: + util.DbgOut(f"언어가 존재하지 않음: {strLanguage}", True) + strLanguage = "unknown" + + strTableName = "authors" + try: + strSQL = f"INSERT OR IGNORE INTO \'{strTableName}\' (name, group, language, desc) VALUES (?, ?, ?, ?)" + self.cursor.execute(strSQL, (strName, strGroup, strLanguage, strDesc)) + nID = self.cursor.lastrowid + self.conn.commit() + return nID if nID is not None else -1 + except sqlite3.Error as e: + util.DbgOut(f"SQLite Error occurred: {e}", True) + return -1 + + + def AddTag(self, strTag: str) -> int: + if True == util.IsEmptyStr(strTag): + return -1 + + nTagID = self.GetTagIDByName(strTag) + if nTagID > 0: + util.DbgOut(f"이미 존재하는 태그: {strTag}", True) + return nTagID + + strSep = "" + strValue = "" + if strTag.find(":") >= 0: + strSep = strTag.split(":")[0] + strValue = strTag.split(":")[1] + + return self.AddTagRaw(strTag, strSep, strValue) + + + def AddTagRaw(self, strName: str, strSep: str, strValue: str) -> int: + if True == util.IsEmptyStr(strName): + return -1 + + strTableName = "tags" + try: + strSQL = f"INSERT INTO \'{strTableName}\' (name, sep_title, value) VALUES (?)" + self.cursor.execute(strSQL, (strName, strSep, strValue,)) + nID = self.cursor.lastrowid + self.conn.commit() + return nID if nID is not None else -1 + except sqlite3.Error as e: + util.DbgOut(f"SQLite Error occurred: {e}", True) + return -1 - def AddTag(self, strName: str) -> int: - pass def AddsSeries(self, strName: str) -> int: pass + def AddGroup(self, strName: str) -> int: - pass + if True == util.IsEmptyStr(strName): + return -1 + + strTableName = "groups" + try: + strSQL = f"INSERT INTO \'{strTableName}\' (name) VALUES (?)" + self.cursor.execute(strSQL, (strName,)) + nID = self.cursor.lastrowid + self.conn.commit() + return nID if nID is not None else -1 + except sqlite3.Error as e: + util.DbgOut(f"SQLite Error occurred: {e}", True) + return -1 + def AddArchive(self, strName: str, setArcPath: str) -> int: pass - - def AddFileInfo(self) -> int: - pass + + # ["width"] ["hash"] ["name"] ["height"] ["hasavif"] + # filename, hash, ext, hasavif, width, height + def AddFileInfo(self, strName: str, strHash: str, bHasAvif: bool, nWidth: int, nHeight: int) -> int: + strTableName = "files" + try: + strSQL = f"INSERT INTO \'{strTableName}\' (filename, hash, hasavif, width, height) VALUES (?)" + self.cursor.execute(strSQL, (strName, strHash, bHasAvif, nWidth, nHeight)) + nID = self.cursor.lastrowid + self.conn.commit() + return nID if nID is not None else -1 + except sqlite3.Error as e: + util.DbgOut(f"SQLite Error occurred: {e}", True) + return -1 diff --git a/main.py b/main.py index ab8d492..6e6d270 100644 --- a/main.py +++ b/main.py @@ -22,3 +22,5 @@ if __name__ == '__main__': argv = sys.argv main(argc, argv) + +