├── .gitignore
├── LICENSE
├── app
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-313.pyc
│ └── config.cpython-313.pyc
├── config.py
├── log
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-313.pyc
│ │ ├── exception_handling.cpython-313.pyc
│ │ └── logger.cpython-313.pyc
│ ├── exception_handling.py
│ └── logger.py
├── model
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-313.pyc
│ │ ├── doc_cov_model.cpython-313.pyc
│ │ └── file_model.cpython-313.pyc
│ ├── doc_cov_model.py
│ └── file_model.py
├── ui
│ ├── Icon.py
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── Icon.cpython-313.pyc
│ │ ├── __init__.cpython-313.pyc
│ │ ├── global_signal.cpython-313.pyc
│ │ ├── mainview.cpython-313.pyc
│ │ └── mainwindow.cpython-313.pyc
│ ├── components
│ │ ├── CAvatar.py
│ │ ├── QCursorGif.py
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── QCursorGif.cpython-313.pyc
│ │ │ ├── __init__.cpython-313.pyc
│ │ │ ├── flowlayout.cpython-313.pyc
│ │ │ ├── router.cpython-313.pyc
│ │ │ └── scroll_bar.cpython-313.pyc
│ │ ├── calendar_dialog.py
│ │ ├── file_list
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-313.pyc
│ │ │ │ └── file_item_ui.cpython-313.pyc
│ │ │ ├── file_item_ui.py
│ │ │ ├── file_item_ui.ui
│ │ │ └── file_list_widget.py
│ │ ├── flowlayout.py
│ │ ├── form.py
│ │ ├── form.ui
│ │ ├── prompt_bar.py
│ │ ├── router.py
│ │ ├── scroll_bar.py
│ │ └── sidebar
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ ├── __init__.cpython-313.pyc
│ │ │ ├── sidebar.cpython-313.pyc
│ │ │ └── sidebar_ui.cpython-313.pyc
│ │ │ ├── sidebar.py
│ │ │ ├── sidebar_ui.py
│ │ │ └── sidebar_ui.ui
│ ├── doc_convert
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-313.pyc
│ │ │ ├── doc_convert.cpython-313.pyc
│ │ │ └── doc_convert_ui.cpython-313.pyc
│ │ ├── doc_convert.py
│ │ ├── doc_convert_ui.py
│ │ ├── doc_convert_ui.ui
│ │ ├── pdf2image
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-313.pyc
│ │ │ │ ├── pdf2image.cpython-313.pyc
│ │ │ │ └── pdf2image_ui.cpython-313.pyc
│ │ │ ├── pdf2image.py
│ │ │ ├── pdf2image_ui.py
│ │ │ └── pdf2image_ui.ui
│ │ ├── pdf2wordui
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-313.pyc
│ │ │ │ ├── pdf2word.cpython-313.pyc
│ │ │ │ └── pdf2word_ui.cpython-313.pyc
│ │ │ ├── pdf2word.py
│ │ │ ├── pdf2word_ui.py
│ │ │ └── pdf2word_ui.ui
│ │ └── web2pdf
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ ├── __init__.cpython-313.pyc
│ │ │ ├── web2pdf.cpython-313.pyc
│ │ │ └── web2pdf_ui.cpython-313.pyc
│ │ │ ├── web2pdf.py
│ │ │ ├── web2pdf_ui.py
│ │ │ └── web2pdf_ui.ui
│ ├── global_signal.py
│ ├── image_tools
│ │ ├── __pycache__
│ │ │ ├── image_tool.cpython-313.pyc
│ │ │ └── image_tool_ui.cpython-313.pyc
│ │ ├── image_tool.py
│ │ ├── image_tool_ui.py
│ │ ├── image_tool_ui.ui
│ │ └── modify_date
│ │ │ ├── __pycache__
│ │ │ ├── modify_date.cpython-313.pyc
│ │ │ └── modify_date_ui.cpython-313.pyc
│ │ │ ├── modify_date.py
│ │ │ ├── modify_date_ui.py
│ │ │ └── modify_date_ui.ui
│ ├── mainview.py
│ ├── mainwindow.py
│ ├── mainwindow.ui
│ ├── memotrace_enhance
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-313.pyc
│ │ │ ├── enhance.cpython-313.pyc
│ │ │ └── enhance_ui.cpython-313.pyc
│ │ ├── enhance.py
│ │ ├── enhance_ui.py
│ │ ├── enhance_ui.ui
│ │ └── toc
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ ├── __init__.cpython-313.pyc
│ │ │ ├── toc.cpython-313.pyc
│ │ │ └── toc_ui.cpython-313.pyc
│ │ │ ├── toc.py
│ │ │ ├── toc_ui.py
│ │ │ └── toc_ui.ui
│ ├── pdf_tools
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-313.pyc
│ │ │ ├── pdf_tool.cpython-313.pyc
│ │ │ └── pdf_tool_ui.cpython-313.pyc
│ │ ├── blank_pages
│ │ │ ├── blank_pages.py
│ │ │ └── blank_pages_ui.py
│ │ ├── conversion
│ │ │ └── __init__.py
│ │ ├── merge
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-313.pyc
│ │ │ │ ├── encrypt_dialog.cpython-313.pyc
│ │ │ │ ├── encrypt_dialog_ui.cpython-313.pyc
│ │ │ │ ├── merge.cpython-313.pyc
│ │ │ │ └── merge_ui.cpython-313.pyc
│ │ │ ├── encrypt_dialog.py
│ │ │ ├── encrypt_dialog_ui.py
│ │ │ ├── encrypt_dialog_ui.ui
│ │ │ ├── merge.py
│ │ │ ├── merge_ui.py
│ │ │ └── merge_ui.ui
│ │ ├── pdf_tool.py
│ │ ├── pdf_tool_ui.py
│ │ ├── pdf_tool_ui.ui
│ │ ├── security
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-313.pyc
│ │ │ │ ├── decrypt.cpython-313.pyc
│ │ │ │ ├── decrypt_ui.cpython-313.pyc
│ │ │ │ ├── encrypt.cpython-313.pyc
│ │ │ │ └── encrypt_ui.cpython-313.pyc
│ │ │ ├── decrypt.py
│ │ │ ├── decrypt_ui.py
│ │ │ ├── encrypt.py
│ │ │ └── encrypt_ui.py
│ │ ├── split
│ │ │ ├── __init__.py
│ │ │ ├── __pycache__
│ │ │ │ ├── __init__.cpython-313.pyc
│ │ │ │ ├── split.cpython-313.pyc
│ │ │ │ └── split_ui.cpython-313.pyc
│ │ │ ├── split.py
│ │ │ └── split_ui.py
│ │ └── watermark
│ │ │ ├── watermark.py
│ │ │ └── watermark_ui.py
│ ├── screen_record
│ │ ├── __init__.py
│ │ ├── screen_record.py
│ │ ├── screen_record_ui.py
│ │ └── screen_record_ui.ui
│ ├── setting
│ │ ├── __pycache__
│ │ │ ├── about_dialog.cpython-313.pyc
│ │ │ ├── seetingUi.cpython-313.pyc
│ │ │ └── setting.cpython-313.pyc
│ │ ├── about_dialog.py
│ │ ├── seetingUi.py
│ │ ├── seetingUi.ui
│ │ └── setting.py
│ └── video_tools
│ │ ├── __pycache__
│ │ ├── video_tool.cpython-313.pyc
│ │ └── video_tool_ui.cpython-313.pyc
│ │ ├── video_tool.py
│ │ ├── video_tool_ui.py
│ │ └── video_tool_ui.ui
└── util
│ ├── __init__.py
│ ├── __pycache__
│ ├── __init__.cpython-313.pyc
│ └── common.cpython-313.pyc
│ └── common.py
├── doc
└── images
│ ├── img.png
│ ├── img_1.png
│ ├── img_2.png
│ └── img_3.png
├── main.py
├── main1.spec
├── main2.spec
├── pdf2docx
├── AFFERO GPL
├── LICENSE
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-313.pyc
│ └── converter.cpython-313.pyc
├── common
│ ├── Block.py
│ ├── Collection.py
│ ├── Element.py
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── Block.cpython-313.pyc
│ │ ├── Collection.cpython-313.pyc
│ │ ├── Element.cpython-313.pyc
│ │ ├── __init__.cpython-313.pyc
│ │ ├── algorithm.cpython-313.pyc
│ │ ├── constants.cpython-313.pyc
│ │ ├── docx.cpython-313.pyc
│ │ └── share.cpython-313.pyc
│ ├── algorithm.py
│ ├── constants.py
│ ├── docx.py
│ └── share.py
├── converter.py
├── font
│ ├── Fonts.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── Fonts.cpython-313.pyc
│ │ └── __init__.cpython-313.pyc
├── image
│ ├── Image.py
│ ├── ImageBlock.py
│ ├── ImageSpan.py
│ ├── ImagesExtractor.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── Image.cpython-313.pyc
│ │ ├── ImageBlock.cpython-313.pyc
│ │ ├── ImageSpan.cpython-313.pyc
│ │ ├── ImagesExtractor.cpython-313.pyc
│ │ └── __init__.cpython-313.pyc
├── layout
│ ├── Blocks.py
│ ├── Column.py
│ ├── Layout.py
│ ├── Section.py
│ ├── Sections.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── Blocks.cpython-313.pyc
│ │ ├── Column.cpython-313.pyc
│ │ ├── Layout.cpython-313.pyc
│ │ ├── Section.cpython-313.pyc
│ │ ├── Sections.cpython-313.pyc
│ │ └── __init__.cpython-313.pyc
├── page
│ ├── BasePage.py
│ ├── Page.py
│ ├── Pages.py
│ ├── RawPage.py
│ ├── RawPageFactory.py
│ ├── RawPageFitz.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── BasePage.cpython-313.pyc
│ │ ├── Page.cpython-313.pyc
│ │ ├── Pages.cpython-313.pyc
│ │ ├── RawPage.cpython-313.pyc
│ │ ├── RawPageFactory.cpython-313.pyc
│ │ ├── RawPageFitz.cpython-313.pyc
│ │ └── __init__.cpython-313.pyc
├── shape
│ ├── Path.py
│ ├── Paths.py
│ ├── Shape.py
│ ├── Shapes.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── Path.cpython-313.pyc
│ │ ├── Paths.cpython-313.pyc
│ │ ├── Shape.cpython-313.pyc
│ │ ├── Shapes.cpython-313.pyc
│ │ └── __init__.cpython-313.pyc
├── table
│ ├── Border.py
│ ├── Cell.py
│ ├── Cells.py
│ ├── Row.py
│ ├── Rows.py
│ ├── TableBlock.py
│ ├── TableStructure.py
│ ├── TablesConstructor.py
│ ├── __init__.py
│ └── __pycache__
│ │ ├── Cell.cpython-313.pyc
│ │ ├── Cells.cpython-313.pyc
│ │ ├── Row.cpython-313.pyc
│ │ ├── Rows.cpython-313.pyc
│ │ ├── TableBlock.cpython-313.pyc
│ │ └── __init__.cpython-313.pyc
└── text
│ ├── Char.py
│ ├── Line.py
│ ├── Lines.py
│ ├── Spans.py
│ ├── TextBlock.py
│ ├── TextSpan.py
│ ├── __init__.py
│ └── __pycache__
│ ├── Char.cpython-313.pyc
│ ├── Line.cpython-313.pyc
│ ├── Lines.cpython-313.pyc
│ ├── Spans.cpython-313.pyc
│ ├── TextBlock.cpython-313.pyc
│ ├── TextSpan.cpython-313.pyc
│ └── __init__.cpython-313.pyc
├── readme.md
├── requirements.txt
├── resource.qrc
├── resource_rc.py
├── resources
├── QSS
│ └── style.qss
├── __init__.py
├── icons
│ ├── Cursors
│ │ ├── 0.png
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ ├── 5.png
│ │ ├── 6.png
│ │ └── 7.png
│ ├── Excel.svg
│ ├── __init__.py
│ ├── arrow-left.svg
│ ├── arrow-right.svg
│ ├── back.svg
│ ├── down.svg
│ ├── help.svg
│ ├── html.svg
│ ├── logo.ico
│ ├── logo.png
│ ├── markdown.svg
│ ├── pdf.svg
│ ├── select.svg
│ ├── setting.svg
│ ├── txt.svg
│ ├── unselect.svg
│ ├── up.svg
│ ├── weixin.png
│ ├── word.svg
│ ├── 减.svg
│ ├── 删除.svg
│ ├── 加.svg
│ ├── 右展开.svg
│ ├── 合并.svg
│ ├── 图片.svg
│ ├── 增加.svg
│ ├── 工具箱.svg
│ ├── 左展开.svg
│ ├── 录屏.svg
│ ├── 批量操作.svg
│ ├── 批量添加.svg
│ ├── 拆分.svg
│ ├── 文档转换.svg
│ ├── 水印.svg
│ ├── 视频.svg
│ ├── 钥匙.svg
│ └── 锁.svg
└── images
│ └── logo.png
├── screenshot
└── screenrecord.py
└── setup.py
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Qt template
2 | # C++ objects and libs
3 | *.slo
4 | *.lo
5 | *.o
6 | *.a
7 | *.la
8 | *.lai
9 | *.so
10 | *.so.*
11 | *.dll
12 | *.dylib
13 |
14 | # Qt-es
15 | object_script.*.Release
16 | object_script.*.Debug
17 | *_plugin_import.cpp
18 | /.qmake.cache
19 | /.qmake.stash
20 | *.pro.user
21 | *.pro.user.*
22 | *.qbs.user
23 | *.qbs.user.*
24 | *.moc
25 | moc_*.cpp
26 | moc_*.h
27 | qrc_*.cpp
28 | ui_*.h
29 | *.qmlc
30 | *.jsc
31 | Makefile*
32 | *build-*
33 | *.qm
34 | *.prl
35 |
36 | # Qt unit tests
37 | target_wrapper.*
38 |
39 | # QtCreator
40 | *.autosave
41 |
42 | # QtCreator Qml
43 | *.qmlproject.user
44 | *.qmlproject.user.*
45 |
46 | # QtCreator CMake
47 | CMakeLists.txt.user*
48 |
49 | # QtCreator 4.8< compilation database
50 | compile_commands.json
51 |
52 | # QtCreator local machine specific files for imported projects
53 | *creator.user*
54 |
55 | *_qmlcache.qrc
56 |
57 | ### PyCharm template
58 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
59 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
60 |
61 | # User-specific stuff
62 | .idea/**/workspace.xml
63 | .idea/**/tasks.xml
64 | .idea/**/usage.statistics.xml
65 | .idea/**/dictionaries
66 | .idea/**/shelf
67 |
68 | # AWS User-specific
69 | .idea/**/aws.xml
70 |
71 | # Generated files
72 | .idea/**/contentModel.xml
73 |
74 | # Sensitive or high-churn files
75 | .idea/**/dataSources/
76 | .idea/**/dataSources.ids
77 | .idea/**/dataSources.local.xml
78 | .idea/**/sqlDataSources.xml
79 | .idea/**/dynamic.xml
80 | .idea/**/uiDesigner.xml
81 | .idea/**/dbnavigator.xml
82 |
83 | # Gradle
84 | .idea/**/gradle.xml
85 | .idea/**/libraries
86 |
87 | # Gradle and Maven with auto-import
88 | # When using Gradle or Maven with auto-import, you should exclude module files,
89 | # since they will be recreated, and may cause churn. Uncomment if using
90 | # auto-import.
91 | # .idea/artifacts
92 | # .idea/compiler.xml
93 | # .idea/jarRepositories.xml
94 | # .idea/modules.xml
95 | # .idea/*.iml
96 | # .idea/modules
97 | # *.iml
98 | # *.ipr
99 |
100 | # CMake
101 | cmake-build-*/
102 |
103 | # Mongo Explorer plugin
104 | .idea/**/mongoSettings.xml
105 |
106 | # File-based project format
107 | *.iws
108 |
109 | # IntelliJ
110 | out/
111 |
112 | # mpeltonen/sbt-idea plugin
113 | .idea_modules/
114 |
115 | # JIRA plugin
116 | atlassian-ide-plugin.xml
117 |
118 | # Cursive Clojure plugin
119 | .idea/replstate.xml
120 |
121 | # SonarLint plugin
122 | .idea/sonarlint/
123 |
124 | # Crashlytics plugin (for Android Studio and IntelliJ)
125 | com_crashlytics_export_strings.xml
126 | crashlytics.properties
127 | crashlytics-build.properties
128 | fabric.properties
129 |
130 | # Editor-based Rest Client
131 | .idea/httpRequests
132 |
133 | # Android studio 3.1+ serialized cache file
134 | .idea/caches/build_file_checksums.ser
135 |
136 | ### Example user template template
137 | ### Example user template
138 |
139 | # IntelliJ project files
140 | .idea
141 | *.iml
142 | out
143 | gen
144 | dist
145 | build
146 | *test*
147 | *.log
148 | *.c
149 | *.pyd
150 | __pycache__/
151 | *.pyc
--------------------------------------------------------------------------------
/app/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/7 10:51
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/__pycache__/config.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/__pycache__/config.cpython-313.pyc
--------------------------------------------------------------------------------
/app/config.py:
--------------------------------------------------------------------------------
1 | version = '0.1.4'
2 | contact = ''
3 | github = ''
4 | website = 'https://memotrace.cn/tools/'
5 | copyright = '© 2022-2024 SiYuan'
6 | license = ''
7 | description = [
8 |
9 | ]
10 | about = f'''
11 | 版本:{version}
12 | QQ交流群:请关注微信公众号回复:联系方式
13 | 地址:{github}
14 | 官网:{website}
15 | 新特性:
{''.join(['' + i for i in description])}
16 | Copyright {copyright}
17 | '''
--------------------------------------------------------------------------------
/app/log/__init__.py:
--------------------------------------------------------------------------------
1 | from .logger import log, logger
2 |
3 | __all__ = ["logger", "log"]
4 |
--------------------------------------------------------------------------------
/app/log/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/log/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/log/__pycache__/exception_handling.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/log/__pycache__/exception_handling.cpython-313.pyc
--------------------------------------------------------------------------------
/app/log/__pycache__/logger.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/log/__pycache__/logger.cpython-313.pyc
--------------------------------------------------------------------------------
/app/log/exception_handling.py:
--------------------------------------------------------------------------------
1 | import sys,os
2 | import traceback
3 | from app.config import version
4 |
5 |
6 | class ExceptionHanding:
7 | def __init__(self, exc_type, exc_value, traceback_):
8 | self.exc_type = exc_type
9 | self.exc_value = exc_value
10 | self.traceback = traceback_
11 | self.error_message = ''.join(traceback.format_exception(exc_type, exc_value, traceback_))
12 |
13 | def parser_exc(self):
14 | return (f'{self.error_message}\n未知错误类型,可参考 https://memotrace.cn/doc/posts/error/faq.html '
15 | f'解决该问题\n温馨提示:重启电脑可解决80%的问题')
16 |
17 | def __str__(self):
18 | errmsg = f'version:{version}\n{self.parser_exc()}'
19 | return errmsg
20 |
21 |
22 | def excepthook(exc_type, exc_value, traceback_):
23 | # 将异常信息转为字符串
24 |
25 | # 在这里处理全局异常
26 |
27 | error_message = ExceptionHanding(exc_type, exc_value, traceback_)
28 | txt = '您可添加QQ群发送log文件以便解决该问题'
29 | msg = f"Exception Type: {exc_type.__name__}\nException Value: {exc_value}\ndetails: {error_message}\n\n{txt}"
30 | print(msg)
31 |
32 | # 调用原始的 excepthook,以便程序正常退出
33 | sys.__excepthook__(exc_type, exc_value, traceback_)
34 |
--------------------------------------------------------------------------------
/app/log/logger.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | import time
4 | import traceback
5 | from functools import wraps
6 | filename = time.strftime("%Y-%m-%d", time.localtime(time.time()))
7 | logger = logging.getLogger('test')
8 | logger.setLevel(level=logging.DEBUG)
9 | formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
10 | try:
11 | if not os.path.exists('./app/log/logs'):
12 | os.mkdir('./app/log/logs')
13 | file_handler = logging.FileHandler(f'./app/log/logs/{filename}-log.log')
14 | except:
15 | file_handler = logging.FileHandler(f'日志文件-{filename}-log.log')
16 |
17 | file_handler.setLevel(level=logging.INFO)
18 | file_handler.setFormatter(formatter)
19 | stream_handler = logging.StreamHandler()
20 | stream_handler.setLevel(logging.DEBUG)
21 | stream_handler.setFormatter(formatter)
22 | logger.addHandler(file_handler)
23 | logger.addHandler(stream_handler)
24 |
25 |
26 | def log(func):
27 | @wraps(func)
28 | def log_(*args, **kwargs):
29 | try:
30 | return func(*args, **kwargs)
31 | except Exception as e:
32 | logger.error(
33 | f"\n{func.__qualname__} is error,params:{(args, kwargs)},here are details:\n{traceback.format_exc()}")
34 | return log_
35 |
--------------------------------------------------------------------------------
/app/model/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/20 14:30
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 | from .file_model import FileInfo, PdfFile, FileType, ImageFile
12 | from .doc_cov_model import Pdf2ImageOpt, Pdf2DocxOpt
13 |
14 | if __name__ == '__main__':
15 | pass
16 |
--------------------------------------------------------------------------------
/app/model/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/model/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/model/__pycache__/doc_cov_model.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/model/__pycache__/doc_cov_model.cpython-313.pyc
--------------------------------------------------------------------------------
/app/model/__pycache__/file_model.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/model/__pycache__/file_model.cpython-313.pyc
--------------------------------------------------------------------------------
/app/model/doc_cov_model.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/26 0:56
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-doc_cov_model.py
9 | @Description : 描述文档转换的配置选项
10 | """
11 | import re
12 |
13 |
14 | def format_file_name(filename):
15 | return re.sub(r'[\\/:*?"<>|\s\.]', '_', filename)
16 |
17 |
18 | class Pdf2DocxOpt:
19 | def __init__(self, output_path):
20 | self.o_dir = output_path
21 |
22 |
23 | class Pdf2ImageOpt:
24 | def __init__(self, output_dir, format_='png', dpi=200):
25 | self.o_dir = output_dir
26 | self.o_fmt = format_
27 | self.o_name = '(转图片)'
28 | self.o_quality = 100
29 | self.o_dpi = dpi
30 |
31 |
32 | class Web2PdfOpt:
33 | def __init__(self, url: str, output_dir='.'):
34 | self.url = url
35 | self.is_url = url.startswith('http')
36 | self.o_dir = output_dir
37 | self.o_name = ''
38 | self.set_name(url)
39 |
40 | def set_name(self, name: str):
41 | name = format_file_name(name)
42 | if name.endswith('.pdf'):
43 | self.o_name = name
44 | else:
45 | self.o_name = name + '.pdf'
46 |
47 | return self.o_name
48 |
49 |
50 | if __name__ == '__main__':
51 | pass
52 |
--------------------------------------------------------------------------------
/app/ui/Icon.py:
--------------------------------------------------------------------------------
1 | from PySide6.QtGui import QIcon
2 |
3 | import resource_rc
4 |
5 | var = resource_rc.qt_resource_name
6 |
7 |
8 | class Icon:
9 | logo_path = ':/icons/resources/icons/logo.png'
10 | logo_ico_path = ':/icons/resources/icons/logo.ico'
11 | # MainWindow_Icon = QIcon(':/icons/icons/logo.svg')
12 | Back = QIcon(':/icons/resources/icons/back.svg')
13 | Tool_Icon = QIcon(':/icons/resources/icons/工具箱.svg')
14 | Arrow_left_Icon = QIcon(':/icons/resources/icons/arrow-left.svg')
15 | Arrow_right_Icon = QIcon(':/icons/resources/icons/arrow-right.svg')
16 | Setting_Icon = QIcon(':/icons/resources/icons/setting.svg')
17 | Add_Icon = QIcon(':/icons/icons/resources/批量添加.svg')
18 | Exp_left_Icon = QIcon(':/icons/resources/icons/左展开.svg')
19 | Exp_right_Icon = QIcon(':/icons/resources/icons/右展开.svg')
20 | Img_Icon = QIcon(':/icons/resources/icons/图片.svg')
21 | PDF_Icon = QIcon(':/icons/resources/icons/pdf.svg')
22 | Doc_Transfer_Icon = QIcon(':/icons/resources/icons/文档转换.svg')
23 | Batch_Icon = QIcon(':/icons/resources/icons/批量操作.svg')
24 | Video_Icon = QIcon(':/icons/resources/icons/视频.svg')
25 |
--------------------------------------------------------------------------------
/app/ui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/__init__.py
--------------------------------------------------------------------------------
/app/ui/__pycache__/Icon.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/__pycache__/Icon.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/__pycache__/global_signal.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/__pycache__/global_signal.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/__pycache__/mainview.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/__pycache__/mainview.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/__pycache__/mainwindow.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/__pycache__/mainwindow.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/QCursorGif.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | Created on 2020年3月13日
6 | @author: Irony
7 | @site: https://pyqt.site , https://github.com/PySide6
8 | @email: 892768447@qq.com
9 | @file: Demo.Lib.QCursorGif
10 | @description:
11 | """
12 |
13 | # try:
14 | # from PySide6.QtCore import QTimer, Qt
15 | # from PySide6.QtGui import QCursor, QPixmap
16 | # from PySide6.QtWidgets import QApplication
17 | # except ImportError:
18 | # from PySide6.QtCore import QTimer, Qt
19 | # from PySide6.QtGui import QCursor, QPixmap
20 | # from PySide6.QtWidgets import QApplication
21 |
22 | from PySide6.QtCore import QTimer, Qt
23 | from PySide6.QtGui import QCursor, QPixmap
24 | from PySide6.QtWidgets import QApplication
25 | import resource_rc
26 |
27 | var = resource_rc.qt_resource_name
28 |
29 |
30 | class QCursorGif:
31 |
32 | def initCursor(self, cursors, parent=None):
33 | # 记录默认的光标
34 | self._oldCursor = Qt.ArrowCursor
35 | self.setOldCursor(parent)
36 | # 加载光标图片
37 | self._cursorImages = [
38 | QCursor(QPixmap(cursor)) for cursor in cursors]
39 | self._cursorIndex = 0
40 | self._cursorCount = len(self._cursorImages) - 1
41 | # 创建刷新定时器
42 | self._cursorTimeout = 200
43 | self._cursorTimer = QTimer(parent)
44 | self._cursorTimer.timeout.connect(self._doBusy)
45 | self.num = 0
46 |
47 | def _doBusy(self):
48 | if self._cursorIndex > self._cursorCount:
49 | self._cursorIndex = 0
50 | QApplication.setOverrideCursor(
51 | self._cursorImages[self._cursorIndex])
52 | self._cursorIndex += 1
53 | self.num += 1
54 |
55 | def startBusy(self):
56 | # QApplication.setOverrideCursor(Qt.WaitCursor)
57 | if not self._cursorTimer.isActive():
58 | self._cursorTimer.start(self._cursorTimeout)
59 |
60 | def stopBusy(self):
61 | self._cursorTimer.stop()
62 | QApplication.restoreOverrideCursor()
63 | # 将光标出栈,恢复至原始状态
64 | for i in range(self.num):
65 | QApplication.restoreOverrideCursor()
66 | self.num = 0
67 |
68 |
69 | def setCursorTimeout(self, timeout):
70 | self._cursorTimeout = timeout
71 |
72 | def setOldCursor(self, parent=None):
73 | QApplication.overrideCursor()
74 | self._oldCursor = (QApplication.overrideCursor() or parent.cursor() or Qt.ArrowCursor or Qt.IBeamCursor) if parent else (
75 | QApplication.overrideCursor() or Qt.ArrowCursor)
76 |
--------------------------------------------------------------------------------
/app/ui/components/__init__.py:
--------------------------------------------------------------------------------
1 | from .scroll_bar import ScrollBar
2 | from .QCursorGif import QCursorGif
3 | from app.ui.components.sidebar.sidebar import Sidebar, SidebarButton
4 | from .flowlayout import FlowLayout
5 |
--------------------------------------------------------------------------------
/app/ui/components/__pycache__/QCursorGif.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/__pycache__/QCursorGif.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/__pycache__/flowlayout.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/__pycache__/flowlayout.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/__pycache__/router.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/__pycache__/router.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/__pycache__/scroll_bar.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/__pycache__/scroll_bar.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/calendar_dialog.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from datetime import datetime, timedelta
4 | from PySide6.QtCore import Signal, Qt, QLocale
5 | from PySide6.QtWidgets import QApplication, QDialog, QCalendarWidget, QVBoxLayout, \
6 | QToolButton
7 |
8 | from app.ui.Icon import Icon
9 |
10 |
11 | class CalendarDialog(QDialog):
12 | selected_date_signal = Signal(int)
13 |
14 | def __init__(self, date_range=None, parent=None):
15 | """
16 |
17 | @param date_range: tuple[Union[QDate, datetime.date],Union[QDate, datetime.date]] #限定的可选择范围
18 | @param parent:
19 | """
20 | super().__init__(parent)
21 | self.setWindowTitle('选择日期')
22 | self.calendar = QCalendarWidget(self)
23 | self.calendar.setLocale(QLocale(QLocale.Chinese, QLocale.China))
24 | self.calendar.clicked.connect(self.onDateChanged)
25 | prev_btn = self.calendar.findChild(QToolButton, "qt_calendar_prevmonth")
26 | prev_btn.setIcon(Icon.Arrow_left_Icon)
27 | next_btn = self.calendar.findChild(QToolButton, "qt_calendar_nextmonth")
28 | next_btn.setIcon(Icon.Arrow_right_Icon)
29 | self.date_range = date_range
30 | if date_range:
31 | self.calendar.setDateRange(*date_range)
32 | # 从第一天开始,依次添加日期到列表,直到该月的最后一天
33 | current_date = date_range[1]
34 | while (current_date + timedelta(days=1)).month == date_range[1].month:
35 | current_date += timedelta(days=1)
36 | range_format = self.calendar.dateTextFormat(current_date)
37 | range_format.setForeground(Qt.gray)
38 | self.calendar.setDateTextFormat(current_date, range_format)
39 | # 从第一天开始,依次添加日期到列表,直到该月的最后一天
40 | current_date = date_range[0]
41 | while (current_date - timedelta(days=1)).month == date_range[0].month:
42 | current_date -= timedelta(days=1)
43 | range_format = self.calendar.dateTextFormat(current_date)
44 | range_format.setForeground(Qt.gray)
45 | self.calendar.setDateTextFormat(current_date, range_format)
46 | layout = QVBoxLayout(self)
47 | layout.addWidget(self.calendar)
48 | self.setLayout(layout)
49 |
50 | def set_start_date(self):
51 | if self.date_range:
52 | self.calendar.setCurrentPage(self.date_range[0].year, self.date_range[0].month)
53 |
54 | def set_end_date(self):
55 | if self.date_range:
56 | self.calendar.setCurrentPage(self.date_range[1].year, self.date_range[1].month)
57 |
58 | def onDateChanged(self):
59 | # 获取选择的日期
60 | selected_date = self.calendar.selectedDate()
61 | selected_date_str = selected_date.toString(Qt.ISODate) # 使用 ISO 标准格式
62 | s_t = time.strptime(selected_date_str, "%Y-%m-%d") # 返回元祖
63 | mkt = int(time.mktime(s_t))
64 | timestamp = mkt
65 | self.selected_date_signal.emit(timestamp)
66 | print("Selected Date:", selected_date_str, timestamp)
67 | self.close()
68 |
69 |
70 | if __name__ == '__main__':
71 | import sys
72 | from datetime import datetime, timedelta
73 |
74 | app = QApplication(sys.argv)
75 | # 设置日期范围
76 | start_date = datetime(2024, 1, 5)
77 | end_date = datetime(2024, 1, 9)
78 | date_range = (start_date.date(), end_date.date())
79 | ex = CalendarDialog(date_range=date_range)
80 | ex.show()
81 | sys.exit(app.exec_())
82 |
--------------------------------------------------------------------------------
/app/ui/components/file_list/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/file_list/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/file_list/__pycache__/file_item_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/file_list/__pycache__/file_item_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/file_list/file_list_widget.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/8 22:38
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-file_list_widget.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/components/flowlayout.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/30 19:26
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-flowlayout.py
9 | @Description :
10 | """
11 | try:
12 | from PySide6.QtCore import QPoint, QRect, QSize, Qt
13 | from PySide6.QtWidgets import (QApplication, QLayout, QPushButton,
14 | QSizePolicy, QWidget)
15 | except ImportError:
16 | from PySide2.QtCore import QPoint, QRect, QSize, Qt
17 | from PySide2.QtWidgets import (QApplication, QLayout, QPushButton,
18 | QSizePolicy, QWidget)
19 |
20 |
21 | class FlowLayout(QLayout):
22 | def __init__(self, parent=None, margin=0, spacing=-1):
23 | super(FlowLayout, self).__init__(parent)
24 |
25 | if parent is not None:
26 | self.setContentsMargins(margin, margin, margin, margin)
27 |
28 | self.setSpacing(spacing)
29 |
30 | self.itemList = []
31 |
32 | def __del__(self):
33 | item = self.takeAt(0)
34 | while item:
35 | item = self.takeAt(0)
36 |
37 | def addItem(self, item):
38 | self.itemList.append(item)
39 |
40 | def clear(self):
41 | item = self.takeAt(0)
42 | while item:
43 | item = self.takeAt(0)
44 |
45 | def count(self):
46 | return len(self.itemList)
47 |
48 | def itemAt(self, index):
49 | if index >= 0 and index < len(self.itemList):
50 | return self.itemList[index]
51 |
52 | return None
53 |
54 | def takeAt(self, index):
55 | if index >= 0 and index < len(self.itemList):
56 | return self.itemList.pop(index)
57 |
58 | return None
59 |
60 | def expandingDirections(self):
61 | return Qt.Orientations(Qt.Orientation(0))
62 |
63 | def hasHeightForWidth(self):
64 | return True
65 |
66 | def heightForWidth(self, width):
67 | height = self.doLayout(QRect(0, 0, width, 0), True)
68 | return height
69 |
70 | def setGeometry(self, rect):
71 | super(FlowLayout, self).setGeometry(rect)
72 | self.doLayout(rect, False)
73 |
74 | def sizeHint(self):
75 | return self.minimumSize()
76 |
77 | def minimumSize(self):
78 | size = QSize()
79 |
80 | for item in self.itemList:
81 | size = size.expandedTo(item.minimumSize())
82 |
83 | margin, _, _, _ = self.getContentsMargins()
84 |
85 | size += QSize(2 * margin, 2 * margin)
86 | return size
87 |
88 | def doLayout(self, rect, testOnly):
89 | x = rect.x()
90 | y = rect.y()
91 | lineHeight = 0
92 |
93 | for item in self.itemList:
94 | wid = item.widget()
95 | spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
96 | QSizePolicy.PushButton, Qt.Horizontal)
97 | spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.PushButton,
98 | QSizePolicy.PushButton, Qt.Vertical)
99 | nextX = x + item.sizeHint().width() + spaceX
100 | if nextX - spaceX > rect.right() and lineHeight > 0:
101 | x = rect.x()
102 | y = y + lineHeight + spaceY
103 | nextX = x + item.sizeHint().width() + spaceX
104 | lineHeight = 0
105 |
106 | if not testOnly:
107 | item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
108 |
109 | x = nextX
110 | lineHeight = max(lineHeight, item.sizeHint().height())
111 |
112 | return y + lineHeight - rect.y()
113 |
114 |
115 | class Window(QWidget):
116 | def __init__(self):
117 | super(Window, self).__init__()
118 |
119 | flowLayout = FlowLayout()
120 | flowLayout.addWidget(QPushButton("Short"))
121 | flowLayout.addWidget(QPushButton("Longer"))
122 | flowLayout.addWidget(QPushButton("Different text"))
123 | flowLayout.addWidget(QPushButton("More text"))
124 | flowLayout.addWidget(QPushButton("Even longer button text"))
125 | self.setLayout(flowLayout)
126 |
127 | self.setWindowTitle("Flow Layout")
128 |
129 |
130 | if __name__ == '__main__':
131 | import sys
132 |
133 | app = QApplication(sys.argv)
134 | mainWin = Window()
135 | mainWin.show()
136 | sys.exit(app.exec_())
137 |
--------------------------------------------------------------------------------
/app/ui/components/form.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'form.ui'
4 | #
5 | # Created by: PySide6 UI code generator 5.15.10
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 | from PySide6 import QtCore, QtGui, QtWidgets
12 |
13 |
14 | class Ui_Form(object):
15 | def setupUi(self, Form):
16 | Form.setObjectName("Form")
17 | Form.resize(250, 92)
18 | Form.setMaximumSize(QtCore.QSize(250, 16777215))
19 | self.gridLayout = QtWidgets.QGridLayout(Form)
20 | self.gridLayout.setObjectName("gridLayout")
21 | self.label_avatar = QtWidgets.QLabel(Form)
22 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
23 | sizePolicy.setHorizontalStretch(0)
24 | sizePolicy.setVerticalStretch(0)
25 | sizePolicy.setHeightForWidth(self.label_avatar.sizePolicy().hasHeightForWidth())
26 | self.label_avatar.setSizePolicy(sizePolicy)
27 | self.label_avatar.setMinimumSize(QtCore.QSize(45, 45))
28 | self.label_avatar.setMaximumSize(QtCore.QSize(45, 45))
29 | self.label_avatar.setObjectName("label_avatar")
30 | self.gridLayout.addWidget(self.label_avatar, 0, 0, 2, 1)
31 | self.label_nickname = QtWidgets.QLabel(Form)
32 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
33 | sizePolicy.setHorizontalStretch(0)
34 | sizePolicy.setVerticalStretch(0)
35 | sizePolicy.setHeightForWidth(self.label_nickname.sizePolicy().hasHeightForWidth())
36 | self.label_nickname.setSizePolicy(sizePolicy)
37 | self.label_nickname.setObjectName("label_nickname")
38 | self.gridLayout.addWidget(self.label_nickname, 0, 1, 1, 1)
39 | self.label_time = QtWidgets.QLabel(Form)
40 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
41 | sizePolicy.setHorizontalStretch(0)
42 | sizePolicy.setVerticalStretch(0)
43 | sizePolicy.setHeightForWidth(self.label_time.sizePolicy().hasHeightForWidth())
44 | self.label_time.setSizePolicy(sizePolicy)
45 | font = QtGui.QFont()
46 | font.setPointSize(8)
47 | self.label_time.setFont(font)
48 | self.label_time.setObjectName("label_time")
49 | self.gridLayout.addWidget(self.label_time, 0, 2, 1, 1)
50 | self.label_content = QtWidgets.QLabel(Form)
51 | font = QtGui.QFont()
52 | font.setPointSize(8)
53 | self.label_content.setFont(font)
54 | self.label_content.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse)
55 | self.label_content.setObjectName("label_content")
56 | self.gridLayout.addWidget(self.label_content, 1, 1, 1, 2)
57 |
58 | self.retranslateUi(Form)
59 | QtCore.QMetaObject.connectSlotsByName(Form)
60 |
61 | def retranslateUi(self, Form):
62 | _translate = QtCore.QCoreApplication.translate
63 | Form.setWindowTitle(_translate("Form", "Form"))
64 | self.label_avatar.setText(_translate("Form", "TextLabel"))
65 | self.label_nickname.setText(_translate("Form", "TextLabel"))
66 | self.label_time.setText(_translate("Form", "24/3/17"))
67 | self.label_content.setText(_translate("Form", "TextLabel"))
68 |
--------------------------------------------------------------------------------
/app/ui/components/form.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 250
10 | 92
11 |
12 |
13 |
14 |
15 | 250
16 | 16777215
17 |
18 |
19 |
20 | Form
21 |
22 |
23 | -
24 |
25 |
26 |
27 | 0
28 | 0
29 |
30 |
31 |
32 |
33 | 45
34 | 45
35 |
36 |
37 |
38 |
39 | 45
40 | 45
41 |
42 |
43 |
44 | TextLabel
45 |
46 |
47 |
48 | -
49 |
50 |
51 |
52 | 0
53 | 0
54 |
55 |
56 |
57 | TextLabel
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 | 0
66 | 0
67 |
68 |
69 |
70 |
71 | 8
72 |
73 |
74 |
75 | 24/3/17
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 | 8
84 |
85 |
86 |
87 | TextLabel
88 |
89 |
90 | Qt::LinksAccessibleByMouse
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/app/ui/components/prompt_bar.py:
--------------------------------------------------------------------------------
1 | from PySide6 import QtGui
2 | from PySide6.QtCore import *
3 | from PySide6.QtGui import *
4 | from PySide6.QtWidgets import *
5 |
6 |
7 | class PromptBar(QLabel):
8 | def __init__(self, parent=None):
9 | super().__init__(parent)
10 |
11 | def paintEvent(self, e): # 绘图事件
12 | qp = QPainter()
13 | qp.begin(self)
14 | self.drawRectangles1(qp) # 绘制线条矩形
15 | self.drawRectangles2(qp) # 绘制填充矩形
16 | self.drawRectangles3(qp) # 绘制线条+填充矩形
17 | self.drawRectangles4(qp) # 绘制线条矩形2
18 | qp.end()
19 |
20 | def drawRectangles1(self, qp): # 绘制填充矩形
21 | qp.setPen(QPen(Qt.black, 2, Qt.SolidLine)) # 颜色、线宽、线性
22 | qp.drawRect(*self.data)
23 |
24 | def drawRectangles2(self, qp): # 绘制填充矩形
25 | qp.setPen(QPen(Qt.black, 2, Qt.NoPen))
26 | qp.setBrush(QColor(200, 0, 0))
27 | qp.drawRect(220, 15, 200, 100)
28 |
29 | def drawRectangles3(self, qp): # 绘制线条+填充矩形
30 | qp.setPen(QPen(Qt.black, 2, Qt.SolidLine))
31 | qp.setBrush(QColor(200, 0, 0))
32 | qp.drawRect(430, 15, 200, 100)
33 |
34 | def drawRectangles4(self, qp): # 绘制线条矩形2
35 | path = QtGui.QPainterPath()
36 | qp.setPen(QPen(Qt.blue, 2, Qt.SolidLine))
37 | qp.setBrush(QColor(0, 0, 0, 0)) # 设置画刷颜色透明
38 | path.addRect(100, 200, 200, 100)
39 | qp.drawPath(path)
40 |
--------------------------------------------------------------------------------
/app/ui/components/router.py:
--------------------------------------------------------------------------------
1 | from PySide6.QtCore import QObject, Signal
2 |
3 |
4 | class Router(QObject):
5 | """ 路由管理器,用于管理页面和路由路径 """
6 | route_changed = Signal(str)
7 | history_changed = Signal(int)
8 |
9 | def __init__(self, stack):
10 | """
11 |
12 | :param stack: 存储页面的stackWidget组件,可通过索引直接显示某个页面,如果为None则直接调用页面的show方法显示到独立窗口上
13 | """
14 | super(Router, self).__init__()
15 | self.stack = stack
16 | self.routes = {}
17 | self.history = []
18 | self.now_router_path = ''
19 |
20 | def add_route(self, path, widget):
21 | """添加路径和页面的映射"""
22 | if self.stack is not None:
23 | index = self.stack.addWidget(widget)
24 | self.routes[path] = index
25 | else:
26 | self.routes[path] = widget
27 | index = len(self.routes)
28 | return index
29 |
30 | def navigate(self, path, turn_back=False):
31 | """
32 | 根据路径切换到对应的页面
33 | :param path:
34 | :param turn_back: 是否是返回调用的页面切换
35 | :return:
36 | """
37 | if self.now_router_path and not turn_back:
38 | self.history.append(self.now_router_path)
39 | self.history_changed.emit(len(self.history))
40 | if path in self.routes:
41 | if self.stack is not None:
42 | self.stack.setCurrentIndex(self.routes[path])
43 | else:
44 | self.routes[path].show()
45 | self.route_changed.emit(path)
46 | self.now_router_path = path
47 | print('页面切换:',self.now_router_path)
48 | else:
49 | print(f"Route '{path}' not found")
50 |
51 | def turn_back(self):
52 | if len(self.history) > 0:
53 | path = self.history.pop()
54 | self.navigate(path, True)
55 | print(f'返回:{path}')
56 | self.history_changed.emit(len(self.history))
57 | return True
58 | else:
59 | print(f'无法返回')
60 | return False
61 |
--------------------------------------------------------------------------------
/app/ui/components/scroll_bar.py:
--------------------------------------------------------------------------------
1 | from PySide6.QtWidgets import QScrollBar
2 |
3 |
4 | class ScrollBar(QScrollBar):
5 | def __init__(self):
6 | super().__init__()
7 | self.setStyleSheet(
8 | '''
9 | QScrollBar:vertical {
10 | border-width: 0px;
11 | border: none;
12 | background:rgba(133, 135, 138, 0);
13 | width:4px;
14 | margin: 0px 0px 0px 0px;
15 | }
16 | QScrollBar::handle:vertical {
17 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
18 | stop: 0 rgb(133, 135, 138), stop: 0.5 rgb(133, 135, 138), stop:1 rgb(133, 135, 138));
19 | min-height: 20px;
20 | max-height: 20px;
21 | margin: 0 0px 0 0px;
22 | border-radius: 2px;
23 | }
24 | QScrollBar::add-line:vertical {
25 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
26 | stop: 0 rgba(133, 135, 138, 0), stop: 0.5 rgba(133, 135, 138, 0), stop:1 rgba(133, 135, 138, 0));
27 | height: 0px;
28 | border: none;
29 | subcontrol-position: bottom;
30 | subcontrol-origin: margin;
31 | }
32 | QScrollBar::sub-line:vertical {
33 | background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
34 | stop: 0 rgba(133, 135, 138, 0), stop: 0.5 rgba(133, 135, 138, 0), stop:1 rgba(133, 135, 138, 0));
35 | height: 0 px;
36 | border: none;
37 | subcontrol-position: top;
38 | subcontrol-origin: margin;
39 | }
40 | QScrollBar::sub-page:vertical {
41 | background: rgba(133, 135, 138, 0);
42 | }
43 |
44 | QScrollBar::add-page:vertical {
45 | background: rgba(133, 135, 138, 0);
46 | }
47 | '''
48 | )
--------------------------------------------------------------------------------
/app/ui/components/sidebar/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/7 10:51
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/components/sidebar/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/sidebar/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/sidebar/__pycache__/sidebar.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/sidebar/__pycache__/sidebar.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/components/sidebar/__pycache__/sidebar_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/components/sidebar/__pycache__/sidebar_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/19 22:41
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/doc_convert/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/__pycache__/doc_convert.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/__pycache__/doc_convert.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/__pycache__/doc_convert_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/__pycache__/doc_convert_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2image/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/26 0:43
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2image/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/pdf2image/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2image/__pycache__/pdf2image.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/pdf2image/__pycache__/pdf2image.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2image/__pycache__/pdf2image_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/pdf2image/__pycache__/pdf2image_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2wordui/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/19 22:54
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2wordui/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/pdf2wordui/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2wordui/__pycache__/pdf2word.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/pdf2wordui/__pycache__/pdf2word.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/pdf2wordui/__pycache__/pdf2word_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/pdf2wordui/__pycache__/pdf2word_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/web2pdf/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/30 16:45
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/doc_convert/web2pdf/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/web2pdf/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/web2pdf/__pycache__/web2pdf.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/web2pdf/__pycache__/web2pdf.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/doc_convert/web2pdf/__pycache__/web2pdf_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/doc_convert/web2pdf/__pycache__/web2pdf_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/global_signal.py:
--------------------------------------------------------------------------------
1 | from PySide6.QtCore import Signal, QThread, QObject
2 |
3 |
4 | class GlobalSignals(QObject):
5 | not_support = Signal(bool)
6 | information = Signal(str) # 警告弹窗信号
7 |
8 |
9 | globalSignals = GlobalSignals()
10 |
--------------------------------------------------------------------------------
/app/ui/image_tools/__pycache__/image_tool.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/image_tools/__pycache__/image_tool.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/image_tools/__pycache__/image_tool_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/image_tools/__pycache__/image_tool_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/image_tools/image_tool.py:
--------------------------------------------------------------------------------
1 | from PySide6.QtCore import Signal, QThread, QSize, QFile, QIODevice, QTextStream
2 | from PySide6.QtWidgets import QWidget
3 |
4 | from app.ui.Icon import Icon
5 | from app.ui.components.QCursorGif import QCursorGif
6 | from app.ui.global_signal import globalSignals
7 | from app.ui.image_tools.image_tool_ui import Ui_Form
8 | from app.ui.image_tools.modify_date.modify_date import ModifyDateControl
9 | from app.ui.pdf_tools.merge import MergeControl
10 |
11 | from app.ui.components.router import Router
12 |
13 |
14 | class ImageToolControl(QWidget, Ui_Form, QCursorGif):
15 | DecryptSignal = Signal(str)
16 | get_wxidSignal = Signal(str)
17 | versionErrorSignal = Signal(str)
18 | childRouterSignal = Signal(str)
19 |
20 | def __init__(self, router: Router, parent=None):
21 | super().__init__(parent)
22 | self.router = router
23 | self.router_path = (self.parent().router_path if self.parent() else '') + '/图片工具箱'
24 | self.child_routes = {}
25 | self.merge_view = None
26 | self.running_flag = False
27 | self.setupUi(self)
28 | # 设置忙碌光标图片数组
29 | self.initCursor([':/icons/icons/Cursors/%d.png' %
30 | i for i in range(8)], self)
31 | self.setCursorTimeout(100)
32 | self.init_ui()
33 |
34 | def init_ui(self):
35 | if not self.parent():
36 | pixmap = QPixmap(Icon.logo_ico_path)
37 | icon = QIcon(pixmap)
38 | self.setWindowIcon(icon)
39 | self.setWindowTitle('PDF工具箱')
40 | style_qss_file = QFile(":/data/resources/QSS/style.qss")
41 | if style_qss_file.open(QIODevice.ReadOnly | QIODevice.Text):
42 | stream = QTextStream(style_qss_file)
43 | style_content = stream.readAll()
44 | self.setStyleSheet(style_content)
45 | style_qss_file.close()
46 | self.commandLinkButton_modify_date.clicked.connect(self.modify_date)
47 |
48 | self.commandLinkButton_modify_name_by_time.clicked.connect(globalSignals.not_support)
49 |
50 |
51 | self.resize(QSize(640, 480))
52 |
53 | def modify_date(self):
54 | if not self.merge_view:
55 | self.merge_view = ModifyDateControl(router=self.router, parent=self if self.parent() else None)
56 | self.merge_view.okSignal.connect(self.merge_finish)
57 | self.router.add_route(self.merge_view.router_path, self.merge_view)
58 | self.child_routes[self.merge_view.router_path] = 0
59 | self.childRouterSignal.emit(self.merge_view.router_path)
60 | self.router.navigate(self.merge_view.router_path)
61 | else:
62 | self.router.navigate(self.merge_view.router_path)
63 |
64 | def merge_finish(self):
65 | self.merge_view = None
66 |
67 | def __del__(self):
68 | self.merge_view = None
69 |
70 |
71 | if __name__ == '__main__':
72 | from PySide6.QtWidgets import QWidget, QApplication
73 | import sys
74 | from PySide6.QtGui import QFont, QPixmap, QIcon
75 | from PySide6.QtCore import Qt
76 |
77 | QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
78 | QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
79 | app = QApplication(sys.argv)
80 | font = QFont('微软雅黑', 10) # 使用 Times New Roman 字体,字体大小为 14
81 | app.setFont(font)
82 | router = Router(None)
83 | view = ImageToolControl(router)
84 | view.show()
85 | sys.exit(app.exec_())
86 |
--------------------------------------------------------------------------------
/app/ui/image_tools/modify_date/__pycache__/modify_date.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/image_tools/modify_date/__pycache__/modify_date.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/image_tools/modify_date/__pycache__/modify_date_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/image_tools/modify_date/__pycache__/modify_date_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/mainview.py:
--------------------------------------------------------------------------------
1 | from PySide6 import QtWidgets, QtGui
2 |
3 | from app.ui import mainwindow
4 | from PySide6.QtCore import Signal, QFile, QIODevice, QTextStream, QSize, Qt
5 | from PySide6.QtGui import QPixmap, QIcon
6 | from PySide6.QtWidgets import QMainWindow, QListWidgetItem, QLabel, QPushButton, QSizePolicy, QSplitter, QMessageBox
7 |
8 | from app.ui.Icon import Icon
9 | from app.ui.components.QCursorGif import QCursorGif
10 | from app.ui.components.router import Router
11 | from app.ui.components import Sidebar, SidebarButton
12 | from app.ui.doc_convert.doc_convert import DocConvertControl
13 | from app.ui.global_signal import globalSignals
14 | from app.ui.image_tools.image_tool import ImageToolControl
15 | from app.ui.memotrace_enhance.enhance import EnhanceControl
16 | from app.ui.pdf_tools.pdf_tool import PDFToolControl
17 | from app.ui.setting.setting import SettingWindow
18 | from app.ui.video_tools.video_tool import VideoToolControl
19 |
20 |
21 | class MainWinController(QMainWindow, mainwindow.Ui_MainWindow, QCursorGif):
22 | exitSignal = Signal(bool)
23 | okSignal = Signal(bool)
24 | childRouterSignal = Signal(str)
25 |
26 | # username = ''
27 | def __init__(self, parent=None):
28 | super(MainWinController, self).__init__(parent)
29 | self.setupUi(self)
30 | self.router_path = ''
31 | self.init_ui()
32 | # 设置无边框
33 | # self.setWindowFlag(Qt.FramelessWindowHint)
34 | globalSignals.not_support.connect(self.show_not_support)
35 | globalSignals.information.connect(self.show_information)
36 |
37 | def init_ui(self):
38 | self.initCursor([':/icons/icons/Cursors/%d.png' %
39 | i for i in range(8)], self)
40 | self.setCursorTimeout(100)
41 | pixmap = QPixmap(Icon.logo_ico_path)
42 | icon = QIcon(pixmap)
43 | self.setWindowIcon(icon)
44 |
45 | style_qss_file = QFile(":/data/resources/QSS/style.qss")
46 | if style_qss_file.open(QIODevice.ReadOnly | QIODevice.Text):
47 | stream = QTextStream(style_qss_file)
48 | style_content = stream.readAll()
49 | self.setStyleSheet(style_content)
50 | style_qss_file.close()
51 |
52 | self.stackedWidget = QtWidgets.QStackedWidget(self)
53 | self.stackedWidget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) # C尽可能挤压B
54 |
55 | self.router = Router(self.stackedWidget)
56 | self.sidebar = Sidebar(self.stackedWidget, parent=None)
57 | self.sidebar.btn_setting.clicked.connect(self.show_setting)
58 | self.sidebar.btn_back.setText('')
59 | self.sidebar.btn_setting.setIcon(Icon.Setting_Icon)
60 | self.sidebar.btn_back.setIcon(Icon.Back)
61 | self.sidebar.btn_back.clicked.connect(self.router.turn_back)
62 | self.router.history_changed.connect(self.sidebar.set_turn_back_enable)
63 | self.horizontalLayout.addWidget(self.sidebar)
64 | self.horizontalLayout.addWidget(self.stackedWidget)
65 | self.horizontalLayout.setContentsMargins(0,0,0,0)
66 | self.setting_view = SettingWindow()
67 |
68 | pdf_view = PDFToolControl(self.router, parent=self)
69 | self.add_widget(Icon.PDF_Icon, 'PDF工具', pdf_view.router_path, pdf_view)
70 |
71 | # l1 = QLabel('文档转换', self)
72 | doc_view = DocConvertControl(self.router, parent=self)
73 | self.add_widget(Icon.Doc_Transfer_Icon, '文档转换', '/文档转换', doc_view)
74 |
75 | image_view = ImageToolControl(self.router, parent=self)
76 | self.add_widget(Icon.Img_Icon, '图片工具', '/图片工具', image_view)
77 |
78 | # Screen_record_view = ScreenRecordControl(self.router, parent=self)
79 | Video_view = VideoToolControl(self.router, parent=self)
80 | self.add_widget(Icon.Video_Icon, '视频工具', '/视频工具', Video_view)
81 |
82 | l4 = QLabel('批量操作', self)
83 | self.add_widget(Icon.Batch_Icon, '批量操作', '/批量操作', l4)
84 |
85 | enhance_view = EnhanceControl(self.router, parent=self)
86 | self.add_widget(Icon.Tool_Icon, '留痕增强', '/留痕增强', enhance_view)
87 |
88 | # 连接信号槽:切换选中按钮样式
89 | self.router.route_changed.connect(self.sidebar.update_sidebar_selection)
90 | self.router.navigate(pdf_view.router_path) # 初始页面
91 |
92 | def add_widget(self, icon, text, router_path, widget):
93 | # """ 创建侧边栏按钮并连接路径导航 """
94 |
95 | self.sidebar.add_nav_button(icon, text, router_path, action=lambda: self.router.navigate(router_path))
96 | index = self.router.add_route(router_path, widget)
97 |
98 | def show_setting(self):
99 | self.setting_view.show()
100 |
101 | def show_not_support(self, a):
102 | self.show_information('暂不支持该功能!')
103 |
104 | def show_information(self, msg):
105 | QMessageBox.information(self, '温馨提示', msg)
106 |
--------------------------------------------------------------------------------
/app/ui/mainwindow.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################################################################################
4 | ## Form generated from reading UI file 'mainwindow.ui'
5 | ##
6 | ## Created by: Qt User Interface Compiler version 6.8.0
7 | ##
8 | ## WARNING! All changes made in this file will be lost when recompiling UI file!
9 | ################################################################################
10 |
11 | from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
12 | QMetaObject, QObject, QPoint, QRect,
13 | QSize, QTime, QUrl, Qt)
14 | from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
15 | QFont, QFontDatabase, QGradient, QIcon,
16 | QImage, QKeySequence, QLinearGradient, QPainter,
17 | QPalette, QPixmap, QRadialGradient, QTransform)
18 | from PySide6.QtWidgets import (QApplication, QHBoxLayout, QMainWindow, QSizePolicy,
19 | QWidget)
20 | import resource_rc
21 |
22 | class Ui_MainWindow(object):
23 | def setupUi(self, MainWindow):
24 | if not MainWindow.objectName():
25 | MainWindow.setObjectName(u"MainWindow")
26 | MainWindow.resize(717, 565)
27 | font = QFont()
28 | font.setFamilies([u"\u5fae\u8f6f\u96c5\u9ed1"])
29 | font.setPointSize(12)
30 | font.setBold(False)
31 | MainWindow.setFont(font)
32 | MainWindow.setMouseTracking(True)
33 | icon = QIcon()
34 | icon.addFile(u":/icons/resources/icons/logo.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
35 | MainWindow.setWindowIcon(icon)
36 | MainWindow.setAutoFillBackground(True)
37 | MainWindow.setStyleSheet(u"")
38 | MainWindow.setIconSize(QSize(50, 24))
39 | MainWindow.setDockOptions(QMainWindow.DockOption.AllowTabbedDocks|QMainWindow.DockOption.AnimatedDocks)
40 | self.centralwidget = QWidget(MainWindow)
41 | self.centralwidget.setObjectName(u"centralwidget")
42 | self.centralwidget.setMouseTracking(True)
43 | self.horizontalLayout = QHBoxLayout(self.centralwidget)
44 | self.horizontalLayout.setSpacing(0)
45 | self.horizontalLayout.setObjectName(u"horizontalLayout")
46 | self.horizontalLayout.setContentsMargins(9, 0, 9, 0)
47 | MainWindow.setCentralWidget(self.centralwidget)
48 |
49 | self.retranslateUi(MainWindow)
50 |
51 | QMetaObject.connectSlotsByName(MainWindow)
52 | # setupUi
53 |
54 | def retranslateUi(self, MainWindow):
55 | MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"EasyBox", None))
56 | #if QT_CONFIG(accessibility)
57 | MainWindow.setAccessibleName(QCoreApplication.translate("MainWindow", u"1423534", None))
58 | #endif // QT_CONFIG(accessibility)
59 | #if QT_CONFIG(accessibility)
60 | MainWindow.setAccessibleDescription(QCoreApplication.translate("MainWindow", u"142345", None))
61 | #endif // QT_CONFIG(accessibility)
62 | # retranslateUi
63 |
64 |
--------------------------------------------------------------------------------
/app/ui/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 717
10 | 565
11 |
12 |
13 |
14 |
15 | 微软雅黑
16 | 12
17 | false
18 |
19 |
20 |
21 | true
22 |
23 |
24 | EasyBox
25 |
26 |
27 |
28 | :/icons/resources/icons/logo.png:/icons/resources/icons/logo.png
29 |
30 |
31 | 1423534
32 |
33 |
34 | 142345
35 |
36 |
37 | true
38 |
39 |
40 |
41 |
42 |
43 |
44 | 50
45 | 24
46 |
47 |
48 |
49 | QMainWindow::DockOption::AllowTabbedDocks|QMainWindow::DockOption::AnimatedDocks
50 |
51 |
52 |
53 | true
54 |
55 |
56 |
57 | 0
58 |
59 |
60 | 9
61 |
62 |
63 | 0
64 |
65 |
66 | 9
67 |
68 |
69 | 0
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/20 21:01
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/memotrace_enhance/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/__pycache__/enhance.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/memotrace_enhance/__pycache__/enhance.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/__pycache__/enhance_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/memotrace_enhance/__pycache__/enhance_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/enhance.py:
--------------------------------------------------------------------------------
1 | from PySide6.QtCore import Signal, QThread, QSize, QFile, QIODevice, QTextStream
2 | from PySide6.QtWidgets import QWidget
3 |
4 | from app.ui.Icon import Icon
5 | from app.ui.components.QCursorGif import QCursorGif
6 | from app.ui.doc_convert.pdf2wordui.pdf2word import Pdf2WordControl
7 | from app.ui.memotrace_enhance.enhance_ui import Ui_Form
8 | from app.ui.components.router import Router
9 | from app.ui.memotrace_enhance.toc.toc import TocControl
10 |
11 |
12 | class EnhanceControl(QWidget, Ui_Form, QCursorGif):
13 | DecryptSignal = Signal(str)
14 | get_wxidSignal = Signal(str)
15 | versionErrorSignal = Signal(str)
16 | childRouterSignal = Signal(str)
17 |
18 | def __init__(self, router: Router, parent=None):
19 | super().__init__(parent)
20 | self.router = router
21 | self.router_path = (self.parent().router_path if self.parent() else '') + '/留痕增强'
22 | self.child_routes = {}
23 | self.merge_view = None
24 | self.make_toc_view = None
25 | self.running_flag = False
26 | self.setupUi(self)
27 | # 设置忙碌光标图片数组
28 | self.initCursor([':/icons/icons/Cursors/%d.png' %
29 | i for i in range(8)], self)
30 | self.setCursorTimeout(100)
31 | self.init_ui()
32 |
33 | def init_ui(self):
34 | if not self.parent():
35 | pixmap = QPixmap(Icon.logo_ico_path)
36 | icon = QIcon(pixmap)
37 | self.setWindowIcon(icon)
38 | self.setWindowTitle('留痕增强')
39 | style_qss_file = QFile(":/data/resources/QSS/style.qss")
40 | if style_qss_file.open(QIODevice.ReadOnly | QIODevice.Text):
41 | stream = QTextStream(style_qss_file)
42 | style_content = stream.readAll()
43 | self.setStyleSheet(style_content)
44 | style_qss_file.close()
45 | self.commandLinkButton_pdf2word.clicked.connect(self.pdf2word)
46 | self.commandLinkButton_toc.clicked.connect(self.make_toc)
47 | self.resize(QSize(640, 480))
48 |
49 | def pdf2word(self):
50 | if not self.merge_view:
51 | self.merge_view = Pdf2WordControl(router=self.router, parent=self if self.parent() else None)
52 | self.merge_view.okSignal.connect(self.merge_finish)
53 | self.router.add_route(self.merge_view.router_path, self.merge_view)
54 | self.child_routes[self.merge_view.router_path] = 0
55 | self.childRouterSignal.emit(self.merge_view.router_path)
56 | self.router.navigate(self.merge_view.router_path)
57 | else:
58 | self.router.navigate(self.merge_view.router_path)
59 |
60 | def make_toc(self):
61 | if not self.make_toc_view:
62 | self.make_toc_view = TocControl(router=self.router, parent=self if self.parent() else None)
63 | self.make_toc_view.okSignal.connect(self.make_toc_finish)
64 | self.router.add_route(self.make_toc_view.router_path, self.make_toc_view)
65 | self.child_routes[self.make_toc_view.router_path] = 0
66 | self.childRouterSignal.emit(self.make_toc_view.router_path)
67 | self.router.navigate(self.make_toc_view.router_path)
68 | else:
69 | self.router.navigate(self.make_toc_view.router_path)
70 |
71 | def make_toc_finish(self):
72 | self.make_toc_view = None
73 |
74 | def merge_finish(self):
75 | self.merge_view = None
76 |
77 | def __del__(self):
78 | self.merge_view = None
79 |
80 |
81 | if __name__ == '__main__':
82 | from PySide6.QtWidgets import QWidget, QApplication
83 | import sys
84 | from PySide6.QtGui import QFont, QPixmap, QIcon
85 | from PySide6.QtCore import Qt
86 |
87 | QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
88 | QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
89 | app = QApplication(sys.argv)
90 | font = QFont('微软雅黑', 10) # 使用 Times New Roman 字体,字体大小为 14
91 | app.setFont(font)
92 | router = Router(None)
93 | view = EnhanceControl(router)
94 | view.show()
95 | sys.exit(app.exec_())
96 |
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/toc/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/19 22:54
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/toc/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/memotrace_enhance/toc/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/toc/__pycache__/toc.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/memotrace_enhance/toc/__pycache__/toc.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/memotrace_enhance/toc/__pycache__/toc_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/memotrace_enhance/toc/__pycache__/toc_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/__init__.py
--------------------------------------------------------------------------------
/app/ui/pdf_tools/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/__pycache__/pdf_tool.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/__pycache__/pdf_tool.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/__pycache__/pdf_tool_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/__pycache__/pdf_tool_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/conversion/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/10 15:39
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/app/ui/pdf_tools/merge/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/10 15:39
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 | from .merge import MergeControl
12 |
13 |
14 | if __name__ == '__main__':
15 | pass
16 |
--------------------------------------------------------------------------------
/app/ui/pdf_tools/merge/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/merge/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/merge/__pycache__/encrypt_dialog.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/merge/__pycache__/encrypt_dialog.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/merge/__pycache__/encrypt_dialog_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/merge/__pycache__/encrypt_dialog_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/merge/__pycache__/merge.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/merge/__pycache__/merge.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/merge/__pycache__/merge_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/merge/__pycache__/merge_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/merge/encrypt_dialog.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/10 21:13
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-encrypt_dialog.py
9 | @Description :
10 | """
11 | from PySide6.QtCore import Signal
12 | from PySide6.QtWidgets import QWidget, QDialog, QMessageBox
13 | from pymupdf import mupdf
14 |
15 | from app.ui.pdf_tools.merge.encrypt_dialog_ui import Ui_Dialog
16 |
17 |
18 | class EncryptControl(QDialog, Ui_Dialog):
19 | okSignal = Signal(bool)
20 | childRouterSignal = Signal(str)
21 |
22 | def __init__(self, parent=None):
23 | super().__init__(parent)
24 | self.setupUi(self)
25 | self.setWindowTitle('填写加密选项')
26 | self.buttonBox.setObjectName('border')
27 |
28 | def accept(self):
29 | owner_pw1 = self.lineEdit_owner_pw1.text()
30 | owner_pw2 = self.lineEdit_owner_pw2.text()
31 | if not owner_pw1 or not owner_pw2:
32 | QMessageBox.warning(self, '警告', '请输入编辑密码')
33 | return
34 | if owner_pw1 != owner_pw2:
35 | QMessageBox.warning(self, '警告', '两次管理员密码输入不一致')
36 | return
37 | user_pw1 = self.lineEdit_user_pw1.text()
38 | user_pw2 = self.lineEdit_user_pw2.text()
39 | if user_pw1 != user_pw2:
40 | QMessageBox.warning(self, '警告', '两次用户密码输入不一致')
41 | return
42 | super().accept()
43 |
44 | def get_data(self):
45 | print('123')
46 | owner_pw1 = self.lineEdit_owner_pw1.text()
47 | owner_pw2 = self.lineEdit_owner_pw2.text()
48 | user_pw1 = self.lineEdit_user_pw1.text()
49 | user_pw2 = self.lineEdit_user_pw2.text()
50 | permissions = 0
51 | if self.checkBox_edit.isChecked():
52 | permissions |= mupdf.PDF_PERM_MODIFY
53 | if self.checkBox_copy.isChecked():
54 | permissions |= mupdf.PDF_PERM_COPY
55 | if self.checkBox_annotate.isChecked():
56 | permissions |= mupdf.PDF_PERM_ANNOTATE
57 | if self.radioButton_print.isChecked():
58 | permissions |= mupdf.PDF_PERM_PRINT | mupdf.PDF_PERM_PRINT_HQ
59 | elif self.radioButton_print_low.isChecked():
60 | permissions |= mupdf.PDF_PERM_PRINT
61 | else:
62 | if permissions == 0:
63 | permissions = 0
64 | return {
65 | "encryption": mupdf.PDF_ENCRYPT_AES_256,
66 | 'owner_pw': owner_pw1,
67 | 'user_pw': user_pw1,
68 | "permissions": permissions
69 | }
70 |
71 |
72 | if __name__ == '__main__':
73 | pass
74 |
--------------------------------------------------------------------------------
/app/ui/pdf_tools/security/__init__.py:
--------------------------------------------------------------------------------
1 | # PDF加密解密功能模块
2 | """
3 | 包含PDF加密和解密相关功能
4 | """
--------------------------------------------------------------------------------
/app/ui/pdf_tools/security/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/security/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/security/__pycache__/decrypt.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/security/__pycache__/decrypt.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/security/__pycache__/decrypt_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/security/__pycache__/decrypt_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/security/__pycache__/encrypt.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/security/__pycache__/encrypt.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/security/__pycache__/encrypt_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/security/__pycache__/encrypt_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/split/__init__.py:
--------------------------------------------------------------------------------
1 | # PDF拆分功能模块
2 | """
3 | PDF拆分相关功能
4 | """
--------------------------------------------------------------------------------
/app/ui/pdf_tools/split/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/split/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/split/__pycache__/split.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/split/__pycache__/split.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/pdf_tools/split/__pycache__/split_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/pdf_tools/split/__pycache__/split_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/screen_record/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/ui/screen_record/screen_record_ui.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################################################################################
4 | ## Form generated from reading UI file 'screen_record_ui.ui'
5 | ##
6 | ## Created by: Qt User Interface Compiler version 6.8.0
7 | ##
8 | ## WARNING! All changes made in this file will be lost when recompiling UI file!
9 | ################################################################################
10 |
11 | from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
12 | QMetaObject, QObject, QPoint, QRect,
13 | QSize, QTime, QUrl, Qt)
14 | from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
15 | QFont, QFontDatabase, QGradient, QIcon,
16 | QImage, QKeySequence, QLinearGradient, QPainter,
17 | QPalette, QPixmap, QRadialGradient, QTransform)
18 | from PySide6.QtWidgets import (QApplication, QComboBox, QGridLayout, QLabel,
19 | QLineEdit, QPushButton, QSizePolicy, QSpinBox,
20 | QWidget)
21 |
22 | class Ui_Form(object):
23 | def setupUi(self, Form):
24 | if not Form.objectName():
25 | Form.setObjectName(u"Form")
26 | Form.resize(448, 300)
27 | self.widget = QWidget(Form)
28 | self.widget.setObjectName(u"widget")
29 | self.widget.setGeometry(QRect(30, 40, 355, 124))
30 | self.gridLayout = QGridLayout(self.widget)
31 | self.gridLayout.setObjectName(u"gridLayout")
32 | self.gridLayout.setContentsMargins(0, 0, 0, 0)
33 | self.format_label = QLabel(self.widget)
34 | self.format_label.setObjectName(u"format_label")
35 |
36 | self.gridLayout.addWidget(self.format_label, 0, 0, 1, 1)
37 |
38 | self.format_combo = QComboBox(self.widget)
39 | self.format_combo.addItem("")
40 | self.format_combo.addItem("")
41 | self.format_combo.setObjectName(u"format_combo")
42 |
43 | self.gridLayout.addWidget(self.format_combo, 0, 1, 1, 3)
44 |
45 | self.fps_label = QLabel(self.widget)
46 | self.fps_label.setObjectName(u"fps_label")
47 |
48 | self.gridLayout.addWidget(self.fps_label, 1, 0, 1, 1)
49 |
50 | self.fps_spin = QSpinBox(self.widget)
51 | self.fps_spin.setObjectName(u"fps_spin")
52 |
53 | self.gridLayout.addWidget(self.fps_spin, 1, 1, 1, 3)
54 |
55 | self.path_label = QLabel(self.widget)
56 | self.path_label.setObjectName(u"path_label")
57 |
58 | self.gridLayout.addWidget(self.path_label, 2, 0, 1, 1)
59 |
60 | self.path_edit = QLineEdit(self.widget)
61 | self.path_edit.setObjectName(u"path_edit")
62 |
63 | self.gridLayout.addWidget(self.path_edit, 2, 1, 1, 2)
64 |
65 | self.browse_button = QPushButton(self.widget)
66 | self.browse_button.setObjectName(u"browse_button")
67 |
68 | self.gridLayout.addWidget(self.browse_button, 2, 3, 1, 1)
69 |
70 | self.start_button = QPushButton(self.widget)
71 | self.start_button.setObjectName(u"start_button")
72 |
73 | self.gridLayout.addWidget(self.start_button, 3, 0, 1, 2)
74 |
75 | self.stop_button = QPushButton(self.widget)
76 | self.stop_button.setObjectName(u"stop_button")
77 |
78 | self.gridLayout.addWidget(self.stop_button, 3, 2, 1, 2)
79 |
80 |
81 | self.retranslateUi(Form)
82 |
83 | QMetaObject.connectSlotsByName(Form)
84 | # setupUi
85 |
86 | def retranslateUi(self, Form):
87 | Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
88 | self.format_label.setText(QCoreApplication.translate("Form", u"\u5f55\u5236\u683c\u5f0f\uff1a", None))
89 | self.format_combo.setItemText(0, QCoreApplication.translate("Form", u"mp4", None))
90 | self.format_combo.setItemText(1, QCoreApplication.translate("Form", u"avi", None))
91 |
92 | self.fps_label.setText(QCoreApplication.translate("Form", u"\u5e27\u7387\uff1a", None))
93 | self.path_label.setText(QCoreApplication.translate("Form", u"\u4fdd\u5b58\u8def\u5f84\uff1a", None))
94 | self.browse_button.setText(QCoreApplication.translate("Form", u"\u9009\u62e9\u8def\u5f84", None))
95 | self.start_button.setText(QCoreApplication.translate("Form", u"\u5f00\u59cb\u5f55\u5236", None))
96 | self.stop_button.setText(QCoreApplication.translate("Form", u"\u7ed3\u675f\u5f55\u5236", None))
97 | # retranslateUi
98 |
99 |
--------------------------------------------------------------------------------
/app/ui/screen_record/screen_record_ui.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 448
10 | 300
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 30
20 | 40
21 | 355
22 | 124
23 |
24 |
25 |
26 | -
27 |
28 |
29 | 录制格式:
30 |
31 |
32 |
33 | -
34 |
35 |
-
36 |
37 | mp4
38 |
39 |
40 | -
41 |
42 | avi
43 |
44 |
45 |
46 |
47 | -
48 |
49 |
50 | 帧率:
51 |
52 |
53 |
54 | -
55 |
56 |
57 | -
58 |
59 |
60 | 保存路径:
61 |
62 |
63 |
64 | -
65 |
66 |
67 | -
68 |
69 |
70 | 选择路径
71 |
72 |
73 |
74 | -
75 |
76 |
77 | 开始录制
78 |
79 |
80 |
81 | -
82 |
83 |
84 | 结束录制
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/app/ui/setting/__pycache__/about_dialog.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/setting/__pycache__/about_dialog.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/setting/__pycache__/seetingUi.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/setting/__pycache__/seetingUi.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/setting/__pycache__/setting.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/setting/__pycache__/setting.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/setting/seetingUi.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################################################################################
4 | ## Form generated from reading UI file 'seetingUi.ui'
5 | ##
6 | ## Created by: Qt User Interface Compiler version 6.8.0
7 | ##
8 | ## WARNING! All changes made in this file will be lost when recompiling UI file!
9 | ################################################################################
10 |
11 | from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
12 | QMetaObject, QObject, QPoint, QRect,
13 | QSize, QTime, QUrl, Qt)
14 | from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
15 | QFont, QFontDatabase, QGradient, QIcon,
16 | QImage, QKeySequence, QLinearGradient, QPainter,
17 | QPalette, QPixmap, QRadialGradient, QTransform)
18 | from PySide6.QtWidgets import (QApplication, QFrame, QHBoxLayout, QListWidget,
19 | QListWidgetItem, QSizePolicy, QStackedWidget, QWidget)
20 |
21 | class Ui_Form(object):
22 | def setupUi(self, Form):
23 | if not Form.objectName():
24 | Form.setObjectName(u"Form")
25 | Form.resize(640, 480)
26 | self.horizontalLayout = QHBoxLayout(Form)
27 | self.horizontalLayout.setObjectName(u"horizontalLayout")
28 | self.listWidget = QListWidget(Form)
29 | self.listWidget.setObjectName(u"listWidget")
30 | self.listWidget.setMinimumSize(QSize(120, 0))
31 | self.listWidget.setMaximumSize(QSize(120, 16777215))
32 | self.listWidget.setFrameShape(QFrame.NoFrame)
33 |
34 | self.horizontalLayout.addWidget(self.listWidget)
35 |
36 | self.line = QFrame(Form)
37 | self.line.setObjectName(u"line")
38 | self.line.setStyleSheet(u"")
39 | self.line.setFrameShadow(QFrame.Raised)
40 | self.line.setLineWidth(5)
41 | self.line.setFrameShape(QFrame.Shape.VLine)
42 |
43 | self.horizontalLayout.addWidget(self.line)
44 |
45 | self.stackedWidget = QStackedWidget(Form)
46 | self.stackedWidget.setObjectName(u"stackedWidget")
47 |
48 | self.horizontalLayout.addWidget(self.stackedWidget)
49 |
50 |
51 | self.retranslateUi(Form)
52 |
53 | QMetaObject.connectSlotsByName(Form)
54 | # setupUi
55 |
56 | def retranslateUi(self, Form):
57 | Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
58 | # retranslateUi
59 |
60 |
--------------------------------------------------------------------------------
/app/ui/setting/seetingUi.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 640
10 | 480
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 |
21 | 120
22 | 0
23 |
24 |
25 |
26 |
27 | 120
28 | 16777215
29 |
30 |
31 |
32 | QFrame::NoFrame
33 |
34 |
35 |
36 | -
37 |
38 |
39 |
40 |
41 |
42 | QFrame::Raised
43 |
44 |
45 | 5
46 |
47 |
48 | Qt::Vertical
49 |
50 |
51 |
52 | -
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/ui/setting/setting.py:
--------------------------------------------------------------------------------
1 | import os.path
2 | import sys
3 |
4 | from PySide6.QtCore import Qt, Signal, QThread, QUrl, QFile, QIODevice, QTextStream, QStringConverter
5 | from PySide6.QtGui import QFont, QDesktopServices, QPixmap, QIcon
6 | from PySide6.QtWidgets import QWidget, QMessageBox, QApplication, QListWidgetItem, QLabel
7 |
8 | from app.ui.Icon import Icon
9 | from app.ui.global_signal import globalSignals
10 | from app.ui.setting.about_dialog import AboutDialog
11 | from app.ui.setting.seetingUi import Ui_Form
12 |
13 | Stylesheet = """
14 | """
15 |
16 |
17 | class SettingWindow(QWidget, Ui_Form):
18 | load_finish_signal = Signal(bool)
19 |
20 | def __init__(self, parent=None):
21 | super().__init__(parent)
22 | self.setupUi(self)
23 | self.init_ui()
24 | # self.setStyleSheet(Stylesheet)
25 |
26 | def init_ui(self):
27 | pixmap = QPixmap(Icon.logo_ico_path)
28 | icon = QIcon(pixmap)
29 | self.setWindowIcon(icon)
30 | self.setWindowTitle('设置')
31 | self.listWidget.currentRowChanged.connect(self.setCurrentIndex)
32 | account_item = QListWidgetItem('PDF设置', self.listWidget)
33 | tool_item = QListWidgetItem('图片设置', self.listWidget)
34 | chat_item = QListWidgetItem('文件管理', self.listWidget)
35 | myinfo_item = QListWidgetItem('关于', self.listWidget)
36 | self.account_setting_window = QLabel('敬请期待', self)
37 | self.report_setting_window = QLabel('敬请期待', self)
38 | self.file_setting_window = QLabel('敬请期待', self)
39 | self.about_window = AboutDialog(main_window=self, parent=self)
40 | self.about_window.buttonBox.setVisible(False)
41 | self.listWidget.setCurrentRow(0)
42 | self.stackedWidget.addWidget(self.account_setting_window)
43 | self.stackedWidget.addWidget(self.report_setting_window)
44 | self.stackedWidget.addWidget(self.file_setting_window)
45 | self.stackedWidget.addWidget(self.about_window)
46 | style_qss_file = QFile(":/data/resources/QSS/style.qss")
47 | if style_qss_file.open(QIODevice.ReadOnly | QIODevice.Text):
48 | stream = QTextStream(style_qss_file)
49 | stream.setEncoding(QStringConverter.Encoding.System)
50 | style_content = stream.readAll()
51 | self.setStyleSheet(style_content)
52 | style_qss_file.close()
53 |
54 | def setCurrentIndex(self, row):
55 | self.stackedWidget.setCurrentIndex(row)
56 |
57 | def logout(self, flag):
58 | if flag:
59 | globalSignals.logout.emit(True)
60 | self.close()
61 |
62 | def reload(self):
63 | self.account_setting_window.init_ui()
64 |
65 |
66 | if __name__ == '__main__':
67 | app = QApplication(sys.argv)
68 | font = QFont('微软雅黑', 12) # 使用 Times New Roman 字体,字体大小为 14
69 | app.setFont(font)
70 | view = SettingWindow()
71 | view.show()
72 | sys.exit(app.exec())
73 |
--------------------------------------------------------------------------------
/app/ui/video_tools/__pycache__/video_tool.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/video_tools/__pycache__/video_tool.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/video_tools/__pycache__/video_tool_ui.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/ui/video_tools/__pycache__/video_tool_ui.cpython-313.pyc
--------------------------------------------------------------------------------
/app/ui/video_tools/video_tool.py:
--------------------------------------------------------------------------------
1 | from PySide6.QtCore import Signal, QThread, QSize, QFile, QIODevice, QTextStream
2 | from PySide6.QtWidgets import QWidget
3 |
4 | from app.ui.Icon import Icon
5 | from app.ui.components.QCursorGif import QCursorGif
6 | from app.ui.global_signal import globalSignals
7 | from app.ui.video_tools.video_tool_ui import Ui_Form
8 | from app.ui.components.router import Router
9 |
10 |
11 | class VideoToolControl(QWidget, Ui_Form, QCursorGif):
12 | DecryptSignal = Signal(str)
13 | get_wxidSignal = Signal(str)
14 | versionErrorSignal = Signal(str)
15 | childRouterSignal = Signal(str)
16 |
17 | def __init__(self, router: Router, parent=None):
18 | super(VideoToolControl, self).__init__(parent)
19 | self.pdf2image_view = None
20 | self.router = router
21 | self.router_path = (self.parent().router_path if self.parent() else '') + '/视频工具'
22 | self.child_routes = {}
23 | self.merge_view = None
24 | self.running_flag = False
25 | self.setupUi(self)
26 | # 设置忙碌光标图片数组
27 | self.initCursor([':/icons/icons/Cursors/%d.png' %
28 | i for i in range(8)], self)
29 | self.setCursorTimeout(100)
30 | self.init_ui()
31 |
32 | def init_ui(self):
33 | if not self.parent():
34 | pixmap = QPixmap(Icon.logo_ico_path)
35 | icon = QIcon(pixmap)
36 | self.setWindowIcon(icon)
37 | self.setWindowTitle('视频工具')
38 | style_qss_file = QFile(":/data/resources/QSS/style.qss")
39 | if style_qss_file.open(QIODevice.ReadOnly | QIODevice.Text):
40 | stream = QTextStream(style_qss_file)
41 | style_content = stream.readAll()
42 | self.setStyleSheet(style_content)
43 | style_qss_file.close()
44 |
45 | self.commandLinkButton_screenshoot.clicked.connect(globalSignals.not_support)
46 | self.commandLinkButton_convert.clicked.connect(globalSignals.not_support)
47 |
48 | self.resize(QSize(640, 480))
49 |
50 | def __del__(self):
51 | self.merge_view = None
52 |
53 |
54 | if __name__ == '__main__':
55 | from PySide6.QtWidgets import QWidget, QApplication
56 | import sys
57 | from PySide6.QtGui import QFont, QPixmap, QIcon
58 | from PySide6.QtCore import Qt
59 |
60 | QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
61 | QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
62 | app = QApplication(sys.argv)
63 | font = QFont('微软雅黑', 10) # 使用 Times New Roman 字体,字体大小为 14
64 | app.setFont(font)
65 | router = Router(None)
66 | view = VideoToolControl(router)
67 | view.show()
68 | sys.exit(app.exec_())
69 |
--------------------------------------------------------------------------------
/app/util/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/10 15:05
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 | from . import common
12 |
13 | if __name__ == '__main__':
14 | pass
15 |
--------------------------------------------------------------------------------
/app/util/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/util/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/app/util/__pycache__/common.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/app/util/__pycache__/common.cpython-313.pyc
--------------------------------------------------------------------------------
/doc/images/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/doc/images/img.png
--------------------------------------------------------------------------------
/doc/images/img_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/doc/images/img_1.png
--------------------------------------------------------------------------------
/doc/images/img_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/doc/images/img_2.png
--------------------------------------------------------------------------------
/doc/images/img_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/doc/images/img_3.png
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import ctypes
2 | import sys
3 | import traceback
4 | from app.config import version
5 | from app.log.exception_handling import ExceptionHanding
6 | from app.ui.Icon import Icon
7 | from multiprocessing import freeze_support
8 |
9 | widget = None
10 |
11 |
12 | def excepthook(exc_type, exc_value, traceback_):
13 | # 将异常信息转为字符串
14 | # 在这里处理全局异常
15 | error_message = ExceptionHanding(exc_type, exc_value, traceback_)
16 | txt = ''
17 | msg = f"Exception Type: {exc_type.__name__}\nException Value: {exc_value}\ndetails: {error_message}\n\n{txt}"
18 |
19 | logger.error(f'程序发生了错误:\n\n{msg}')
20 | # 创建一个 QMessageBox 对象
21 | error_box = QMessageBox()
22 | # 设置对话框的标题
23 | error_box.setWindowTitle("未知错误")
24 | pixmap = QPixmap(Icon.logo_ico_path)
25 | icon = QIcon(pixmap)
26 | error_box.setWindowIcon(icon)
27 | # 设置对话框的文本消息
28 | error_box.setText(msg)
29 | # 设置对话框的图标,使用 QMessageBox.Critical 作为图标类型
30 | error_box.setIcon(QMessageBox.Critical)
31 | # 添加一个“确定”按钮
32 | error_box.addButton(QMessageBox.Ok)
33 | # 显示对话框
34 | error_box.exec()
35 | # 调用原始的 excepthook,以便程序正常退出
36 | sys.__excepthook__(exc_type, exc_value, traceback_)
37 |
38 |
39 | # 设置 excepthook
40 | sys.excepthook = excepthook
41 | from PySide6.QtGui import QFont, QPixmap, QIcon
42 | from PySide6.QtWidgets import *
43 | from PySide6.QtCore import Qt
44 |
45 | from app.log import logger
46 | from app.ui import mainview
47 |
48 | import platform
49 |
50 | if platform.system() == "Windows":
51 | ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("EasyBox")
52 | QApplication.setHighDpiScaleFactorRoundingPolicy(
53 | Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
54 |
55 |
56 | class ViewController(QWidget):
57 | def __init__(self):
58 | super().__init__()
59 | pixmap = QPixmap(Icon.logo_ico_path)
60 | icon = QIcon(pixmap)
61 | self.setWindowIcon(icon)
62 | self.viewLogin = None
63 | self.viewMainWindow = None
64 | self.viewDecrypt = None
65 |
66 | def loadPCDecryptView(self):
67 | """
68 | 登录界面
69 | :return:
70 | """
71 |
72 | def loadLoginView(self):
73 | """
74 | 登录界面
75 | :return:
76 | """
77 |
78 | def login(self, username):
79 | self.loadMainWinView(username)
80 |
81 | def loadMainWinView(self, username=''):
82 | """
83 | 聊天界面
84 | :param username: 账号
85 | :return:
86 | """
87 | self.viewMainWindow = mainview.MainWinController()
88 | self.viewMainWindow.setWindowTitle(f"EasyBox-{version}")
89 | self.viewMainWindow.exitSignal.connect(self.close)
90 | try:
91 | self.viewMainWindow.show()
92 | except Exception as e:
93 | print(f"Exception: {e}")
94 | logger.error(traceback.format_exc())
95 |
96 | def close(self) -> bool:
97 | super().close()
98 |
99 |
100 | if __name__ == '__main__':
101 | freeze_support()
102 | app = QApplication(sys.argv)
103 | font = QFont('微软雅黑', 12) # 使用 Times New Roman 字体,字体大小为 14
104 | app.setFont(font)
105 | view = ViewController()
106 | widget = view.viewMainWindow
107 | try:
108 | # view.loadPCDecryptView()
109 | # view.loadLoginView()
110 | view.loadMainWinView()
111 | # view.show()
112 | # view.show_success()
113 | sys.exit(app.exec())
114 | except Exception as e:
115 | print(f"Exception: {e}")
116 | logger.error(traceback.format_exc())
117 |
--------------------------------------------------------------------------------
/main1.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 |
3 |
4 | a = Analysis(
5 | ['main.py'],
6 | pathex=[],
7 | binaries=[],
8 | datas=[
9 | (".\\.venv\\Lib\\site-packages\\docxcompose\\templates",'docxcompose/templates/'),
10 | ],
11 | hiddenimports=['cv2'],
12 | hookspath=[],
13 | hooksconfig={},
14 | runtime_hooks=[],
15 | excludes=['PySide6.QtQuick', 'PySide6.QtQml', 'PySide6.QtOpenGL'],
16 | noarchive=False,
17 | )
18 | pyz = PYZ(a.pure)
19 |
20 | exe1 = EXE(
21 | pyz,
22 | a.scripts,
23 | [],
24 | exclude_binaries=True,
25 | uac_admin=False,
26 | name='EasyBox',
27 | debug=False,
28 | bootloader_ignore_signals=False,
29 | strip=False,
30 | upx=True,
31 | upx_exclude=[],
32 | runtime_tmpdir=None,
33 | console=False,
34 | disable_windowed_traceback=True,
35 | argv_emulation=False,
36 | target_arch=None,
37 | codesign_identity=None,
38 | entitlements_file=None,
39 | icon=['./resources/images/logo.png'],
40 | version='version.txt',
41 | )
42 |
43 | coll2 = COLLECT(
44 | exe1,
45 | a.binaries,
46 | a.datas,
47 | strip=False,
48 | upx=True,
49 | upx_exclude=[],
50 | name='EasyBox',
51 | )
52 |
53 | import os
54 | import shutil
55 |
56 | # 删除 dist 目录中的 opengl32sw.dll
57 | dist_dir = './dist/EasyBox/_internal' # 替换成你的应用程序路径
58 | del_path = [
59 | ['PySide6', 'opengl32sw.dll'],
60 | ['cv2', 'opencv_videoio_ffmpeg4100_64.dll']
61 | ]
62 |
63 | for p in del_path:
64 | dll_path = os.path.join(dist_dir,*p)
65 | if os.path.exists(dll_path):
66 | os.remove(dll_path)
67 |
--------------------------------------------------------------------------------
/main2.spec:
--------------------------------------------------------------------------------
1 |
2 | a3 = Analysis(
3 | ['./app/ui/pdf_tools/merge/merge.py'],
4 | pathex=[],
5 | binaries=[],
6 | datas=[],
7 | hiddenimports=['openpyxl.cell._writer'],
8 | hookspath=[],
9 | hooksconfig={},
10 | runtime_hooks=[],
11 | excludes=[],
12 | noarchive=False,
13 | )
14 | pyz3 = PYZ(a3.pure)
15 | exe3 = EXE(
16 | pyz3,
17 | a3.scripts,
18 | [],
19 | exclude_binaries=True,
20 | uac_admin=False,
21 | name='PDF合并',
22 | debug=False,
23 | bootloader_ignore_signals=False,
24 | strip=False,
25 | upx=True,
26 | upx_exclude=[],
27 | runtime_tmpdir=None,
28 | console=False,
29 | disable_windowed_traceback=True,
30 | argv_emulation=False,
31 | target_arch=None,
32 | codesign_identity=None,
33 | entitlements_file=None,
34 | icon=['./resources/logo.png'],
35 | version='version.txt',
36 | )
37 |
38 | coll2 = COLLECT(
39 | exe1,exe2,
40 | a2.binaries,
41 | a2.datas,
42 | strip=False,
43 | upx=True,
44 | upx_exclude=[],
45 | name='EasyBox',
46 | )
--------------------------------------------------------------------------------
/pdf2docx/__init__.py:
--------------------------------------------------------------------------------
1 | from .converter import Converter
2 | from .page.Page import Page
--------------------------------------------------------------------------------
/pdf2docx/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/__pycache__/converter.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/__pycache__/converter.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/Block.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Base class for text/image/table blocks.
4 | '''
5 |
6 | from .share import BlockType, TextAlignment
7 | from .Element import Element
8 |
9 |
10 | class Block(Element):
11 | '''Base class for text/image/table blocks.
12 |
13 | Attributes:
14 | raw (dict): initialize object from raw properties.
15 | parent (optional): parent object that this block belongs to.
16 | '''
17 | def __init__(self, raw:dict=None, parent=None):
18 | self._type = BlockType.UNDEFINED
19 |
20 | # horizontal spacing
21 | if raw is None: raw = {}
22 | self.alignment = self._get_alignment(raw.get('alignment', 0))
23 | self.left_space = raw.get('left_space', 0.0)
24 | self.right_space = raw.get('right_space', 0.0)
25 | self.first_line_space = raw.get('first_line_space', 0.0)
26 |
27 | # RELATIVE position of tab stops
28 | self.tab_stops = raw.get('tab_stops', [])
29 |
30 | # vertical spacing
31 | self.before_space = raw.get('before_space', 0.0)
32 | self.after_space = raw.get('after_space', 0.0)
33 | self.line_space = raw.get('line_space', 0.0)
34 | self.line_space_type = raw.get('line_space_type', 1) # 0-exactly, 1-relatively
35 |
36 | super().__init__(raw, parent)
37 |
38 |
39 | @property
40 | def is_text_block(self):
41 | '''Whether test block.'''
42 | return self._type==BlockType.TEXT
43 |
44 | @property
45 | def is_inline_image_block(self):
46 | '''Whether inline image block.'''
47 | return self._type==BlockType.IMAGE
48 |
49 | @property
50 | def is_float_image_block(self):
51 | '''Whether float image block.'''
52 | return self._type==BlockType.FLOAT_IMAGE
53 |
54 | @property
55 | def is_image_block(self):
56 | '''Whether inline or float image block.'''
57 | return self.is_inline_image_block or self.is_float_image_block
58 |
59 | @property
60 | def is_text_image_block(self):
61 | '''Whether text block or inline image block.'''
62 | return self.is_text_block or self.is_inline_image_block
63 |
64 | @property
65 | def is_lattice_table_block(self):
66 | '''Whether lattice table (explicit table borders) block.'''
67 | return self._type==BlockType.LATTICE_TABLE
68 |
69 | @property
70 | def is_stream_table_block(self):
71 | '''Whether stream table (implied by table content) block.'''
72 | return self._type==BlockType.STREAM_TABLE
73 |
74 | @property
75 | def is_table_block(self):
76 | '''Whether table (lattice or stream) block.'''
77 | return self.is_lattice_table_block or self.is_stream_table_block
78 |
79 | def set_text_block(self):
80 | '''Set block type.'''
81 | self._type = BlockType.TEXT
82 |
83 | def set_inline_image_block(self):
84 | '''Set block type.'''
85 | self._type = BlockType.IMAGE
86 |
87 | def set_float_image_block(self):
88 | '''Set block type.'''
89 | self._type = BlockType.FLOAT_IMAGE
90 |
91 | def set_lattice_table_block(self):
92 | '''Set block type.'''
93 | self._type = BlockType.LATTICE_TABLE
94 |
95 | def set_stream_table_block(self):
96 | '''Set block type.'''
97 | self._type = BlockType.STREAM_TABLE
98 |
99 | def _get_alignment(self, mode:int):
100 | for t in TextAlignment:
101 | if t.value==mode:
102 | return t
103 | return TextAlignment.LEFT
104 |
105 | def parse_horizontal_spacing(self, bbox, *args):
106 | """Set left alignment, and calculate left space.
107 |
108 | Override by :obj:`pdf2docx.text.TextBlock`.
109 |
110 | Args:
111 | bbox (fitz.rect): boundary box of this block.
112 | """
113 | # NOTE: in PyMuPDF CS, horizontal text direction is same with positive x-axis,
114 | # while vertical text is on the contrary, so use f = -1 here
115 | idx, f = (0, 1.0) if self.is_horizontal_text else (3, -1.0)
116 | self.alignment = TextAlignment.LEFT
117 | self.left_space = (self.bbox[idx] - bbox[idx]) * f
118 |
119 |
120 | def store(self):
121 | '''Store attributes in json format.'''
122 | res = super().store()
123 | res.update({
124 | 'type' : self._type.value,
125 | 'alignment' : self.alignment.value,
126 | 'left_space' : self.left_space,
127 | 'right_space' : self.right_space,
128 | 'first_line_space' : self.first_line_space,
129 | 'before_space' : self.before_space,
130 | 'after_space' : self.after_space,
131 | 'line_space' : self.line_space,
132 | 'line_space_type' : self.line_space_type,
133 | 'tab_stops' : self.tab_stops
134 | })
135 | return res
136 |
137 |
138 | def make_docx(self, *args, **kwargs):
139 | """Create associated docx element.
140 |
141 | Raises:
142 | NotImplementedError
143 | """
144 | raise NotImplementedError
--------------------------------------------------------------------------------
/pdf2docx/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/Block.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/Block.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/Collection.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/Collection.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/Element.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/Element.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/algorithm.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/algorithm.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/constants.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/constants.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/docx.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/docx.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/__pycache__/share.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/common/__pycache__/share.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/common/constants.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | # -------------------------------------
5 | # basic unit
6 | # -------------------------------------
7 | PT = 1.0 # basic unit
8 | ITP = 72.0 # inch to point
9 |
10 | MAJOR_DIST = 5.0 * PT # significant distance exists between two block lines
11 | MINOR_DIST = 1.0 * PT # small distance
12 | TINY_DIST = 0.5 * PT # very small distance
13 |
14 | FACTOR_SAME = 0.99
15 | FACTOR_ALMOST = 0.95
16 | FACTOR_MOST = 0.90
17 | FACTOR_MAJOR = 0.75
18 | FACTOR_A_HALF = 0.5
19 | FACTOR_A_FEW = 0.1
20 | FACTOR_FEW = 0.01
21 |
22 |
23 | # -------------------------------------
24 | # docx
25 | # -------------------------------------
26 | HIDDEN_W_BORDER = 0.0 # do not show border
27 | MIN_LINE_SPACING = 0.7 # minimum line spacing available in MS word
28 | DEFAULT_LINE_SPACING = 1.02
29 |
30 | # punctuation implying end of a sentense
31 | SENTENCE_END_PUNC = '..。??!!'
32 |
33 | # control characters not supported by lxml
34 | # https://github.com/dothinking/pdf2docx/issues/126#issuecomment-1040034077
35 | INVALID_CHARS = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f'
36 |
37 |
38 | # -------------------------------------
39 | # font parameters
40 | # -------------------------------------
41 |
42 | # CJK font definition parameters
43 | CJK_CODEPAGE_BITS = {
44 | "JIS/Japan": 17,
45 | "Chinese: Simplified chars—PRC and Singapore": 18,
46 | "Korean Wansung": 19,
47 | "Chinese: Traditional chars—Taiwan and Hong Kong": 20,
48 | "Korean Johab": 21
49 | }
50 |
51 | CJK_UNICODE_RANGE_BITS = {
52 | 'Hangul Jamo': 28,
53 | 'Hiragana': 49,
54 | 'Katakana': 50,
55 | 'Bopomofo': 51,
56 | 'Hangul Compatibility Jamo': 52,
57 | 'Enclosed CJK Letters And Months': 54,
58 | 'CJK Compatibility': 55,
59 | 'Hangul Syllables': 56,
60 | 'CJK Unified Ideographs': 59,
61 | 'CJK Strokes': 61,
62 | 'Yi Syllables': 83
63 | }
64 |
65 | CJK_UNICODE_RANGES = [
66 | [0x1100, 0x11FF], # Hangul Jamo
67 | [0x3040, 0x309F], # Hiragana
68 | [0x30A0, 0x30FF], # Katakana
69 | [0x31F0, 0x31FF], # Katakana Phonetic Extensions
70 | [0x3100, 0x312F], # Bopomofo
71 | [0x31A0, 0x31BF], # Bopomofo Extended (Bopomofo)
72 | [0x3130, 0x318F], # Hangul Compatibility Jamo
73 | [0x3200, 0x32FF], # Enclosed CJK Letters and Months
74 | [0x3300, 0x33FF], # CJK Compatibility
75 | [0xAC00, 0xD7AF], # Hangul Syllables
76 | [0x4E00, 0x9FFF], # CJK Unified Ideographs
77 | [0x2E80, 0x2EFF], # CJK Radicals Supplement (CJK Unified Ideographs)
78 | [0x2F00, 0x2FDF], # Kangxi Radicals (CJK Unified Ideographs)
79 | [0x2FF0, 0x2FFF], # Ideographic Description Characters (CJK Unified Ideographs)
80 | [0x3400, 0x4DBF], # CJK Unified Ideographs Extension A (CJK Unified Ideographs)
81 | [0x20000, 0x2A6DF], # CJK Unified Ideographs Extension B (CJK Unified Ideographs)
82 | [0x3190, 0x319F], # Kanbun (CJK Unified Ideographs)
83 | [0x31C0, 0x31EF], # CJK Strokes
84 | [0xF900, 0xFAFF], # CJK Compatibility Ideographs (CJK Strokes)
85 | [0x2F800, 0x2FA1F], # CJK Compatibility Ideographs Supplement (CJK Strokes)
86 | [0xA000, 0xA48F], # Yi Syllables
87 | [0xA490, 0xA4CF], # Yi Radicals
88 | ]
89 |
90 | DEFAULT_FONT_NAME = 'helv'
--------------------------------------------------------------------------------
/pdf2docx/font/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/font/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/font/__pycache__/Fonts.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/font/__pycache__/Fonts.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/font/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/font/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/image/Image.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Image object.
4 |
5 | Data structure defined in link https://pymupdf.readthedocs.io/en/latest/textpage.html::
6 |
7 | {
8 | 'type': 1,
9 | 'bbox': (x0,y0,x1,y1),
10 | 'width': w,
11 | 'height': h,
12 | 'image': b'',
13 |
14 | # --- discard properties ---
15 | 'ext': 'png',
16 | 'colorspace': n,
17 | 'xref': xref, 'yref': yref, 'bpc': bpc
18 | }
19 | '''
20 |
21 | import base64
22 | from io import BytesIO
23 | from ..common import docx
24 | from ..common.Element import Element
25 |
26 |
27 | class Image(Element):
28 | '''Base image object.'''
29 |
30 | def __init__(self, raw:dict=None):
31 | if raw is None: raw = {}
32 | self.width = raw.get('width', 0.0)
33 | self.height = raw.get('height', 0.0)
34 |
35 | # source image bytes
36 | # - image bytes passed from PyMuPDF -> use it directly
37 | # - base64 encoded string restored from json file -> encode to bytes and decode with base64 -> image bytes
38 | image = raw.get('image', b'')
39 | self.image = image if isinstance(image, bytes) else base64.b64decode(image.encode())
40 |
41 | super().__init__(raw)
42 |
43 |
44 | @property
45 | def text(self):
46 | '''Get an image placeholder ````.'''
47 | return ''
48 |
49 |
50 | def from_image(self, image):
51 | '''Update with image block/span.
52 |
53 | Args:
54 | image (Image): Target image block/span.
55 | '''
56 | self.width = image.width
57 | self.height = image.height
58 | self.image = image.image
59 | self.update_bbox(image.bbox)
60 | return self
61 |
62 |
63 | def store(self):
64 | '''Store image with base64 encode.
65 |
66 | * Encode image bytes with base64 -> base64 bytes
67 | * Decode base64 bytes -> str -> so can be serialized in json format
68 | '''
69 | res = super().store()
70 | res.update({
71 | 'width': self.width,
72 | 'height': self.height,
73 | 'image': base64.b64encode(self.image).decode() # serialize image with base64
74 | })
75 |
76 | return res
77 |
78 |
79 | def plot(self, page, color:tuple):
80 | '''Plot image bbox with diagonal lines (for debug purpose).
81 |
82 | Args:
83 | page (fitz.Page): Plotting page.
84 | '''
85 | x0, y0, x1, y1 = self.bbox
86 | page.draw_line((x0, y0), (x1, y1), color=color, width=0.5)
87 | page.draw_line((x0, y1), (x1, y0), color=color, width=0.5)
88 | super().plot(page, stroke=color)
89 |
90 |
91 | def make_docx(self, paragraph):
92 | '''Add image span to a docx paragraph.'''
93 | # add image
94 | docx.add_image(paragraph, BytesIO(self.image), self.bbox.x1-self.bbox.x0, self.bbox.y1-self.bbox.y0)
--------------------------------------------------------------------------------
/pdf2docx/image/ImageBlock.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Definition of Image block objects.
4 |
5 | **The raw image block will be merged into TextBlock > Line > Span.**
6 | '''
7 |
8 | from io import BytesIO
9 | from ..text.Line import Line
10 | from ..text.TextBlock import TextBlock
11 | from .Image import Image
12 | from .ImageSpan import ImageSpan
13 | from ..common.Block import Block
14 | from ..common.docx import add_float_image
15 |
16 |
17 | class ImageBlock(Image, Block):
18 | '''Image block.'''
19 | def __init__(self, raw:dict=None):
20 | super().__init__(raw)
21 |
22 | # inline image type by default
23 | self.set_inline_image_block()
24 |
25 |
26 | def to_text_block(self):
27 | """Convert image block to a span under text block.
28 |
29 | Returns:
30 | TextBlock: New TextBlock instance containing this image.
31 | """
32 | # image span
33 | span = ImageSpan().from_image(self)
34 |
35 | # add span to line
36 | image_line = Line()
37 | image_line.add(span)
38 |
39 | # insert line to block
40 | block = TextBlock()
41 | block.add(image_line)
42 |
43 | # NOTE: it's an image block even though in TextBlock type
44 | block.set_inline_image_block()
45 |
46 | return block
47 |
48 |
49 | def store(self):
50 | '''Store ImageBlock instance in raw dict.'''
51 | res = Block.store(self)
52 | res.update(
53 | Image.store(self)
54 | )
55 | return res
56 |
57 |
58 | def plot(self, page):
59 | '''Plot image bbox with diagonal lines (for debug purpose).
60 |
61 | Args:
62 | page (fitz.Page): pdf page to plot.
63 | '''
64 | super().plot(page, color=(1,0,0))
65 |
66 |
67 | def make_docx(self, p):
68 | '''Create floating image behind text.
69 |
70 | Args:
71 | p (Paragraph): ``python-docx`` paragraph instance.
72 |
73 | .. note::
74 | Inline image is created within TextBlock.
75 | '''
76 | if self.is_float_image_block:
77 | x0, y0, x1, y1 = self.bbox
78 | add_float_image(p, BytesIO(self.image), width=x1-x0, pos_x=x0, pos_y=y0)
79 | else:
80 | super().make_docx(p)
81 | return p
--------------------------------------------------------------------------------
/pdf2docx/image/ImageSpan.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Image span based on same raw data structure with Image block.
4 | '''
5 |
6 | from ..common import constants
7 | from .Image import Image
8 |
9 |
10 | class ImageSpan(Image):
11 | '''Image span.'''
12 |
13 | def intersects(self, rect):
14 | '''Create new ImageSpan object with image contained in given bbox.
15 |
16 | Args:
17 | rect (fitz.Rect): Target bbox.
18 |
19 | Returns:
20 | ImageSpan: A copy of itself if intersects with target; otherwise empty ImageSpan.
21 | '''
22 | # add image span if most of of the image is contained in bbox
23 | if self.get_main_bbox(rect, constants.FACTOR_MAJOR):
24 | return self.copy()
25 |
26 | # otherwise, ignore image
27 | return ImageSpan()
--------------------------------------------------------------------------------
/pdf2docx/image/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/image/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/image/__pycache__/Image.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/image/__pycache__/Image.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/image/__pycache__/ImageBlock.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/image/__pycache__/ImageBlock.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/image/__pycache__/ImageSpan.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/image/__pycache__/ImageSpan.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/image/__pycache__/ImagesExtractor.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/image/__pycache__/ImagesExtractor.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/image/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/image/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/layout/Column.py:
--------------------------------------------------------------------------------
1 | '''Column of Section.
2 |
3 | In most cases, one section per page. But in case multi-columns page, sections are used
4 | to distinguish these different layouts.
5 |
6 | .. note::
7 | Currently, support at most two columns.
8 |
9 | ::
10 |
11 | {
12 | 'bbox': (x0, y0, x1, y1),
13 | 'blocks': [{
14 | ... # block instances
15 | }, ...],
16 | 'shapes': [{
17 | ... # shape instances
18 | }, ...]
19 | }
20 | '''
21 |
22 | from ..common.Collection import Collection
23 | from ..layout.Layout import Layout
24 | from ..shape.Shape import Shape
25 | from ..text.Line import Line
26 |
27 |
28 | class Column(Layout):
29 | '''Column of Section.'''
30 |
31 | @property
32 | def working_bbox(self): return self.bbox
33 |
34 |
35 | def add_elements(self, elements:Collection):
36 | '''Add candidate elements, i.e. lines or shapes, to current column.'''
37 | blocks = [e for e in elements if isinstance(e, Line)]
38 | shapes = [e for e in elements if isinstance(e, Shape)]
39 | self.assign_blocks(blocks)
40 | self.assign_shapes(shapes)
41 |
42 |
43 | def make_docx(self, doc):
44 | '''Create Section Column in docx.
45 |
46 | Args:
47 | doc (Document): ``python-docx`` document object
48 | '''
49 | self.blocks.make_docx(doc)
50 |
--------------------------------------------------------------------------------
/pdf2docx/layout/Section.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Section of Page.
4 |
5 | In most cases, one section per page. But in case multi-columns page, sections are used
6 | to distinguish these different layouts.
7 |
8 | .. note::
9 | Currently, support at most two columns.
10 |
11 | ::
12 |
13 | {
14 | 'bbox': (x0,y0,x1,y1)
15 | 'num_cols': 1,
16 | 'space': 0,
17 | 'columns': [{
18 | ... # column properties
19 | }, ...]
20 | }
21 | '''
22 |
23 | from docx.enum.section import WD_SECTION
24 | from ..common.docx import set_columns
25 | from ..common.Collection import BaseCollection
26 | from .Column import Column
27 |
28 |
29 | class Section(BaseCollection):
30 |
31 | def __init__(self, space:int=0, columns:list=None, parent=None):
32 | """Initialize Section instance.
33 |
34 | Args:
35 | space (int, optional): Space between adjacent columns. Defaults to 0.
36 | columns (list, optional): A list of Column instances. Defaults to None.
37 | parent (Sections, optional): Parent element. Defaults to None.
38 | """
39 | self.space = space
40 | self.before_space = 0.0
41 | super().__init__(columns, parent)
42 |
43 |
44 | @property
45 | def num_cols(self): return len(self)
46 |
47 |
48 | def store(self):
49 | '''Store parsed section layout in dict format.'''
50 | return {
51 | 'bbox' : tuple([x for x in self.bbox]),
52 | 'num_cols' : self.num_cols,
53 | 'space' : self.space,
54 | 'before_space' : self.before_space,
55 | 'columns': super().store()
56 | }
57 |
58 |
59 | def restore(self, raw:dict):
60 | '''Restore section from source dict.'''
61 | # bbox is maintained automatically based on columns
62 | self.space = raw.get('space', 0) # space between adjacent columns
63 | self.before_space = raw.get('before_space', 0) # space between adjacent columns
64 |
65 | # get each column
66 | for raw_col in raw.get('columns', []):
67 | column = Column().restore(raw_col)
68 | self.append(column)
69 |
70 | return self
71 |
72 |
73 | def parse(self, **settings):
74 | '''Parse section layout.'''
75 | for column in self: column.parse(**settings)
76 | return self
77 |
78 |
79 | def make_docx(self, doc):
80 | '''Create section in docx.
81 |
82 | Args:
83 | doc (Document): ``python-docx`` document object
84 | '''
85 | # set section column
86 | section = doc.sections[-1]
87 | width_list = [c.bbox[2]-c.bbox[0] for c in self]
88 | set_columns(section, width_list, self.space)
89 |
90 | # add create each column
91 | for column in self:
92 | # column break to start new column
93 | if column != self[0]:
94 | doc.add_section(WD_SECTION.NEW_COLUMN)
95 |
96 | # make doc
97 | column.make_docx(doc)
--------------------------------------------------------------------------------
/pdf2docx/layout/Sections.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Collection of :py:class:`~pdf2docx.layout.Section` instances.
4 | '''
5 |
6 | from docx.enum.section import WD_SECTION
7 | from docx.shared import Pt
8 | from ..common.Collection import BaseCollection
9 | from ..common.docx import reset_paragraph_format
10 | from .Section import Section
11 | from ..common import constants
12 |
13 |
14 | class Sections(BaseCollection):
15 |
16 | def restore(self, raws:list):
17 | """Restore sections from source dicts."""
18 | self.reset()
19 | for raw in raws:
20 | section = Section().restore(raw)
21 | self.append(section)
22 | return self
23 |
24 |
25 | def parse(self, **settings):
26 | '''Parse layout under section level.'''
27 | for section in self: section.parse(**settings)
28 | return self
29 |
30 |
31 | def make_docx(self, doc):
32 | '''Create sections in docx.'''
33 | if not self: return
34 |
35 | # mark paragraph index before creating current page
36 | n = len(doc.paragraphs)
37 |
38 | def create_dummy_paragraph_for_section(section):
39 | p = doc.add_paragraph()
40 | line_height = min(section.before_space, 11)
41 | pf = reset_paragraph_format(p, line_spacing=Pt(line_height))
42 | pf.space_after = Pt(section.before_space-line_height)
43 |
44 | # ---------------------------------------------------
45 | # first section
46 | # ---------------------------------------------------
47 | # vertical position: add dummy paragraph only if before space is required
48 | section = self[0]
49 | if section.before_space > constants.MINOR_DIST:
50 | create_dummy_paragraph_for_section(section)
51 |
52 | # create first section
53 | if section.num_cols==2:
54 | doc.add_section(WD_SECTION.CONTINUOUS)
55 | section.make_docx(doc)
56 |
57 | # ---------------------------------------------------
58 | # more sections
59 | # ---------------------------------------------------
60 | for section in self[1:]:
61 | # create new section symbol
62 | doc.add_section(WD_SECTION.CONTINUOUS)
63 |
64 | # set after space of last paragraph to define the vertical
65 | # position of current section
66 | # NOTE: the after space doesn't work if last paragraph is
67 | # image only (without any text). In this case, set after
68 | # space for the section break.
69 | p = doc.paragraphs[-2] # -1 is the section break
70 | if not p.text.strip() and 'graphicData' in p._p.xml:
71 | p = doc.paragraphs[-1]
72 | pf = p.paragraph_format
73 | pf.space_after = Pt(section.before_space)
74 |
75 | # section content
76 | section.make_docx(doc)
77 |
78 | # ---------------------------------------------------
79 | # create floating images
80 | # ---------------------------------------------------
81 | # lazy: assign all float images to first paragraph of current page
82 | for image in self.parent.float_images:
83 | image.make_docx(doc.paragraphs[n])
84 |
85 |
86 | def plot(self, page):
87 | '''Plot all section blocks for debug purpose.'''
88 | for section in self:
89 | for column in section:
90 | column.plot(page, stroke=(1,1,0), width=1.5) # column bbox
91 | column.blocks.plot(page) # blocks
--------------------------------------------------------------------------------
/pdf2docx/layout/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/layout/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/layout/__pycache__/Blocks.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/layout/__pycache__/Blocks.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/layout/__pycache__/Column.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/layout/__pycache__/Column.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/layout/__pycache__/Layout.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/layout/__pycache__/Layout.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/layout/__pycache__/Section.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/layout/__pycache__/Section.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/layout/__pycache__/Sections.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/layout/__pycache__/Sections.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/layout/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/layout/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/page/BasePage.py:
--------------------------------------------------------------------------------
1 | '''Base page with basic properties, e.g. width, height and margin.'''
2 |
3 | class BasePage:
4 | def __init__(self, width:float=0.0, height:float=0.0, margin:tuple=None):
5 | '''Initialize page layout.
6 |
7 | Args:
8 | width (float, optional): Page width. Defaults to 0.0.
9 | height (float, optional): Page height. Defaults to 0.0.
10 | margin (tuple, optional): Page margin. Defaults to None.
11 | '''
12 | # page size and margin
13 | self.width = width
14 | self.height = height
15 | self.margin = margin or (0,) * 4
16 |
17 |
18 | @property
19 | def bbox(self): return (0.0, 0.0, self.width, self.height)
20 |
21 |
22 | @property
23 | def working_bbox(self):
24 | '''bbox with margin considered.'''
25 | x0, y0, x1, y1 = self.bbox
26 | L, R, T, B = self.margin
27 | return (x0+L, y0+T, x1-R, y1-B)
--------------------------------------------------------------------------------
/pdf2docx/page/Pages.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Collection of :py:class:`~pdf2docx.page.Page` instances.'''
4 |
5 | import logging
6 |
7 | from .RawPageFactory import RawPageFactory
8 | from ..common.Collection import BaseCollection
9 | from ..font.Fonts import Fonts
10 |
11 |
12 | class Pages(BaseCollection):
13 | '''A collection of ``Page``.'''
14 |
15 | def parse(self, fitz_doc, **settings):
16 | '''Analyze document structure, e.g. page section, header, footer.
17 |
18 | Args:
19 | fitz_doc (fitz.Document): ``PyMuPDF`` Document instance.
20 | settings (dict): Parsing parameters.
21 | '''
22 | # ---------------------------------------------
23 | # 0. extract fonts properties, especially line height ratio
24 | # ---------------------------------------------
25 | fonts = Fonts.extract(fitz_doc)
26 |
27 | # ---------------------------------------------
28 | # 1. extract and then clean up raw page
29 | # ---------------------------------------------
30 | pages, raw_pages = [], []
31 | words_found = False
32 | for page in self:
33 | if page.skip_parsing: continue
34 |
35 | # init and extract data from PDF
36 | raw_page = RawPageFactory.create(page_engine=fitz_doc[page.id], backend='PyMuPDF')
37 | raw_page.restore(**settings)
38 |
39 | # check if any words are extracted since scanned pdf may be directed
40 | if not words_found and raw_page.raw_text.strip():
41 | words_found = True
42 |
43 | # process blocks and shapes based on bbox
44 | raw_page.clean_up(**settings)
45 |
46 | # process font properties
47 | raw_page.process_font(fonts)
48 |
49 | # after this step, we can get some basic properties
50 | # NOTE: floating images are detected when cleaning up blocks, so collect them here
51 | page.width = raw_page.width
52 | page.height = raw_page.height
53 | page.float_images.reset().extend(raw_page.blocks.floating_image_blocks)
54 |
55 | raw_pages.append(raw_page)
56 | pages.append(page)
57 |
58 | # show message if no words found
59 | if not words_found:
60 | logging.warning('Words count: 0. It might be a scanned pdf, which is not supported yet.')
61 |
62 |
63 | # ---------------------------------------------
64 | # 2. parse structure in document/pages level
65 | # ---------------------------------------------
66 | # NOTE: blocks structure might be changed in this step, e.g. promote page header/footer,
67 | # so blocks structure based process, e.g. calculating margin, parse section should be
68 | # run after this step.
69 | header, footer = Pages._parse_document(raw_pages)
70 |
71 |
72 | # ---------------------------------------------
73 | # 3. parse structure in page level, e.g. page margin, section
74 | # ---------------------------------------------
75 | # parse sections
76 | for page, raw_page in zip(pages, raw_pages):
77 | # page margin
78 | margin = raw_page.calculate_margin(**settings)
79 | raw_page.margin = page.margin = margin
80 |
81 | # page section
82 | sections = raw_page.parse_section(**settings)
83 | page.sections.extend(sections)
84 |
85 |
86 | @staticmethod
87 | def _parse_document(raw_pages:list):
88 | '''Parse structure in document/pages level, e.g. header, footer'''
89 | # TODO
90 | return '', ''
--------------------------------------------------------------------------------
/pdf2docx/page/RawPageFactory.py:
--------------------------------------------------------------------------------
1 | '''
2 | Load :py:class:`~pdf2docx.page.RawPage` with specified pdf engine,
3 | e.g. PyMuPDF, pdfminer.six. For now, only PyMuPDF is implemented.
4 | '''
5 |
6 | from .RawPageFitz import RawPageFitz
7 |
8 |
9 | class RawPageFactory:
10 |
11 | MAP = {
12 | 'PYMUPDF': RawPageFitz
13 | }
14 |
15 | @classmethod
16 | def create(cls, page_engine, backend:str='pymupdf'):
17 | '''Create RawPage class with specified backend.'''
18 | klass = cls.MAP.get(backend.upper(), None)
19 | if not klass:
20 | raise TypeError(f'Page with pdf engine "{backend}" is not implemented yet.')
21 | else:
22 | return klass(page_engine=page_engine)
23 |
--------------------------------------------------------------------------------
/pdf2docx/page/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/page/__pycache__/BasePage.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__pycache__/BasePage.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/page/__pycache__/Page.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__pycache__/Page.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/page/__pycache__/Pages.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__pycache__/Pages.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/page/__pycache__/RawPage.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__pycache__/RawPage.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/page/__pycache__/RawPageFactory.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__pycache__/RawPageFactory.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/page/__pycache__/RawPageFitz.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__pycache__/RawPageFitz.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/page/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/page/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/shape/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/shape/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/shape/__pycache__/Path.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/shape/__pycache__/Path.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/shape/__pycache__/Paths.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/shape/__pycache__/Paths.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/shape/__pycache__/Shape.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/shape/__pycache__/Shape.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/shape/__pycache__/Shapes.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/shape/__pycache__/Shapes.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/shape/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/shape/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/table/Cells.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Collection of Cell instances.
4 | '''
5 |
6 | from .Cell import Cell
7 | from ..common.Collection import ElementCollection
8 |
9 |
10 | class Cells(ElementCollection):
11 | '''A group of Cells.'''
12 | def restore(self, raws:list):
13 | '''Restore Cells from source dict.
14 |
15 | Args:
16 | raws (list): A list of source dict.
17 | '''
18 | for raw in raws:
19 | cell = Cell(raw)
20 | self.append(cell)
21 | return self
22 |
23 | def append(self, cell:Cell):
24 | '''Override. Append a cell (allow empty cell, i.e. merged cells) and update bbox accordingly.'''
25 | self._instances.append(cell)
26 | self._update_bbox(cell)
27 | cell.parent = self._parent # set parent
28 |
--------------------------------------------------------------------------------
/pdf2docx/table/Row.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Row in a table.
4 | '''
5 |
6 | from docx.enum.table import WD_ROW_HEIGHT
7 | from docx.shared import Pt
8 | from .Cells import Cells
9 | from ..common.Element import Element
10 |
11 |
12 | class Row(Element):
13 | '''Row in a table.'''
14 | def __init__(self, raw:dict=None):
15 | if raw is None: raw = {}
16 | super().__init__(raw)
17 |
18 | # logical row height
19 | self.height = raw.get('height', 0.0)
20 |
21 | # cells in row
22 | self._cells = Cells(parent=self).restore(raw.get('cells', []))
23 |
24 |
25 | def __getitem__(self, idx):
26 | try:
27 | cell = self._cells[idx]
28 | except IndexError:
29 | msg = f'Cell index {idx} out of range'
30 | raise IndexError(msg)
31 | else:
32 | return cell
33 |
34 | def __iter__(self):
35 | return (cell for cell in self._cells)
36 |
37 | def __len__(self):
38 | return len(self._cells)
39 |
40 |
41 | def append(self, cell):
42 | '''Append cell to row and update bbox accordingly.'''
43 | self._cells.append(cell)
44 |
45 |
46 | def store(self):
47 | res = super().store()
48 | res.update({
49 | 'height': self.height,
50 | 'cells': self._cells.store()
51 | })
52 |
53 | return res
54 |
55 |
56 | def make_docx(self, table, idx_row:int):
57 | '''Create row of docx table.
58 |
59 | Args:
60 | table (Table): ``python-docx`` table instance.
61 | idx_row (int): Current row index.
62 | '''
63 | # set row height
64 | docx_row = table.rows[idx_row]
65 |
66 | # to control the layout precisely, set `exact` value, rather than `at least` value
67 | # the associated steps in MS word: Table Properties -> Row -> Row height -> exactly
68 | docx_row.height_rule = WD_ROW_HEIGHT.EXACTLY
69 |
70 | # NOTE: row height is counted from center-line of top border to center line of bottom border
71 | docx_row.height = Pt(self.height)
72 |
73 | # set cell style and contents
74 | for idx_col in range(len(table.columns)):
75 | self._cells[idx_col].make_docx(table, (idx_row, idx_col))
--------------------------------------------------------------------------------
/pdf2docx/table/Rows.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''A group of Row objects in a table.
4 | '''
5 |
6 | from .Row import Row
7 | from ..common.Collection import ElementCollection
8 |
9 |
10 | class Rows(ElementCollection):
11 | '''A group of Rows.'''
12 |
13 | def restore(self, raws:list):
14 | """Restore Rows from source dicts.
15 |
16 | Args:
17 | raws (list): A list of source dicts representing each row.
18 |
19 | Returns:
20 | Rows: self
21 | """
22 | for raw in raws:
23 | row = Row(raw)
24 | self.append(row)
25 | return self
26 |
--------------------------------------------------------------------------------
/pdf2docx/table/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/table/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/table/__pycache__/Cell.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/table/__pycache__/Cell.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/table/__pycache__/Cells.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/table/__pycache__/Cells.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/table/__pycache__/Row.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/table/__pycache__/Row.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/table/__pycache__/Rows.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/table/__pycache__/Rows.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/table/__pycache__/TableBlock.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/table/__pycache__/TableBlock.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/table/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/table/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/text/Char.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Char object based on PDF raw dict extracted with ``PyMuPDF``.
4 |
5 | Data structure refer to this `link `_::
6 |
7 | {
8 | 'bbox' : (x0, y0, x1, y1),
9 | 'c' : str,
10 | 'origin': (x,y)
11 | }
12 | '''
13 |
14 |
15 | from ..common.constants import INVALID_CHARS
16 | from ..common.Element import Element
17 | from ..shape.Shape import Shape
18 |
19 |
20 | class Char(Element):
21 | '''Object representing a character.'''
22 | def __init__(self, raw:dict=None):
23 | if raw is None: raw = {}
24 |
25 | # Note to filter control character avoiding error when making docx, #126
26 | c = raw.get('c', '')
27 | if c in INVALID_CHARS: c = ''
28 | self.c = c
29 | self.origin = raw.get('origin', None)
30 |
31 | super().__init__(raw) # NOTE: ignore parent element for Char instance
32 |
33 |
34 | def contained_in_rect(self, rect:Shape, horizontal:bool=True):
35 | """Detect whether it locates in a rect.
36 |
37 | Args:
38 | rect (Shape): Target rect to check.
39 | horizontal (bool, optional): Text direction is horizontal if True. Defaults to True.
40 |
41 | Returns:
42 | bool: Whether a Char locates in target rect.
43 |
44 | .. note::
45 | It's considered as contained in the target rect if the intersection is larger than
46 | half of the char bbox.
47 | """
48 | # char in rect?
49 | if self.bbox in rect.bbox: return True
50 |
51 | # intersection?
52 | s = self.bbox & rect.bbox
53 | if s.is_empty: return False
54 | if horizontal: return s.width > 0.5*self.bbox.width
55 | return s.height > 0.5*self.bbox.height
56 |
57 |
58 | def store(self):
59 | res = super().store()
60 | res.update({
61 | 'c': self.c,
62 | 'origin': self.origin
63 | })
64 |
65 | return res
--------------------------------------------------------------------------------
/pdf2docx/text/Spans.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''A group of TextSpan and ImageSpan objects.
4 | '''
5 |
6 | from ..common.Collection import ElementCollection
7 | from .TextSpan import TextSpan
8 | from ..image.ImageSpan import ImageSpan
9 |
10 | class Spans(ElementCollection):
11 | '''Collection of TextSpan and ImageSpan instances.'''
12 |
13 | def restore(self, raws:list):
14 | '''Recreate TextSpan or ImageSpan from source dict list.'''
15 | for raw_span in raws:
16 | if 'image' in raw_span:
17 | span = ImageSpan(raw_span)
18 | else:
19 | span = TextSpan(raw_span)
20 | if not span.text.strip() and not span.style:
21 | span = None
22 |
23 | self.append(span)
24 | return self
25 |
26 | @property
27 | def text_spans(self):
28 | '''Get TextSpan instances.'''
29 | spans = list(filter(
30 | lambda span: isinstance(span, TextSpan), self._instances
31 | ))
32 | return Spans(spans)
33 |
34 | @property
35 | def image_spans(self):
36 | '''Get ImageSpan instances.'''
37 | spans = list(filter(
38 | lambda span: isinstance(span, ImageSpan), self._instances
39 | ))
40 | return Spans(spans)
41 |
42 |
43 | def strip(self):
44 | '''Remove redundant blanks at the begin/end span.'''
45 | stripped = False
46 | if not self._instances: return stripped
47 |
48 | # left strip the first span
49 | left_span = self._instances[0]
50 | if isinstance(left_span, TextSpan): stripped = stripped or left_span.lstrip()
51 |
52 | # right strip the last span
53 | right_span = self._instances[-1]
54 | if isinstance(right_span, TextSpan): stripped = stripped or right_span.rstrip()
55 |
56 | # update bbox
57 | if stripped: self._parent.update_bbox(self.bbox)
58 |
59 | return stripped
--------------------------------------------------------------------------------
/pdf2docx/text/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__init__.py
--------------------------------------------------------------------------------
/pdf2docx/text/__pycache__/Char.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__pycache__/Char.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/text/__pycache__/Line.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__pycache__/Line.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/text/__pycache__/Lines.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__pycache__/Lines.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/text/__pycache__/Spans.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__pycache__/Spans.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/text/__pycache__/TextBlock.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__pycache__/TextBlock.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/text/__pycache__/TextSpan.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__pycache__/TextSpan.cpython-313.pyc
--------------------------------------------------------------------------------
/pdf2docx/text/__pycache__/__init__.cpython-313.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/pdf2docx/text/__pycache__/__init__.cpython-313.pyc
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # EasyBox——一个多功能工具箱
2 |
3 | ## 支持的功能
4 |
5 | * PDF工具箱
6 | * 合并PDF✅
7 | * 拆分PDF✅
8 | * PDF加密✅
9 | * PDF解密✅
10 | * 文档转换
11 | * PDF转Word
12 | * 网页转PDF
13 | * 图片工具
14 | * 根据文件名修改图片拍摄时间
15 |
16 | ## 相关文章
17 |
18 | * [Python合并多个PDF](https://blog.lc044.love/post/11)
19 | * [PyQt5/PySide6自定义可拖拽列表组件](https://blog.lc044.love/post/12)
20 | * [基于文件名修改图片的拍摄日期](https://blog.lc044.love/post/14)
21 | * [基于 PyQt5/PySide6 实现分组列表滚动吸顶效果](https://blog.lc044.love/post/15)
22 |
23 | ## 运行截图
24 |
25 | 
26 | 
27 | 
28 | 
29 |
30 | ## PDF工具箱功能说明
31 |
32 | ### PDF合并
33 | 将多个PDF文件合并为一个文件,支持设置文件顺序和页面范围,可以保留原PDF的书签。
34 |
35 | ### PDF拆分
36 | 支持多种拆分方式:按页数拆分、按页码范围拆分、提取单页、拆分为单页文件。输出文件格式为"原文件名_拆分文件_页码.pdf"。
37 |
38 | ### PDF加密
39 | 为PDF文件添加密码保护,支持设置用户密码(打开文档)和所有者密码(编辑文档),可自定义权限控制(打印、复制、修改等),支持多种加密方式(AES-128, RC4-128, RC4-40)。
40 |
41 | ### PDF解密
42 | 提供多种解密方式:
43 | - 常规解密:使用用户提供的密码解密
44 | - 密码破解:使用John the Ripper自动破解PDF密码(需额外安装),支持字典攻击和暴力破解
45 |
46 | ## 计划中功能
47 |
48 | * PDF工具箱
49 | * 添加水印
50 | * 去除水印
51 | * 文档转换
52 | * PDF转Word
53 | * PDF转图片
54 | * PDF转TXT
55 | * PDF转MarkDown
56 | * 图片转PDF
57 | * 批量工具
58 | * 批量重命名
59 | * 图片批量改格式
60 | * 文档批量加水印
61 | * 批量替换文本
62 | * 视频工具
63 | * 屏幕录制(没有分辨率限制)
64 | * 定时录制
65 | * 视频转GIF
66 | * 视频转avi
67 | * 视频转MP4
68 |
69 | ## 安装
70 |
71 | ```shell
72 | git clone https://github.com/LC044/EasyBox.git
73 | cd EaseBox
74 | pip install -r requirements.txt
75 | ```
76 |
77 | ## 运行
78 |
79 | ```shell
80 | python main.py
81 | ```
82 |
83 | ## 打包
84 |
85 | ```shell
86 | pip install pyinstaller
87 | pyinstaller main1.spec
88 | ```
89 |
90 | ## 证书
91 |
92 | [AGPL3.0](./LICENSE)
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | PyQtWebEngine
2 | python-docx
3 | docxcompose
4 | pillow~=11.0.0
5 | pymupdf~=1.24.13
6 | PySide6~=6.8.0.2
7 | pdf2docx~=0.5.8
8 | piexif~=1.1.3
9 | numpy~=2.1.3
10 | opencv-python~=4.10.0.84
11 | fonttools~=4.54.1
12 | setuptools~=75.3.0
13 | Cython~=3.0.11
14 | PyPDF2~=3.0.1
15 | pdf2john~=0.2.0
16 |
--------------------------------------------------------------------------------
/resource.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | resources/icons/Cursors/0.png
4 | resources/icons/Cursors/1.png
5 | resources/icons/Cursors/2.png
6 | resources/icons/Cursors/3.png
7 | resources/icons/Cursors/4.png
8 | resources/icons/Cursors/5.png
9 | resources/icons/Cursors/6.png
10 | resources/icons/Cursors/7.png
11 | resources/icons/back.svg
12 | resources/icons/logo.png
13 | resources/icons/logo.ico
14 | resources/icons/setting.svg
15 | resources/icons/select.svg
16 | resources/icons/unselect.svg
17 | resources/icons/arrow-left.svg
18 | resources/icons/arrow-right.svg
19 | resources/icons/down.svg
20 | resources/icons/up.svg
21 | resources/icons/增加.svg
22 | resources/icons/批量添加.svg
23 | resources/icons/加.svg
24 | resources/icons/html.svg
25 | resources/icons/markdown.svg
26 | resources/icons/减.svg
27 | resources/icons/工具箱.svg
28 | resources/icons/左展开.svg
29 | resources/icons/右展开.svg
30 | resources/icons/图片.svg
31 | resources/icons/pdf.svg
32 | resources/icons/文档转换.svg
33 | resources/icons/批量操作.svg
34 | resources/icons/weixin.png
35 | resources/icons/录屏.svg
36 | resources/icons/合并.svg
37 | resources/icons/视频.svg
38 | resources/icons/拆分.svg
39 | resources/icons/钥匙.svg
40 | resources/icons/锁.svg
41 | resources/icons/删除.svg
42 | resources/icons/Excel.svg
43 | resources/icons/word.svg
44 | resources/icons/水印.svg
45 | resources/icons/txt.svg
46 |
47 |
48 | resources/QSS/style.qss
49 |
50 |
51 |
--------------------------------------------------------------------------------
/resources/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | @Time : 2024/11/29 16:48
6 | @Author : SiYuan
7 | @Email : siyuan044@qq.com
8 | @File : EasyBox-__init__.py.py
9 | @Description :
10 | """
11 |
12 | if __name__ == '__main__':
13 | pass
14 |
--------------------------------------------------------------------------------
/resources/icons/Cursors/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/0.png
--------------------------------------------------------------------------------
/resources/icons/Cursors/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/1.png
--------------------------------------------------------------------------------
/resources/icons/Cursors/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/2.png
--------------------------------------------------------------------------------
/resources/icons/Cursors/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/3.png
--------------------------------------------------------------------------------
/resources/icons/Cursors/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/4.png
--------------------------------------------------------------------------------
/resources/icons/Cursors/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/5.png
--------------------------------------------------------------------------------
/resources/icons/Cursors/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/6.png
--------------------------------------------------------------------------------
/resources/icons/Cursors/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/Cursors/7.png
--------------------------------------------------------------------------------
/resources/icons/Excel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/__init__.py
--------------------------------------------------------------------------------
/resources/icons/arrow-left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/arrow-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/back.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/resources/icons/down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/help.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/html.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/resources/icons/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/logo.ico
--------------------------------------------------------------------------------
/resources/icons/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/logo.png
--------------------------------------------------------------------------------
/resources/icons/markdown.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/pdf.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/select.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/txt.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/unselect.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/up.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/weixin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/icons/weixin.png
--------------------------------------------------------------------------------
/resources/icons/word.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/resources/icons/减.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/删除.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/加.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/右展开.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/合并.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/图片.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/增加.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/工具箱.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/左展开.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/录屏.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/批量操作.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/批量添加.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/拆分.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/文档转换.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/水印.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/视频.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/icons/锁.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LC044/EasyBox/974f0be3c8524109b9bce93921831ae53421e585/resources/images/logo.png
--------------------------------------------------------------------------------
/screenshot/screenrecord.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import subprocess
3 | from PySide6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QLabel
4 |
5 | class ScreenRecorderApp(QWidget):
6 | def __init__(self):
7 | super().__init__()
8 |
9 | self.setWindowTitle("Screen Recorder")
10 | self.setGeometry(200, 200, 300, 150)
11 |
12 | # 创建按钮和标签
13 | self.start_button = QPushButton("Start Recording", self)
14 | self.stop_button = QPushButton("Stop Recording", self)
15 | self.status_label = QLabel("Status: Idle", self)
16 |
17 | # 布局
18 | layout = QVBoxLayout()
19 | layout.addWidget(self.status_label)
20 | layout.addWidget(self.start_button)
21 | layout.addWidget(self.stop_button)
22 |
23 | self.setLayout(layout)
24 |
25 | # 按钮事件
26 | self.start_button.clicked.connect(self.start_recording)
27 | self.stop_button.clicked.connect(self.stop_recording)
28 |
29 | self.recording_process = None
30 |
31 | def start_recording(self):
32 | self.status_label.setText("Status: Recording...")
33 | # 使用 FFmpeg 开始屏幕录制
34 | command = [
35 | r"E:\Project\Python\MemoTrace\app\resources\data\ffmpeg.exe",
36 | "-f", "x11grab", # X11屏幕抓取
37 | "-s", "1920x1080", # 分辨率
38 | "-i", ":0.0", # 输入设备,屏幕
39 | r"E:\Project\Python\EasyBox\screenshot\output.mp4" # 输出文件
40 | ]
41 | # 启动子进程
42 | self.recording_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
43 | self.start_button.setEnabled(False)
44 | self.stop_button.setEnabled(True)
45 |
46 | def stop_recording(self):
47 | self.status_label.setText("Status: Stopped")
48 | if self.recording_process:
49 | self.recording_process.terminate() # 终止录制进程
50 | self.recording_process = None
51 | self.start_button.setEnabled(True)
52 | self.stop_button.setEnabled(False)
53 |
54 | if __name__ == "__main__":
55 | app = QApplication(sys.argv)
56 | window = ScreenRecorderApp()
57 | window.show()
58 | sys.exit(app.exec_())
59 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 | from Cython.Build import cythonize
3 | import os
4 |
5 |
6 | def find_py_files(path):
7 | py_files = []
8 | for root, dirs, files in os.walk(path):
9 | for file in files:
10 | if file.endswith(".py") and file != "setup.py":
11 | py_files.append(os.path.join(root, file))
12 | return py_files
13 |
14 |
15 | py_files = find_py_files("./app/")
16 |
17 | # 如果工程名和模块无冲突,直接编译
18 | setup(
19 | ext_modules=cythonize(py_files, language_level="3")
20 | )
21 |
22 |
--------------------------------------------------------------------------------