pyPDFeditor-GUI 2.2.7__tar.gz → 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/PKG-INFO +10 -5
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/README.md +7 -2
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pyPDFeditor_GUI.egg-info/PKG-INFO +10 -5
- pypdfeditor_gui-3.0.0/pyPDFeditor_GUI.egg-info/requires.txt +2 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/__init__.py +6 -12
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/__main__.py +3 -3
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/application.py +29 -33
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/functions.py +46 -76
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/language.py +48 -6
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/style_sheets.py +9 -9
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/window_effect.py +6 -3
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/windows.py +253 -166
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/setup.py +1 -1
- pyPDFeditor-GUI-2.2.7/pyPDFeditor_GUI.egg-info/requires.txt +0 -2
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/LICENSE +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pyPDFeditor_GUI.egg-info/SOURCES.txt +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pyPDFeditor_GUI.egg-info/dependency_links.txt +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pyPDFeditor_GUI.egg-info/entry_points.txt +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pyPDFeditor_GUI.egg-info/top_level.txt +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/Add.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/Add_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/Add_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/Photo.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/__init__.py +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/arrow_move.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/book2.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/chevron_down.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/color.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/color_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/color_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/delete.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/delete_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/delete_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/dismiss.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/dismiss_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/down.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/down_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/down_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/edit.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/folder.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/folder_d.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/folder_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/folder_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/font.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/font_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/font_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/home.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/lock.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/maximize.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/merge.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/metadata.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/minimize.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/more.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/more_d.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/more_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/more_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/move_page.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/pdf icon.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/rotate_anticlockwise.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/rotate_clockwise.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/settings.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/settings_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/settings_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/square_multiple.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/sync.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/sync_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/sync_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/view.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/view_h.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/pypdfeditor_core/icons/view_p.svg +0 -0
- {pyPDFeditor-GUI-2.2.7 → pypdfeditor_gui-3.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyPDFeditor-GUI
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: A desktop application to edit PDF files.
|
|
5
5
|
Home-page: https://github.com/Augus1999/pyPDFeditor-GUI/
|
|
6
6
|
Author: Nianze A. TAO
|
|
@@ -25,8 +25,8 @@ Classifier: Topic :: Office/Business
|
|
|
25
25
|
Requires-Python: >=3.7
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
|
-
Requires-Dist: PyMuPDF>=1.
|
|
29
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: PyMuPDF>=1.24.3
|
|
29
|
+
Requires-Dist: PyQt6>=6.7.0
|
|
30
30
|
|
|
31
31
|
# pyPDFeditor-GUI
|
|
32
32
|
|
|
@@ -49,6 +49,11 @@ and [PyMuPDF](https://github.com/pymupdf/PyMuPDF), designed to work on simple PD
|
|
|
49
49
|
|
|
50
50
|
I tried my best to make it close to Fluent UI. Icons used can be found [🔗here](https://fluenticons.co/).
|
|
51
51
|
|
|
52
|
+
From version 3.0.0, we have moved the GUI library to PyQt6. If you upgraded from a previous version, you can consider removing PyQt5:
|
|
53
|
+
```bash
|
|
54
|
+
$ pip uninstall PyQt5 PyQt5-Qt5 PyQt5-sip
|
|
55
|
+
```
|
|
56
|
+
|
|
52
57
|
## Features
|
|
53
58
|
|
|
54
59
|
* Support 3 languages: English, 日本語 (Japanese), and 中文 (Traditional Chinese)
|
|
@@ -81,8 +86,8 @@ Python>=3.7
|
|
|
81
86
|
```
|
|
82
87
|
|
|
83
88
|
```text
|
|
84
|
-
|
|
85
|
-
PyMuPDF>=1.
|
|
89
|
+
PyQt6>=6.7.0
|
|
90
|
+
PyMuPDF>=1.24.0
|
|
86
91
|
```
|
|
87
92
|
|
|
88
93
|
## Install & Run
|
|
@@ -19,6 +19,11 @@ and [PyMuPDF](https://github.com/pymupdf/PyMuPDF), designed to work on simple PD
|
|
|
19
19
|
|
|
20
20
|
I tried my best to make it close to Fluent UI. Icons used can be found [🔗here](https://fluenticons.co/).
|
|
21
21
|
|
|
22
|
+
From version 3.0.0, we have moved the GUI library to PyQt6. If you upgraded from a previous version, you can consider removing PyQt5:
|
|
23
|
+
```bash
|
|
24
|
+
$ pip uninstall PyQt5 PyQt5-Qt5 PyQt5-sip
|
|
25
|
+
```
|
|
26
|
+
|
|
22
27
|
## Features
|
|
23
28
|
|
|
24
29
|
* Support 3 languages: English, 日本語 (Japanese), and 中文 (Traditional Chinese)
|
|
@@ -51,8 +56,8 @@ Python>=3.7
|
|
|
51
56
|
```
|
|
52
57
|
|
|
53
58
|
```text
|
|
54
|
-
|
|
55
|
-
PyMuPDF>=1.
|
|
59
|
+
PyQt6>=6.7.0
|
|
60
|
+
PyMuPDF>=1.24.0
|
|
56
61
|
```
|
|
57
62
|
|
|
58
63
|
## Install & Run
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyPDFeditor-GUI
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: A desktop application to edit PDF files.
|
|
5
5
|
Home-page: https://github.com/Augus1999/pyPDFeditor-GUI/
|
|
6
6
|
Author: Nianze A. TAO
|
|
@@ -25,8 +25,8 @@ Classifier: Topic :: Office/Business
|
|
|
25
25
|
Requires-Python: >=3.7
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
|
-
Requires-Dist: PyMuPDF>=1.
|
|
29
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: PyMuPDF>=1.24.3
|
|
29
|
+
Requires-Dist: PyQt6>=6.7.0
|
|
30
30
|
|
|
31
31
|
# pyPDFeditor-GUI
|
|
32
32
|
|
|
@@ -49,6 +49,11 @@ and [PyMuPDF](https://github.com/pymupdf/PyMuPDF), designed to work on simple PD
|
|
|
49
49
|
|
|
50
50
|
I tried my best to make it close to Fluent UI. Icons used can be found [🔗here](https://fluenticons.co/).
|
|
51
51
|
|
|
52
|
+
From version 3.0.0, we have moved the GUI library to PyQt6. If you upgraded from a previous version, you can consider removing PyQt5:
|
|
53
|
+
```bash
|
|
54
|
+
$ pip uninstall PyQt5 PyQt5-Qt5 PyQt5-sip
|
|
55
|
+
```
|
|
56
|
+
|
|
52
57
|
## Features
|
|
53
58
|
|
|
54
59
|
* Support 3 languages: English, 日本語 (Japanese), and 中文 (Traditional Chinese)
|
|
@@ -81,8 +86,8 @@ Python>=3.7
|
|
|
81
86
|
```
|
|
82
87
|
|
|
83
88
|
```text
|
|
84
|
-
|
|
85
|
-
PyMuPDF>=1.
|
|
89
|
+
PyQt6>=6.7.0
|
|
90
|
+
PyMuPDF>=1.24.0
|
|
86
91
|
```
|
|
87
92
|
|
|
88
93
|
## Install & Run
|
|
@@ -6,9 +6,8 @@ core of pyPDFeditor-GUI
|
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
8
|
import platform
|
|
9
|
-
import
|
|
10
|
-
from
|
|
11
|
-
from PyQt5.QtWidgets import QApplication
|
|
9
|
+
import pymupdf
|
|
10
|
+
from PyQt6.QtWidgets import QApplication
|
|
12
11
|
from .application import reset, remove, Main, app_home
|
|
13
12
|
|
|
14
13
|
if not os.path.exists(app_home):
|
|
@@ -16,7 +15,7 @@ if not os.path.exists(app_home):
|
|
|
16
15
|
|
|
17
16
|
__system__ = platform.system()
|
|
18
17
|
__author__ = "Nianze A. TAO (Omozawa SUENO)"
|
|
19
|
-
__version__ = "
|
|
18
|
+
__version__ = "3.0.0"
|
|
20
19
|
__all__ = ["main", "reset", "remove"]
|
|
21
20
|
|
|
22
21
|
|
|
@@ -31,14 +30,9 @@ def main(
|
|
|
31
30
|
:param debug: whether display mupdf errors or not
|
|
32
31
|
:return: None
|
|
33
32
|
"""
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
del s, a # delete QApplication object so that it won't affect the following codes
|
|
38
|
-
if screen_w > 1920 and screen_h > 1080:
|
|
39
|
-
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
|
|
40
|
-
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
|
|
41
|
-
fitz.TOOLS.mupdf_display_errors(debug)
|
|
33
|
+
if system == "Windows":
|
|
34
|
+
os.environ["QT_FONT_DPI"] = "96"
|
|
35
|
+
pymupdf.TOOLS.mupdf_display_errors(debug)
|
|
42
36
|
app = QApplication(sys.argv)
|
|
43
37
|
main_app = Main(system, version)
|
|
44
38
|
main_app.show()
|
|
@@ -9,7 +9,7 @@ from pypdfeditor_core import main, reset, remove
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
if __name__ == "__main__":
|
|
12
|
-
|
|
12
|
+
DEBUG= False
|
|
13
13
|
parser = ArgumentParser(description="pyPDFeditor-GUI")
|
|
14
14
|
parser.add_argument(
|
|
15
15
|
"--reset",
|
|
@@ -32,5 +32,5 @@ if __name__ == "__main__":
|
|
|
32
32
|
remove()
|
|
33
33
|
sys.exit(0)
|
|
34
34
|
if args.debug:
|
|
35
|
-
|
|
36
|
-
main(debug=
|
|
35
|
+
DEBUG = True
|
|
36
|
+
main(debug=DEBUG)
|
|
@@ -10,10 +10,10 @@ import getpass
|
|
|
10
10
|
import subprocess as sp
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from typing import Dict
|
|
13
|
-
import fitz
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
13
|
+
import pymupdf as fitz
|
|
14
|
+
from PyQt6 import QtCore
|
|
15
|
+
from PyQt6.QtGui import QColor, QPixmap, QCloseEvent
|
|
16
|
+
from PyQt6.QtWidgets import QColorDialog
|
|
17
17
|
from .language import set_language, lag_s, lag_p
|
|
18
18
|
from .windows import (
|
|
19
19
|
MainR,
|
|
@@ -120,13 +120,15 @@ class Main(MainR):
|
|
|
120
120
|
)
|
|
121
121
|
)
|
|
122
122
|
self.tab3.button9.clicked.connect(
|
|
123
|
-
lambda:
|
|
124
|
-
os.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
os.path.
|
|
123
|
+
lambda: (
|
|
124
|
+
os.remove(
|
|
125
|
+
os.path.join(app_home, "font_dir_cache.json"),
|
|
126
|
+
)
|
|
127
|
+
if os.path.exists(
|
|
128
|
+
os.path.join(app_home, "font_dir_cache.json"),
|
|
129
|
+
)
|
|
130
|
+
else None
|
|
128
131
|
)
|
|
129
|
-
else None
|
|
130
132
|
) # delete font dir cache
|
|
131
133
|
self.tab3.line3.returnPressed.connect(self.preview)
|
|
132
134
|
self.tab3.line4.returnPressed.connect(self.preview)
|
|
@@ -149,11 +151,18 @@ class Main(MainR):
|
|
|
149
151
|
)
|
|
150
152
|
self.tab4.table.Index.connect(lambda par: self.show_index(par, self.tab4))
|
|
151
153
|
set_language(self)
|
|
154
|
+
self.settings = QtCore.QSettings("QtProject", "pyPDFEditor-GUI")
|
|
155
|
+
if not self.settings.value("geometry") == None:
|
|
156
|
+
self.restoreGeometry(self.settings.value("geometry"))
|
|
157
|
+
if not self.settings.value("windowState") == None:
|
|
158
|
+
self.restoreState(self.settings.value("windowState"))
|
|
152
159
|
|
|
153
|
-
def closeEvent(self, event) -> None:
|
|
160
|
+
def closeEvent(self, event: QCloseEvent) -> None:
|
|
154
161
|
"""
|
|
155
162
|
write settings to settings.json
|
|
156
163
|
"""
|
|
164
|
+
self.settings.setValue("geometry", self.saveGeometry())
|
|
165
|
+
self.settings.setValue("windowState", self.saveState())
|
|
157
166
|
_settings = {
|
|
158
167
|
"start dir": self.s_dir,
|
|
159
168
|
"save dir": self.o_dir,
|
|
@@ -165,9 +174,7 @@ class Main(MainR):
|
|
|
165
174
|
os.makedirs(app_home)
|
|
166
175
|
if os.path.exists(os.path.join(app_home, "settings.json")):
|
|
167
176
|
with open(
|
|
168
|
-
os.path.join(app_home, "settings.json"),
|
|
169
|
-
mode="r",
|
|
170
|
-
encoding="utf-8",
|
|
177
|
+
os.path.join(app_home, "settings.json"), mode="r", encoding="utf-8"
|
|
171
178
|
) as c:
|
|
172
179
|
states = json.load(c)
|
|
173
180
|
if states == _settings:
|
|
@@ -175,13 +182,7 @@ class Main(MainR):
|
|
|
175
182
|
with open(
|
|
176
183
|
os.path.join(app_home, "settings.json"), mode="w", encoding="utf-8"
|
|
177
184
|
) as f: # write new settings
|
|
178
|
-
json.dump(
|
|
179
|
-
_settings,
|
|
180
|
-
f,
|
|
181
|
-
sort_keys=True,
|
|
182
|
-
indent=4,
|
|
183
|
-
separators=(",", ": "),
|
|
184
|
-
)
|
|
185
|
+
json.dump(_settings, f, sort_keys=True, indent=4, separators=(",", ": "))
|
|
185
186
|
|
|
186
187
|
def enable_preview(self) -> None:
|
|
187
188
|
"""
|
|
@@ -366,7 +367,7 @@ class Main(MainR):
|
|
|
366
367
|
self.SettingCD.show()
|
|
367
368
|
self.SettingCD.signal.connect(self.get_data)
|
|
368
369
|
|
|
369
|
-
def get_perm_para(self, par) -> None:
|
|
370
|
+
def get_perm_para(self, par: int) -> None:
|
|
370
371
|
"""
|
|
371
372
|
obtain permission code
|
|
372
373
|
"""
|
|
@@ -490,7 +491,7 @@ class Main(MainR):
|
|
|
490
491
|
int(255 * float(self.tab3.line4.text()) / 100),
|
|
491
492
|
),
|
|
492
493
|
options=QColorDialog.ColorDialogOption(
|
|
493
|
-
QColorDialog.ShowAlphaChannel,
|
|
494
|
+
QColorDialog.ColorDialogOption.ShowAlphaChannel,
|
|
494
495
|
),
|
|
495
496
|
parent=self,
|
|
496
497
|
title="Select Colour",
|
|
@@ -514,7 +515,7 @@ class Main(MainR):
|
|
|
514
515
|
)
|
|
515
516
|
else:
|
|
516
517
|
font_paths = QtCore.QStandardPaths.standardLocations(
|
|
517
|
-
QtCore.QStandardPaths.FontsLocation,
|
|
518
|
+
QtCore.QStandardPaths.StandardLocation.FontsLocation,
|
|
518
519
|
)
|
|
519
520
|
name_dict, file_dict = find_font(font_paths)
|
|
520
521
|
store_font_path(name_dict, os.path.join(app_home, "font_dir_cache.json"))
|
|
@@ -572,12 +573,7 @@ class Setting(SettingR):
|
|
|
572
573
|
setting window
|
|
573
574
|
"""
|
|
574
575
|
|
|
575
|
-
signal = QtCore.pyqtSignal(
|
|
576
|
-
str,
|
|
577
|
-
str,
|
|
578
|
-
bool,
|
|
579
|
-
str,
|
|
580
|
-
)
|
|
576
|
+
signal = QtCore.pyqtSignal(str, str, bool, str)
|
|
581
577
|
|
|
582
578
|
def __init__(self, set_dict: dict):
|
|
583
579
|
super().__init__()
|
|
@@ -623,7 +619,7 @@ class Setting(SettingR):
|
|
|
623
619
|
self.line1.setReadOnly(False)
|
|
624
620
|
self.line2.setReadOnly(False)
|
|
625
621
|
|
|
626
|
-
def closeEvent(self, event) -> None:
|
|
622
|
+
def closeEvent(self, event: QCloseEvent) -> None:
|
|
627
623
|
"""
|
|
628
624
|
re-write closeEvent
|
|
629
625
|
"""
|
|
@@ -650,7 +646,7 @@ class PermMenu(PermMenuR):
|
|
|
650
646
|
"""
|
|
651
647
|
lag_p(self, language)
|
|
652
648
|
|
|
653
|
-
def closeEvent(self, event) -> None:
|
|
649
|
+
def closeEvent(self, event: QCloseEvent) -> None:
|
|
654
650
|
"""
|
|
655
651
|
close event
|
|
656
652
|
"""
|
|
@@ -725,7 +721,7 @@ class FontDialog(FontDialogR):
|
|
|
725
721
|
fitz.TOOLS.store_shrink(100) # delete MuPDF cache
|
|
726
722
|
del cover, shape, page, r1, doc
|
|
727
723
|
|
|
728
|
-
def closeEvent(self, event) -> None:
|
|
724
|
+
def closeEvent(self, event: QCloseEvent) -> None:
|
|
729
725
|
"""
|
|
730
726
|
close event
|
|
731
727
|
"""
|
|
@@ -10,11 +10,11 @@ import json
|
|
|
10
10
|
import time
|
|
11
11
|
from typing import Union, Optional, Tuple, List
|
|
12
12
|
from pathlib import Path
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
13
|
+
from pymupdf import Document, Page, Pixmap, Rect, Point, Font
|
|
14
|
+
from pymupdf.utils import get_pixmap, set_metadata, Shape
|
|
15
|
+
from pymupdf import TOOLS, Matrix, Identity
|
|
16
|
+
from PyQt6 import QtGui, QtCore, QtWidgets
|
|
17
|
+
from PyQt6.QtWidgets import (
|
|
18
18
|
QInputDialog,
|
|
19
19
|
QHBoxLayout,
|
|
20
20
|
QWidget,
|
|
@@ -25,14 +25,8 @@ from PyQt5.QtWidgets import (
|
|
|
25
25
|
from .icons import icon_path
|
|
26
26
|
from .language import MENU_L, MESSAGE
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
".jpg",
|
|
31
|
-
".jpeg",
|
|
32
|
-
".bmp",
|
|
33
|
-
".tiff",
|
|
34
|
-
".svg",
|
|
35
|
-
) # list .svg at the end!
|
|
28
|
+
# list .svg at the end!
|
|
29
|
+
SUPPORT_IMG_FORMAT = (".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".svg")
|
|
36
30
|
SUPPORT_FORMAT = (".pdf", ".epub", ".xps", ".fb2", ".cbz") + SUPPORT_IMG_FORMAT
|
|
37
31
|
SUPPORT_OUT_FORMAT = (".pdf",)
|
|
38
32
|
|
|
@@ -53,13 +47,12 @@ def copy(doc: Doc) -> Doc:
|
|
|
53
47
|
:param doc: document to be copied
|
|
54
48
|
:return: copied document
|
|
55
49
|
"""
|
|
56
|
-
_doc = Doc(doc.name)
|
|
50
|
+
_doc = Doc(filename=doc.name)
|
|
57
51
|
if not _doc.is_pdf:
|
|
58
52
|
pdf_bites = _doc.convert_to_pdf()
|
|
59
53
|
_doc = Doc("pdf", pdf_bites)
|
|
60
54
|
if doc.pass_word is not None:
|
|
61
55
|
_doc.authenticate(doc.pass_word)
|
|
62
|
-
_doc.name = doc.name
|
|
63
56
|
_doc.rotatedPages = doc.rotatedPages
|
|
64
57
|
if len(_doc.rotatedPages) != 0:
|
|
65
58
|
for page in _doc.rotatedPages:
|
|
@@ -92,7 +85,12 @@ def open_pdf(file_name: str, parent: QWidget) -> Tuple[Optional[Doc], bool]:
|
|
|
92
85
|
if doc.needs_pass:
|
|
93
86
|
while doc.is_encrypted:
|
|
94
87
|
value, _ = QInputDialog.getText(
|
|
95
|
-
parent,
|
|
88
|
+
parent,
|
|
89
|
+
" ",
|
|
90
|
+
"Password:",
|
|
91
|
+
QLineEdit.EchoMode.Password,
|
|
92
|
+
"",
|
|
93
|
+
QtCore.Qt.WindowType.Dialog,
|
|
96
94
|
)
|
|
97
95
|
if not _:
|
|
98
96
|
doc.close()
|
|
@@ -110,15 +108,11 @@ def render_pdf_page(page_data: Doc.load_page) -> QtGui.QPixmap:
|
|
|
110
108
|
:param page_data: page data
|
|
111
109
|
:return: a QPixmap
|
|
112
110
|
"""
|
|
113
|
-
page_pixmap = get_pixmap(
|
|
114
|
-
page_data,
|
|
115
|
-
matrix=Identity,
|
|
116
|
-
clip=True,
|
|
117
|
-
)
|
|
111
|
+
page_pixmap = get_pixmap(page_data, matrix=Identity, clip=True)
|
|
118
112
|
if page_pixmap.alpha:
|
|
119
|
-
image_format = QtGui.QImage.Format_RGBA8888
|
|
113
|
+
image_format = QtGui.QImage.Format.Format_RGBA8888
|
|
120
114
|
else:
|
|
121
|
-
image_format = QtGui.QImage.Format_RGB888
|
|
115
|
+
image_format = QtGui.QImage.Format.Format_RGB888
|
|
122
116
|
page_image = QtGui.QImage(
|
|
123
117
|
page_pixmap.samples,
|
|
124
118
|
page_pixmap.w,
|
|
@@ -171,16 +165,8 @@ def add_watermark(
|
|
|
171
165
|
x, y = position
|
|
172
166
|
x, y = int(x), int(y)
|
|
173
167
|
for page in doc:
|
|
174
|
-
r1 = Rect(
|
|
175
|
-
|
|
176
|
-
10 + y,
|
|
177
|
-
page.rect.width - 10 + x,
|
|
178
|
-
page.rect.height - 10 + y,
|
|
179
|
-
)
|
|
180
|
-
pos0 = Point(
|
|
181
|
-
page.rect.width // 2 + x,
|
|
182
|
-
page.rect.height // 2 + y,
|
|
183
|
-
)
|
|
168
|
+
r1 = Rect(10 + x, 10 + y, page.rect.width - 10 + x, page.rect.height - 10 + y)
|
|
169
|
+
pos0 = Point(page.rect.width // 2 + x, page.rect.height // 2 + y)
|
|
184
170
|
shape = Shape(page)
|
|
185
171
|
shape.insert_textbox(
|
|
186
172
|
r1,
|
|
@@ -208,11 +194,7 @@ def setting_warning(set_file_name: str, parent: QWidget) -> dict:
|
|
|
208
194
|
:return: a dict loaded from JSON file or default values
|
|
209
195
|
"""
|
|
210
196
|
try:
|
|
211
|
-
with open(
|
|
212
|
-
set_file_name,
|
|
213
|
-
"r",
|
|
214
|
-
encoding="utf-8",
|
|
215
|
-
) as f:
|
|
197
|
+
with open(set_file_name, "r", encoding="utf-8") as f:
|
|
216
198
|
content = json.load(f)
|
|
217
199
|
if "start dir" not in content:
|
|
218
200
|
content["start dir"] = ""
|
|
@@ -236,11 +218,11 @@ def setting_warning(set_file_name: str, parent: QWidget) -> dict:
|
|
|
236
218
|
"Error",
|
|
237
219
|
f"Cannot find {os.path.basename(set_file_name)}\n\n"
|
|
238
220
|
f"Create an empty setting file?",
|
|
239
|
-
QMessageBox.Yes | QMessageBox.No,
|
|
221
|
+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
|
240
222
|
)
|
|
241
|
-
if reply == QMessageBox.No:
|
|
223
|
+
if reply == QMessageBox.StandardButton.No:
|
|
242
224
|
sys.exit(0)
|
|
243
|
-
if reply == QMessageBox.Yes:
|
|
225
|
+
if reply == QMessageBox.StandardButton.Yes:
|
|
244
226
|
content = {
|
|
245
227
|
"start dir": "",
|
|
246
228
|
"save dir": "",
|
|
@@ -281,7 +263,7 @@ def page_icon(page: Page, width: int, w_col: int, _scaled: float) -> QWidget:
|
|
|
281
263
|
label = QtWidgets.QLabel(None)
|
|
282
264
|
layout = QHBoxLayout(None)
|
|
283
265
|
widget = QWidget(None)
|
|
284
|
-
layout.addWidget(label, alignment=QtCore.Qt.AlignCenter)
|
|
266
|
+
layout.addWidget(label, alignment=QtCore.Qt.AlignmentFlag.AlignCenter)
|
|
285
267
|
widget.setLayout(layout)
|
|
286
268
|
if _cover.height() / _cover.width() >= 4 / 3:
|
|
287
269
|
scaled_height = int(width // w_col * 4 / 3 * _scaled)
|
|
@@ -293,11 +275,11 @@ def page_icon(page: Page, width: int, w_col: int, _scaled: float) -> QWidget:
|
|
|
293
275
|
QtGui.QPixmap(_cover).scaled(
|
|
294
276
|
scaled_width,
|
|
295
277
|
scaled_height,
|
|
296
|
-
QtCore.Qt.IgnoreAspectRatio,
|
|
297
|
-
QtCore.Qt.SmoothTransformation,
|
|
278
|
+
QtCore.Qt.AspectRatioMode.IgnoreAspectRatio,
|
|
279
|
+
QtCore.Qt.TransformationMode.SmoothTransformation,
|
|
298
280
|
),
|
|
299
281
|
)
|
|
300
|
-
label.setAlignment(QtCore.Qt.AlignCenter)
|
|
282
|
+
label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
|
301
283
|
label.setFixedSize(scaled_width, scaled_height)
|
|
302
284
|
shadow(label, QtGui.QColor(0, 0, 0, 100), 20)
|
|
303
285
|
del _cover, label, layout
|
|
@@ -318,9 +300,11 @@ def set_icon(
|
|
|
318
300
|
x, y = 0, 0
|
|
319
301
|
for i in widget.book_list:
|
|
320
302
|
label = page_icon(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
303
|
+
(
|
|
304
|
+
widget.book[i]
|
|
305
|
+
if isinstance(widget.book_list[0], int)
|
|
306
|
+
else (i[0] if doc is None else doc[0])
|
|
307
|
+
),
|
|
324
308
|
widget.table.width(),
|
|
325
309
|
widget.w_col,
|
|
326
310
|
_scaled,
|
|
@@ -408,24 +392,21 @@ def generate_menu(pos, widget: QWidget, main: QWidget, select: int = 0) -> None:
|
|
|
408
392
|
index = row_num * widget.w_col + col_num # get position
|
|
409
393
|
if 0 <= index < len(widget.book_list):
|
|
410
394
|
menu = QtWidgets.QMenu()
|
|
395
|
+
menu.setStyleSheet("font-size:12pt")
|
|
411
396
|
item1 = menu.addAction(
|
|
412
|
-
QtGui.QIcon(os.path.join(icon_path, "delete.svg")),
|
|
413
|
-
MENU_L[main.language][0],
|
|
397
|
+
QtGui.QIcon(os.path.join(icon_path, "delete.svg")), MENU_L[main.language][0]
|
|
414
398
|
)
|
|
415
399
|
item2, item3, item4, item5, item6, item7, item8 = (None for _ in range(7))
|
|
416
400
|
if select in (0, 2):
|
|
417
401
|
item3 = menu.addAction(
|
|
418
|
-
QtGui.QIcon(str(icon_path / "view.svg")),
|
|
419
|
-
MENU_L[main.language][1],
|
|
402
|
+
QtGui.QIcon(str(icon_path / "view.svg")), MENU_L[main.language][1]
|
|
420
403
|
)
|
|
421
404
|
if select == 1:
|
|
422
405
|
item2 = menu.addAction(
|
|
423
|
-
QtGui.QIcon(str(icon_path / "down.svg")),
|
|
424
|
-
MENU_L[main.language][2],
|
|
406
|
+
QtGui.QIcon(str(icon_path / "down.svg")), MENU_L[main.language][2]
|
|
425
407
|
)
|
|
426
408
|
item4 = menu.addAction(
|
|
427
|
-
QtGui.QIcon(str(icon_path / "Photo.svg")),
|
|
428
|
-
MENU_L[main.language][3],
|
|
409
|
+
QtGui.QIcon(str(icon_path / "Photo.svg")), MENU_L[main.language][3]
|
|
429
410
|
)
|
|
430
411
|
item5 = menu.addAction(
|
|
431
412
|
QtGui.QIcon(str(icon_path / "rotate_clockwise.svg")),
|
|
@@ -437,15 +418,13 @@ def generate_menu(pos, widget: QWidget, main: QWidget, select: int = 0) -> None:
|
|
|
437
418
|
)
|
|
438
419
|
if select in (1, 2):
|
|
439
420
|
item7 = menu.addAction(
|
|
440
|
-
QtGui.QIcon(str(icon_path / "move_page.svg")),
|
|
441
|
-
MENU_L[main.language][6],
|
|
421
|
+
QtGui.QIcon(str(icon_path / "move_page.svg")), MENU_L[main.language][6]
|
|
442
422
|
)
|
|
443
423
|
if select == 0:
|
|
444
424
|
item8 = menu.addAction(
|
|
445
|
-
QtGui.QIcon(str(icon_path / "arrow_move.svg")),
|
|
446
|
-
MENU_L[main.language][7],
|
|
425
|
+
QtGui.QIcon(str(icon_path / "arrow_move.svg")), MENU_L[main.language][7]
|
|
447
426
|
)
|
|
448
|
-
action = menu.
|
|
427
|
+
action = menu.exec(widget.table.mapToGlobal(pos))
|
|
449
428
|
if action == item1:
|
|
450
429
|
delete(index=index, widget=widget)
|
|
451
430
|
if action == item2 and select == 1:
|
|
@@ -567,7 +546,7 @@ def extract_img(index: int, widget: QWidget, main: QWidget) -> None:
|
|
|
567
546
|
main,
|
|
568
547
|
"Saved",
|
|
569
548
|
MESSAGE[main.language][1].format(len(img_inf), main.s_dir),
|
|
570
|
-
QMessageBox.Yes,
|
|
549
|
+
QMessageBox.StandardButton.Yes,
|
|
571
550
|
)
|
|
572
551
|
TOOLS.store_shrink(100) # delete MuPDF cache
|
|
573
552
|
|
|
@@ -611,7 +590,7 @@ def rearrange_page(index: int, widget: QWidget, parent: QWidget) -> None:
|
|
|
611
590
|
min=1,
|
|
612
591
|
max=book_length,
|
|
613
592
|
step=1,
|
|
614
|
-
flags=QtCore.Qt.Dialog,
|
|
593
|
+
flags=QtCore.Qt.WindowType.Dialog,
|
|
615
594
|
)
|
|
616
595
|
if not _:
|
|
617
596
|
return None
|
|
@@ -623,10 +602,7 @@ def rearrange_page(index: int, widget: QWidget, parent: QWidget) -> None:
|
|
|
623
602
|
widget.book_list.insert(value, page_index)
|
|
624
603
|
widget.book_list.remove(None)
|
|
625
604
|
widget.table.clearContents()
|
|
626
|
-
reset_table(
|
|
627
|
-
book_len=len(widget.book_list),
|
|
628
|
-
widget=widget,
|
|
629
|
-
)
|
|
605
|
+
reset_table(book_len=len(widget.book_list), widget=widget)
|
|
630
606
|
set_icon(widget)
|
|
631
607
|
return None
|
|
632
608
|
|
|
@@ -639,7 +615,7 @@ def _set_watermark_pos(main: QWidget) -> None:
|
|
|
639
615
|
:return: None
|
|
640
616
|
"""
|
|
641
617
|
pos_str, _ = QInputDialog.getText(
|
|
642
|
-
main, " ", "Set watermark position: x,y", flags=QtCore.Qt.Dialog
|
|
618
|
+
main, " ", "Set watermark position: x,y", flags=QtCore.Qt.WindowType.Dialog
|
|
643
619
|
)
|
|
644
620
|
if _:
|
|
645
621
|
pos = pos_str.strip().split(",")
|
|
@@ -836,10 +812,7 @@ def warning(parent) -> None:
|
|
|
836
812
|
:return: None
|
|
837
813
|
"""
|
|
838
814
|
QMessageBox.warning(
|
|
839
|
-
parent,
|
|
840
|
-
"Oops",
|
|
841
|
-
MESSAGE[parent.language][2],
|
|
842
|
-
QMessageBox.Yes,
|
|
815
|
+
parent, "Oops", MESSAGE[parent.language][2], QMessageBox.StandardButton.Yes
|
|
843
816
|
)
|
|
844
817
|
|
|
845
818
|
|
|
@@ -851,9 +824,6 @@ def _open_warning(parent: QWidget) -> Tuple[None, bool]:
|
|
|
851
824
|
:return: (None, False)
|
|
852
825
|
"""
|
|
853
826
|
QMessageBox.critical(
|
|
854
|
-
parent,
|
|
855
|
-
"Oops",
|
|
856
|
-
MESSAGE[parent.language][0],
|
|
857
|
-
QMessageBox.Yes,
|
|
827
|
+
parent, "Oops", MESSAGE[parent.language][0], QMessageBox.StandardButton.Yes
|
|
858
828
|
)
|
|
859
829
|
return None, False
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
language related functions
|
|
5
5
|
"""
|
|
6
|
-
from
|
|
6
|
+
from PyQt6 import QtWidgets
|
|
7
7
|
|
|
8
8
|
TAB_L = {
|
|
9
9
|
"English": [
|
|
@@ -12,7 +12,12 @@ TAB_L = {
|
|
|
12
12
|
" Security ",
|
|
13
13
|
" Metadata ",
|
|
14
14
|
],
|
|
15
|
-
"中文": [
|
|
15
|
+
"中文": [
|
|
16
|
+
" 合并文檔 ",
|
|
17
|
+
" 分割頁面 ",
|
|
18
|
+
" 檔案保護 ",
|
|
19
|
+
" 元數據 ",
|
|
20
|
+
],
|
|
16
21
|
"日本語": ["ファイル結合", "ページオルガナイズ", "電子透かし", "メタデータ"],
|
|
17
22
|
}
|
|
18
23
|
TIP_L = {
|
|
@@ -27,8 +32,28 @@ TIP_L = {
|
|
|
27
32
|
"font",
|
|
28
33
|
"update font",
|
|
29
34
|
],
|
|
30
|
-
"中文": [
|
|
31
|
-
|
|
35
|
+
"中文": [
|
|
36
|
+
"開啓檔案",
|
|
37
|
+
"保存",
|
|
38
|
+
"設定",
|
|
39
|
+
"清除",
|
|
40
|
+
"顔色",
|
|
41
|
+
"預覽",
|
|
42
|
+
"更多",
|
|
43
|
+
"字體",
|
|
44
|
+
"更新字體庫",
|
|
45
|
+
],
|
|
46
|
+
"日本語": [
|
|
47
|
+
"開く",
|
|
48
|
+
"保存する",
|
|
49
|
+
"設定",
|
|
50
|
+
"全て閉じる",
|
|
51
|
+
"色選ぶ",
|
|
52
|
+
"プレビュー",
|
|
53
|
+
"詳細設定",
|
|
54
|
+
"字体",
|
|
55
|
+
"字体を更新",
|
|
56
|
+
],
|
|
32
57
|
}
|
|
33
58
|
LAB_L3 = {
|
|
34
59
|
"English": [
|
|
@@ -41,7 +66,16 @@ LAB_L3 = {
|
|
|
41
66
|
"Preview Mode",
|
|
42
67
|
"Edit Restriction",
|
|
43
68
|
],
|
|
44
|
-
"中文": [
|
|
69
|
+
"中文": [
|
|
70
|
+
"密碼",
|
|
71
|
+
"水印",
|
|
72
|
+
"字號:",
|
|
73
|
+
"保存後開啓",
|
|
74
|
+
"透明度:",
|
|
75
|
+
"旋轉:",
|
|
76
|
+
"預覽模式",
|
|
77
|
+
"限制編輯",
|
|
78
|
+
],
|
|
45
79
|
"日本語": [
|
|
46
80
|
"パスワード",
|
|
47
81
|
"電子透かし",
|
|
@@ -174,7 +208,11 @@ MESSAGE = {
|
|
|
174
208
|
"{} image(s) saved to {}",
|
|
175
209
|
"Cannot save! Try a new file name...",
|
|
176
210
|
],
|
|
177
|
-
"中文": [
|
|
211
|
+
"中文": [
|
|
212
|
+
" 格式錯誤:\n 無法開啓此檔案",
|
|
213
|
+
"已保存{}張圖像至{}",
|
|
214
|
+
"無法保存欸。請嘗試新的文檔名稱。。。",
|
|
215
|
+
],
|
|
178
216
|
"日本語": [
|
|
179
217
|
" 格式エラー:\n このファイルが開けません",
|
|
180
218
|
"{}幅のイメージが{}に保存されました",
|
|
@@ -253,3 +291,7 @@ def lag_p(parent: QtWidgets.QWidget, language: str) -> None:
|
|
|
253
291
|
parent.label6.setText(LAB_LP[language][5])
|
|
254
292
|
parent.label7.setText(LAB_LP[language][6])
|
|
255
293
|
parent.label8.setText(LAB_LP[language][7])
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
if __name__ == "__main__":
|
|
297
|
+
...
|