diff --git a/.gitignore b/.gitignore
index fb936ad..08701dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -122,8 +122,12 @@ venv.bak/
# mypy
.mypy_cache/
-.dmypy.json
-dmypy.json
+*.json
+*.log
+*.ini
+*.test
+*.tst
+*.txt
# Pyre type checker
.pyre/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb9221d..017952d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -108,3 +108,18 @@
23. Update color rule and relation under ryb system.
24. Optimize data type.
25. Change default font to LXGW WenKai.
+
+# v2.8.35-x3d3s3
+* Date: July 16, 2023
+* Tag: https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.35
+* Comments:
+1. Update scale factor for 1080p screen.
+2. Change color cube ratio.
+3. Update view icons.
+4. Update translations.
+5. Update button logic.
+6. Fix fcitx input bug on Ubuntu.
+7. Change default font to Noto Sans.
+8. Update interface theme colors.
+9. Upgrade ersion of PyQt5 from 5.12.1 to 5.15.6.
+10. Upgrade version of settings.json from 2 to 3 (x3d3s3).
diff --git a/README.md b/README.md
index aa38053..3952a2e 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ In the age of digital creativity, the color palette has become an indispensable
Rickrack (**R**e**a**l-t**i**me **C**olor **K**it) is a free and user-friendly color editor. It is designed to generate a set of harmonious colors from the color wheel or other places. You can share these colors with your friends, or apply them into your creative works. What’s more, you can export them into individual files and import them into other softwares such as Adobe Photoshop, GIMP, Krita, Pencil 2D and Clip Studio Paint. Rickrack can run normally on operating systems such as Windows, Linux, and macOS.
-[:rocket: v2.8.27 Update Notes](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.27)
+[:rocket: v2.8.35 Update Notes](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.35)
[:house: Rickrack](https://eigenmiao.com/rickrack)
@@ -24,7 +24,7 @@ Rickrack (**R**e**a**l-t**i**me **C**olor **K**it) is a free and user-friendly c
焰火十二卷(实时色彩工具箱)是一款免费且实用的色彩编辑器。它可以帮助你从色轮或者其他地方生成一组和谐的色彩。你可以将这些色彩分享给其他人,或者应用到你自己的创作当中。此外,你也可以将色彩组或者色库导出为单独的色彩文档并导入其他软件中(如 Adobe Photoshop、GIMP、Krita、Pencil 2D 以及优动漫 Paint 等)。焰火十二卷可以在 Windows、Linux、macOS 等操作系统上正常运行。
-[:rocket: v2.8.27 更新说明](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.27)
+[:rocket: v2.8.35 更新说明](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.35)
[:house: 焰火十二卷](https://eigenmiao.com/yanhuo)
@@ -62,6 +62,7 @@ Rickrack (**R**e**a**l-t**i**me **C**olor **K**it) is a free and user-friendly c
* [License for Rickrack](#license-for-rickrack)
* [License for Required Packages](#license-for-required-packages)
* [More Information](#more-information)
+* [Contributing](#contributing)
* [Acknowledgment](#acknowledgment)
# Introduction Translations
@@ -195,7 +196,7 @@ Support the continuous development of Rickrack!
# Installation
## Current Release
-The latest preview version is [v2.8.27](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.27).
+The latest preview version is [v2.8.35](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.35).
## Install Software
### Recommend: Install on Windows 10 or 11 via WinGet tool
@@ -204,7 +205,7 @@ winget install rickrack
```
## Install on other platforms
-Download Software from [Github](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.27) or [Sourceforge](https://sourceforge.net/projects/rickrack/files/v2.8.27/). The installation steps are presented in [tutorials](https://eigenmiao.com/2021/12/12/rickrack-tutorial-en-v2.3.4/#Installation).
+Download Software from [Github](https://github.com/eigenmiao/Rickrack/releases/tag/v2.8.35) or [Sourceforge](https://sourceforge.net/projects/rickrack/files/v2.8.35/). The installation steps are presented in [tutorials](https://eigenmiao.com/2021/12/12/rickrack-tutorial-en-v2.3.4/#Installation).
Here is a [video tutorial](https://www.bilibili.com/video/BV17r4y1L7R6/).
@@ -277,7 +278,7 @@ pip install rickrack
rickrack -h
# Run Rickrack.
-rickrack
+rickrack -d .
```
## How to Build the Module
@@ -305,7 +306,7 @@ Rickrack is a free software, which is distributed in the hope that it will be us
All images, documents and translations in Rickrack [code repository](https://github.com/eigenmiao/Rickrack) are licensed under [Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) unless stating additionally.
-Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL).
+Rickrack default uses [Noto Sans](https://fonts.google.com/noto) font family for interface display. These fonts are open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL). Rickrack only carries basic fonts. All fonts can be downloaded here: [all fonts](https://fonts.google.com/noto/fonts).
## License for Required Packages
| Package | Version | License |
@@ -320,7 +321,7 @@ Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for
| Pillow | 8.4.0 | HPND |
| pip | 21.3.1 | MIT |
| PyInstaller | 3.4 | GPLv2 or Later |
-| PyQt5 | 5.12.1 | GPLv3 |
+| PyQt5 | 5.15.6 | GPLv3 |
| PyQt5_sip | 4.19.19 | SIP |
| pywin32 | 302 | PSF |
| pywin32-ctypes | 0.2.0 | BSD |
@@ -343,49 +344,15 @@ Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for
# Contributing
-This project welcomes contributions of all types. If you want to contribute code (new features, or bug fixes) to this project, please contact me first. Thanks.
+Welcome to participate in community discussions, report bugs and submit feature-requests, but it is not recommended to contribute code to this project.
# Acknowledgment
-## Reviews
-
-
-## Translators
-
-
-## Feature Implementation & Bug Fix
-
+## Reviewers
+[TJ FREE@Youtube](https://www.youtube.com/watch?v=OUnktTCtv3E), [Robert Condorache@Softpedia](https://www.softpedia.com/get/Multimedia/Graphic/Graphic-Others/RickRack.shtml)
## Software Dependency
-
+[Vedantmgoyal2009@Github](https://github.com/vedantmgoyal2009), [Dependabot@Github](https://github.com/apps/dependabot)
diff --git a/SECURITY.md b/SECURITY.md
index dd608b2..8066cef 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,7 +4,8 @@ These versions of Rickrack are currently being supported with security updates.
| Version | Supported |
| --------------------- | ------------------ |
-| v2.8.27-x2d3s3-pre | :white_check_mark: |
+| v2.8.35-x3d3s3-pre | :white_check_mark: |
+| v2.8.27-x2d3s3-pre | :x: |
| v2.8.5-x2d3s3-pre | :x: |
| v2.7.26-x2d3s3-stable | :white_check_mark: |
| v2.7.25-x2d3s3-stable | :x: |
diff --git a/demo/00_usage/README.md b/demo/00_usage/README.md
index 4988e6d..031ac30 100644
--- a/demo/00_usage/README.md
+++ b/demo/00_usage/README.md
@@ -8,7 +8,7 @@ Rickrack is a free software, which is distributed in the hope that it will be us
All images, documents and translations in Rickrack [code repository](https://github.com/eigenmiao/Rickrack) are licensed under [Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) unless stating additionally.
-Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL).
+Rickrack default uses [Noto Sans](https://fonts.google.com/noto) font family for interface display. These fonts are open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL). Rickrack only carries basic fonts. All fonts can be downloaded here: [all fonts](https://fonts.google.com/noto/fonts).
Please visit https://github.com/eigenmiao/Rickrack for more infomation about Rickrack.
diff --git a/demo/01_color_sets/README.md b/demo/01_color_sets/README.md
index 8508e6d..dd87438 100644
--- a/demo/01_color_sets/README.md
+++ b/demo/01_color_sets/README.md
@@ -14,7 +14,7 @@ Rickrack is a free software, which is distributed in the hope that it will be us
All images, documents and translations in Rickrack [code repository](https://github.com/eigenmiao/Rickrack) are licensed under [Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) unless stating additionally.
-Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL).
+Rickrack default uses [Noto Sans](https://fonts.google.com/noto) font family for interface display. These fonts are open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL). Rickrack only carries basic fonts. All fonts can be downloaded here: [all fonts](https://fonts.google.com/noto/fonts).
Please visit https://github.com/eigenmiao/Rickrack for more infomation about Rickrack.
diff --git a/demo/02_color_palettes/README.md b/demo/02_color_palettes/README.md
index b2f0705..59ace95 100644
--- a/demo/02_color_palettes/README.md
+++ b/demo/02_color_palettes/README.md
@@ -17,7 +17,7 @@ Rickrack is a free software, which is distributed in the hope that it will be us
All images, documents and translations in Rickrack [code repository](https://github.com/eigenmiao/Rickrack) are licensed under [Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) unless stating additionally.
-Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL).
+Rickrack default uses [Noto Sans](https://fonts.google.com/noto) font family for interface display. These fonts are open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL). Rickrack only carries basic fonts. All fonts can be downloaded here: [all fonts](https://fonts.google.com/noto/fonts).
Please visit https://github.com/eigenmiao/Rickrack for more infomation about Rickrack.
diff --git a/demo/03_plot_scripts/README.md b/demo/03_plot_scripts/README.md
index 94b2475..0afebae 100644
--- a/demo/03_plot_scripts/README.md
+++ b/demo/03_plot_scripts/README.md
@@ -27,7 +27,7 @@ Rickrack is a free software, which is distributed in the hope that it will be us
All images, documents and translations in Rickrack [code repository](https://github.com/eigenmiao/Rickrack) are licensed under [Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) unless stating additionally.
-Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL).
+Rickrack default uses [Noto Sans](https://fonts.google.com/noto) font family for interface display. These fonts are open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL). Rickrack only carries basic fonts. All fonts can be downloaded here: [all fonts](https://fonts.google.com/noto/fonts).
Please visit https://github.com/eigenmiao/Rickrack for more infomation about Rickrack.
diff --git a/demo/README.md b/demo/README.md
index eac0b03..7211182 100644
--- a/demo/README.md
+++ b/demo/README.md
@@ -14,7 +14,7 @@ Rickrack is a free software, which is distributed in the hope that it will be us
All images, documents and translations in Rickrack [code repository](https://github.com/eigenmiao/Rickrack) are licensed under [Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) unless stating additionally.
-Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL).
+Rickrack default uses [Noto Sans](https://fonts.google.com/noto) font family for interface display. These fonts are open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL). Rickrack only carries basic fonts. All fonts can be downloaded here: [all fonts](https://fonts.google.com/noto/fonts).
Please visit https://github.com/eigenmiao/Rickrack for more infomation about Rickrack.
diff --git a/rickrack/rickrack.py b/rickrack/rickrack.py
index 55faa3a..8d602d8 100644
--- a/rickrack/rickrack.py
+++ b/rickrack/rickrack.py
@@ -17,7 +17,7 @@
"""
__VERSION__ = """
-v2.8.27-x2d3s3-pre
+v2.8.35-x3d3s3-pre
"""
__AUTHOR__ = """
@@ -25,7 +25,7 @@
"""
__DATE__ = """
-June 25, 2023
+July 16, 2023
"""
__HELP__ = """
@@ -796,7 +796,7 @@ def run(self, dp_argv={}, dp_proj=""):
dirname, basename = None, None
else:
- dirname, basename = None, None
+ dirname, basename = para_dir(".")
if not dirname or not basename:
dirname, basename = para_dir(os.path.abspath(os.path.dirname(__file__)))
diff --git a/setup.py b/setup.py
index 3847e41..9e86a45 100644
--- a/setup.py
+++ b/setup.py
@@ -18,7 +18,7 @@
setup(
name="Rickrack",
- version="2.8.27",
+ version="2.8.35",
author="Eigenmiao",
author_email="eigenmiao@outlook.com",
description="Generate harmonious colors freely.",
diff --git a/src/build/settings/base.json b/src/build/settings/base.json
index c8450c0..5e2c767 100644
--- a/src/build/settings/base.json
+++ b/src/build/settings/base.json
@@ -2,5 +2,5 @@
"app_name": "Rickrack",
"author": "Eigenmiao",
"main_module": "src/main/python/main.py",
- "version": "2.8.27"
+ "version": "2.8.35"
}
\ No newline at end of file
diff --git a/src/main/icons/README.md b/src/main/icons/README.md
index 2086552..e99c627 100644
--- a/src/main/icons/README.md
+++ b/src/main/icons/README.md
@@ -8,7 +8,7 @@ Rickrack is a free software, which is distributed in the hope that it will be us
All images, documents and translations in Rickrack [code repository](https://github.com/eigenmiao/Rickrack) are licensed under [Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/) unless stating additionally.
-Rickrack default uses [LXGW WenKai](https://github.com/lxgw/LxgwWenKai) font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL).
+Rickrack default uses [Noto Sans](https://fonts.google.com/noto) font family for interface display. These fonts are open-sourced under [SIL Open Font License 1.1](http://scripts.sil.org/OFL). Rickrack only carries basic fonts. All fonts can be downloaded here: [all fonts](https://fonts.google.com/noto/fonts).
Please visit https://github.com/eigenmiao/Rickrack for more infomation about Rickrack.
diff --git a/src/main/python/cguis/design/box_dialog.py b/src/main/python/cguis/design/box_dialog.py
index e9740c8..50b2910 100644
--- a/src/main/python/cguis/design/box_dialog.py
+++ b/src/main/python/cguis/design/box_dialog.py
@@ -69,7 +69,6 @@ def setupUi(self, BoxDialog):
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Reset)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 5, 0, 1, 4)
-
self.retranslateUi(BoxDialog)
self.buttonBox.accepted.connect(BoxDialog.accept)
self.buttonBox.rejected.connect(BoxDialog.reject)
@@ -81,5 +80,3 @@ def retranslateUi(self, BoxDialog):
self.name_label.setText(_translate("BoxDialog", "Name:"))
self.hec_label.setText(_translate("BoxDialog", "Color:"))
self.index_label.setText(_translate("BoxDialog", "Index:"))
-
-
diff --git a/src/main/python/cguis/design/info_dialog.py b/src/main/python/cguis/design/info_dialog.py
index e3150cd..66b8b8d 100644
--- a/src/main/python/cguis/design/info_dialog.py
+++ b/src/main/python/cguis/design/info_dialog.py
@@ -76,7 +76,6 @@ def setupUi(self, InfoDialog):
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Reset)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 6, 0, 1, 4)
-
self.retranslateUi(InfoDialog)
self.buttonBox.accepted.connect(InfoDialog.accept)
self.buttonBox.rejected.connect(InfoDialog.reject)
@@ -89,5 +88,3 @@ def retranslateUi(self, InfoDialog):
self.rule_label.setText(_translate("InfoDialog", "Rule:"))
self.time_label.setText(_translate("InfoDialog", "Time:"))
self.desc_label.setText(_translate("InfoDialog", "Description"))
-
-
diff --git a/src/main/python/cguis/design/main_window.py b/src/main/python/cguis/design/main_window.py
index 9264e23..f2af720 100644
--- a/src/main/python/cguis/design/main_window.py
+++ b/src/main/python/cguis/design/main_window.py
@@ -12,7 +12,7 @@
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
- MainWindow.resize(900, 640)
+ MainWindow.resize(1200, 860)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
@@ -29,7 +29,7 @@ def setupUi(self, MainWindow):
self.central_widget.setObjectName("central_widget")
MainWindow.setCentralWidget(self.central_widget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
- self.menubar.setGeometry(QtCore.QRect(0, 0, 900, 18))
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 1200, 18))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
@@ -41,6 +41,8 @@ def setupUi(self, MainWindow):
self.menuHelp.setObjectName("menuHelp")
self.menuView = QtWidgets.QMenu(self.menubar)
self.menuView.setObjectName("menuView")
+ self.menuLayout = QtWidgets.QMenu(self.menubar)
+ self.menuLayout.setObjectName("menuLayout")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
@@ -202,6 +204,20 @@ def setupUi(self, MainWindow):
self.actionSaveImage.setObjectName("actionSaveImage")
self.actionDirectQuit = QtWidgets.QAction(MainWindow)
self.actionDirectQuit.setObjectName("actionDirectQuit")
+ self.actionInspired_L = QtWidgets.QAction(MainWindow)
+ self.actionInspired_L.setObjectName("actionInspired_L")
+ self.actionSpecific_L = QtWidgets.QAction(MainWindow)
+ self.actionSpecific_L.setObjectName("actionSpecific_L")
+ self.actionConcise_L = QtWidgets.QAction(MainWindow)
+ self.actionConcise_L.setObjectName("actionConcise_L")
+ self.actionInspired_R = QtWidgets.QAction(MainWindow)
+ self.actionInspired_R.setObjectName("actionInspired_R")
+ self.actionSpecific_R = QtWidgets.QAction(MainWindow)
+ self.actionSpecific_R.setObjectName("actionSpecific_R")
+ self.actionConcise_R = QtWidgets.QAction(MainWindow)
+ self.actionConcise_R.setObjectName("actionConcise_R")
+ self.actionForum = QtWidgets.QAction(MainWindow)
+ self.actionForum.setObjectName("actionForum")
self.menuFile.addAction(self.actionImport)
self.menuFile.addAction(self.actionExport)
self.menuFile.addSeparator()
@@ -232,17 +248,25 @@ def setupUi(self, MainWindow):
self.menuHelp.addAction(self.actionUpdate)
self.menuHelp.addAction(self.actionAbout)
self.menuHelp.addSeparator()
+ self.menuHelp.addAction(self.actionForum)
self.menuHelp.addAction(self.actionInfo)
self.menuView.addAction(self.actionWheel)
self.menuView.addAction(self.actionImage)
self.menuView.addAction(self.actionBoard)
self.menuView.addAction(self.actionDepot)
+ self.menuLayout.addAction(self.actionInspired_L)
+ self.menuLayout.addAction(self.actionSpecific_L)
+ self.menuLayout.addAction(self.actionConcise_L)
+ self.menuLayout.addSeparator()
+ self.menuLayout.addAction(self.actionInspired_R)
+ self.menuLayout.addAction(self.actionSpecific_R)
+ self.menuLayout.addAction(self.actionConcise_R)
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuEdit.menuAction())
self.menubar.addAction(self.menuView.menuAction())
+ self.menubar.addAction(self.menuLayout.menuAction())
self.menubar.addAction(self.menuWindow.menuAction())
self.menubar.addAction(self.menuHelp.menuAction())
-
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
@@ -253,6 +277,7 @@ def retranslateUi(self, MainWindow):
self.menuWindow.setTitle(_translate("MainWindow", "Window"))
self.menuHelp.setTitle(_translate("MainWindow", "Help"))
self.menuView.setTitle(_translate("MainWindow", "View"))
+ self.menuLayout.setTitle(_translate("MainWindow", "Layout"))
self.result_dock_widget.setToolTip(_translate("MainWindow", "Result."))
self.result_dock_widget.setStatusTip(_translate("MainWindow", "Result."))
self.result_dock_widget.setWindowTitle(_translate("MainWindow", "Result"))
@@ -333,5 +358,17 @@ def retranslateUi(self, MainWindow):
self.actionSaveImage.setStatusTip(_translate("MainWindow", "Save Image."))
self.actionDirectQuit.setText(_translate("MainWindow", "Direct Quit"))
self.actionDirectQuit.setStatusTip(_translate("MainWindow", "Direct Quit."))
-
-
+ self.actionInspired_L.setText(_translate("MainWindow", "Inspired"))
+ self.actionInspired_L.setStatusTip(_translate("MainWindow", "Inspired."))
+ self.actionSpecific_L.setText(_translate("MainWindow", "Specific"))
+ self.actionSpecific_L.setStatusTip(_translate("MainWindow", "Specific."))
+ self.actionConcise_L.setText(_translate("MainWindow", "Concise"))
+ self.actionConcise_L.setStatusTip(_translate("MainWindow", "Concise."))
+ self.actionInspired_R.setText(_translate("MainWindow", "Inspired (R)"))
+ self.actionInspired_R.setStatusTip(_translate("MainWindow", "Inspired (R)."))
+ self.actionSpecific_R.setText(_translate("MainWindow", "Specific (R)"))
+ self.actionSpecific_R.setStatusTip(_translate("MainWindow", "Specific (R)."))
+ self.actionConcise_R.setText(_translate("MainWindow", "Concise (R)"))
+ self.actionConcise_R.setStatusTip(_translate("MainWindow", "Concise (R)."))
+ self.actionForum.setText(_translate("MainWindow", "Forum"))
+ self.actionForum.setStatusTip(_translate("MainWindow", "Forum."))
diff --git a/src/main/python/cguis/design/scroll_cube.py b/src/main/python/cguis/design/scroll_cube.py
index 39d3e4c..e67e41e 100644
--- a/src/main/python/cguis/design/scroll_cube.py
+++ b/src/main/python/cguis/design/scroll_cube.py
@@ -21,7 +21,7 @@ def setupUi(self, ScrollCube):
ScrollCube.setBaseSize(QtCore.QSize(0, 0))
ScrollCube.setWindowTitle("Form")
self.gridLayout = QtWidgets.QGridLayout(ScrollCube)
- self.gridLayout.setContentsMargins(10, 10, 10, 10)
+ self.gridLayout.setContentsMargins(9, 0, 9, 0)
self.gridLayout.setSpacing(8)
self.gridLayout.setObjectName("gridLayout")
self.sharp = QtWidgets.QLabel(ScrollCube)
@@ -187,11 +187,8 @@ def setupUi(self, ScrollCube):
self.dp_hsv_v.setObjectName("dp_hsv_v")
self.gbox_hsv_grid_layout.addWidget(self.dp_hsv_v, 2, 2, 1, 1)
self.gridLayout.addWidget(self.gbox_hsv, 3, 0, 1, 4)
-
self.retranslateUi(ScrollCube)
QtCore.QMetaObject.connectSlotsByName(ScrollCube)
def retranslateUi(self, ScrollCube):
pass
-
-
diff --git a/src/main/python/cguis/design/settings_dialog.py b/src/main/python/cguis/design/settings_dialog.py
index d556cb0..1760e8e 100644
--- a/src/main/python/cguis/design/settings_dialog.py
+++ b/src/main/python/cguis/design/settings_dialog.py
@@ -900,7 +900,6 @@ def setupUi(self, SettingsDialog):
self.gridLayout_9.addWidget(self.shortcuts_scroll_area, 0, 0, 1, 1)
self.setti_items.addTab(self.setti_shortcuts, "")
self.gridLayout.addWidget(self.setti_items, 0, 0, 1, 1)
-
self.retranslateUi(SettingsDialog)
self.setti_items.setCurrentIndex(0)
self.buttonBox.accepted.connect(SettingsDialog.accept)
@@ -985,5 +984,3 @@ def retranslateUi(self, SettingsDialog):
self.lst_prefix_label.setText(_translate("SettingsDialog", "lst prefix"))
self.setti_items.setTabText(self.setti_items.indexOf(self.setti_system), _translate("SettingsDialog", "System"))
self.setti_items.setTabText(self.setti_items.indexOf(self.setti_shortcuts), _translate("SettingsDialog", "Shortcuts"))
-
-
diff --git a/src/main/python/cguis/resource/view_rc.py b/src/main/python/cguis/resource/view_rc.py
index 0d55b6e..7b4f14d 100644
--- a/src/main/python/cguis/resource/view_rc.py
+++ b/src/main/python/cguis/resource/view_rc.py
@@ -99179,5 +99179,4 @@ def qInitResources():
def qCleanupResources():
QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
-
qInitResources()
diff --git a/src/main/python/clibs/image3c.py b/src/main/python/clibs/image3c.py
index 3d68ba9..a55639a 100644
--- a/src/main/python/clibs/image3c.py
+++ b/src/main/python/clibs/image3c.py
@@ -23,37 +23,6 @@
class Image3C(QThread):
- """
- Image transformations.
-
- Graph categories (finished signals):
- 0: normal rgb data;
- 1: vertical rgb space edge data;
- 2: horizontal rgb space edge data;
- 3: final rgb space edge data;
- 4: normal hsv data;
- 5: vertical hsv space edge data;
- 6: horizontal hsv space edge data;
- 7: final hsv space edge data.
-
- Graph channels:
- 0: rgb or hsv full data.
- 1: r or h channel data;
- 2: g or s channel data;
- 3: b or v channel data;
- 4: not r or h channel data;
- 5: not g or s channel data;
- 6: not b or v channel data.
-
- Extract types:
- 0: bright colorful
- 1: light colorful
- 2: dark colorful
- 3: bright
- 4: light
- 5: dark
- """
-
ps_proceses = pyqtSignal(int)
ps_describe = pyqtSignal(int)
ps_finished = pyqtSignal(int)
@@ -61,27 +30,17 @@ class Image3C(QThread):
ps_extracts = pyqtSignal(list)
def __init__(self, temp_dir):
- """
- Init image3c with default temp dir.
- """
-
super().__init__()
-
- # load args.
self._temp_dir = temp_dir
-
self.img_data = None
self.display = None
-
self.rgb_data = None
self.hsv_data = None
self.run_args = None
self.run_category = None
-
self.ori_display_data = None
self.res_display_data = None
self.rev_display_data = None
-
self._rgb_ext_data = None
self._hsv_ext_data = None
self._rgb_vtl_data = None
@@ -89,26 +48,15 @@ def __init__(self, temp_dir):
self._hsv_vtl_data = None
self._hsv_hrz_data = None
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def run(self):
- """
- Start running in thread.
- """
-
if isinstance(self.run_category, int):
func = getattr(self, "run_{}".format(self.run_category))
func((0, 100))
-
else:
func = getattr(self, "run_{}".format(self.run_category))
func((0, 100), self.run_args)
def run_rgb_extend(self):
- """
- Extend rgb data into extended rgb data for Sobel edge detection.
- """
-
if not isinstance(self._rgb_ext_data, np.ndarray):
self._rgb_ext_data = np.insert(self.rgb_data, 0, self.rgb_data[1, :], axis=0)
self._rgb_ext_data = np.insert(self._rgb_ext_data, self._rgb_ext_data.shape[0], self._rgb_ext_data[self._rgb_ext_data.shape[0] - 2, :], axis=0)
@@ -116,10 +64,6 @@ def run_rgb_extend(self):
self._rgb_ext_data = np.insert(self._rgb_ext_data, self._rgb_ext_data.shape[1], self._rgb_ext_data[:, self._rgb_ext_data.shape[1] - 2], axis=1)
def run_hsv_extend(self):
- """
- Extend rgb data into extended rgb data for Sobel edge detection.
- """
-
if not isinstance(self._hsv_ext_data, np.ndarray):
self._hsv_ext_data = np.insert(self.hsv_data, 0, self.hsv_data[1, :], axis=0)
self._hsv_ext_data = np.insert(self._hsv_ext_data, self._hsv_ext_data.shape[0], self._hsv_ext_data[self._hsv_ext_data.shape[0] - 2, :], axis=0)
@@ -127,215 +71,125 @@ def run_hsv_extend(self):
self._hsv_ext_data = np.insert(self._hsv_ext_data, self._hsv_ext_data.shape[1], self._hsv_ext_data[:, self._hsv_ext_data.shape[1] - 2], axis=1)
def run_init(self, process_scope, script=""):
- """
- Run pre init data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- script (str): (str): BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE, EMBOSS, FIND_EDGES, SHARPEN, SMOOTH, SMOOTH_MORE.
- """
-
if isinstance(script, tuple) and script[0] in ("BLUR", "CONTOUR", "DETAIL", "EDGE_ENHANCE", "EDGE_ENHANCE_MORE", "EMBOSS", "FIND_EDGES", "SHARPEN", "SMOOTH", "SMOOTH_MORE"):
self.ps_describe.emit(17)
self.ps_proceses.emit(int(process_scope[0]))
-
self.img_data = self.img_data.filter(getattr(ImageFilter, script[0]))
-
elif isinstance(script, tuple) and script[0] == "ZOOM":
self.ps_describe.emit(17)
self.ps_proceses.emit(int(process_scope[0]))
-
ratio = max(5.0 / self.img_data.size[0], 5.0 / self.img_data.size[1], script[1])
-
if ratio != 1.0:
self.img_data = self.img_data.resize((int(round(self.img_data.size[0] * ratio)), int(round(self.img_data.size[1] * ratio))), Image.ANTIALIAS)
-
elif isinstance(script, tuple) and script[0] == "CROP":
self.ps_describe.emit(17)
self.ps_proceses.emit(int(process_scope[0]))
-
if script[1] != (0.0, 0.0, 1.0, 1.0):
self.img_data = self.img_data.crop((int(round(script[1][0] * self.img_data.size[0])), int(round(script[1][1] * self.img_data.size[1])), int(round(script[1][2] * self.img_data.size[0])), int(round(script[1][3] * self.img_data.size[1]))))
-
else:
self.ps_describe.emit(1)
self.ps_proceses.emit(int(process_scope[0]))
-
ratio = max(5.0 / self.img_data.size[0], 5.0 / self.img_data.size[1])
-
if ratio > 1.0:
self.img_data = self.img_data.resize((int(self.img_data.size[0] * ratio), int(self.img_data.size[1] * ratio)), Image.ANTIALIAS)
-
self.ps_proceses.emit(int(process_scope[0] + process_scope[1] * 0.60))
self.rgb_data = np.array(self.img_data.convert("RGB"), dtype=np.uint8)
-
self.ps_proceses.emit(int(process_scope[0] + process_scope[1] * 0.80))
self.save_rgb_full_data(self.rgb_data, 0)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(process_scope[0] + process_scope[1]))
def run_0(self, process_scope):
- """
- Run normal rgb data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self.rgb_data, np.ndarray):
self.run_init((process_scope[0], process_scope[1] * 0.40))
pro_scope = (process_scope[0] + process_scope[1] * 0.40, process_scope[1] * 0.60)
-
else:
pro_scope = tuple(process_scope)
-
- # generating rgb data.
self.ps_describe.emit(2)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.60))
self.save_rgb_chnl_data(self.rgb_data, 0)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
def run_4(self, process_scope):
- """
- Run normal hsv data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self.rgb_data, np.ndarray):
self.run_0((process_scope[0], process_scope[1] * 0.20))
pro_scope = (process_scope[0] + process_scope[1] * 0.20, process_scope[1] * 0.80)
-
else:
pro_scope = tuple(process_scope)
-
- # generating hsv data.
self.ps_describe.emit(3)
self.ps_proceses.emit(int(pro_scope[0]))
-
self.hsv_data = Color.rgb2hsv_array(self.rgb_data)
-
self.ps_describe.emit(4)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.60))
self.save_hsv_chnl_data(self.hsv_data, 4)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
def run_1(self, process_scope):
- """
- Run vertical rgb space edge data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self.rgb_data, np.ndarray):
self.run_0((process_scope[0], process_scope[1] * 0.35))
pro_scope = (process_scope[0] + process_scope[1] * 0.35, process_scope[1] * 0.65)
-
else:
pro_scope = tuple(process_scope)
-
- # get extended rgb data.
self.run_rgb_extend()
-
self.ps_describe.emit(5)
self.ps_proceses.emit(int(pro_scope[0]))
self._rgb_vtl_data = np.zeros((self.rgb_data.shape[0], self.rgb_data.shape[1], 3), dtype=np.uint8)
-
- # generating rgb vertical edge data.
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.40))
for i in range(self.rgb_data.shape[0]):
for j in range(self.rgb_data.shape[1]):
rgb_result = self._rgb_ext_data[i:i + 3, j:j + 3, :] * [[[-1, -1, -1], [0, 0, 0], [1, 1, 1]], [[-2, -2, -2], [0, 0, 0], [2, 2, 2]], [[-1, -1, -1], [0, 0, 0], [1, 1, 1]]]
rgb_result = rgb_result.sum(axis=(0, 1)) / 4
-
self._rgb_vtl_data[i][j] = np.abs(rgb_result).astype(np.uint8)
-
self.ps_describe.emit(6)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.80))
self.save_rgb_full_data(self._rgb_vtl_data, 1)
self.save_rgb_chnl_data(self._rgb_vtl_data, 1)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
def run_2(self, process_scope):
- """
- Run horizontal rgb space edge data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self.rgb_data, np.ndarray):
self.run_0((process_scope[0], process_scope[1] * 0.35))
pro_scope = (process_scope[0] + process_scope[1] * 0.35, process_scope[1] * 0.65)
-
else:
pro_scope = tuple(process_scope)
-
- # get extended rgb data.
self.run_rgb_extend()
-
self.ps_describe.emit(7)
self.ps_proceses.emit(int(pro_scope[0]))
self._rgb_hrz_data = np.zeros((self.rgb_data.shape[0], self.rgb_data.shape[1], 3), dtype=np.uint8)
-
- # generating rgb horizontal edge data.
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.40))
for i in range(self.rgb_data.shape[0]):
for j in range(self.rgb_data.shape[1]):
rgb_result = self._rgb_ext_data[i:i + 3, j:j + 3, :] * [[[-1, -1, -1], [-2, -2, -2], [-1, -1, -1]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[1, 1, 1], [2, 2, 2], [1, 1, 1]]]
rgb_result = rgb_result.sum(axis=(0, 1)) / 4
-
self._rgb_hrz_data[i][j] = np.abs(rgb_result).astype(np.uint8)
-
self.ps_describe.emit(8)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.80))
self.save_rgb_full_data(self._rgb_hrz_data, 2)
self.save_rgb_chnl_data(self._rgb_hrz_data, 2)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
def run_3(self, process_scope):
- """
- Run final rgb space edge data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self._rgb_vtl_data, np.ndarray):
self.run_1((process_scope[0], process_scope[1] * 0.60))
pro_scope = (process_scope[0] + process_scope[1] * 0.60, process_scope[1] * 0.40)
-
else:
pro_scope = tuple(process_scope)
-
if not isinstance(self._rgb_hrz_data, np.ndarray):
self.run_2((pro_scope[0], pro_scope[1] * 0.50))
pro_scope = (pro_scope[0] + pro_scope[1] * 0.50, pro_scope[1] * 0.50)
-
else:
pro_scope = tuple(pro_scope)
-
- # generating rgb final edge data.
self.ps_describe.emit(9)
self.ps_proceses.emit(int(pro_scope[0]))
fnl_results = (np.sqrt(self._rgb_vtl_data.astype(np.uint32) ** 2 + self._rgb_hrz_data.astype(np.uint32) ** 2) / np.sqrt(2)).astype(np.uint8)
-
self.ps_describe.emit(10)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.80))
self.save_rgb_full_data(fnl_results, 3)
self.save_rgb_chnl_data(fnl_results, 3)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
self._rgb_ext_data = None
@@ -343,28 +197,15 @@ def run_3(self, process_scope):
self._rgb_hrz_data = None
def run_5(self, process_scope):
- """
- Run vertical hsv space edge data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self.hsv_data, np.ndarray):
self.run_4((process_scope[0], process_scope[1] * 0.35))
pro_scope = (process_scope[0] + process_scope[1] * 0.35, process_scope[1] * 0.65)
-
else:
pro_scope = tuple(process_scope)
-
- # get extended hsv data.
self.run_hsv_extend()
-
self.ps_describe.emit(11)
self.ps_proceses.emit(int(pro_scope[0]))
self._hsv_vtl_data = np.zeros((self.hsv_data.shape[0], self.hsv_data.shape[1], 3), dtype=np.uint8)
-
- # generating hsv vertical edge data.
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.40))
for i in range(self.hsv_data.shape[0]):
for j in range(self.hsv_data.shape[1]):
@@ -375,43 +216,26 @@ def run_5(self, process_scope):
h_result_1 = 360.0 - h_result_1 if h_result_1 > 180.0 else h_result_1
h_result_2 = 360.0 - h_result_2 if h_result_2 > 180.0 else h_result_2
h_result = h_result_0 + h_result_1 * 2 + h_result_2
-
sv_result = self._hsv_ext_data[i:i + 3, j:j + 3, 1:3] * [[[-1, -1], [0, 0], [1, 1]], [[-2, -2], [0, 0], [2, 2]], [[-1, -1], [0, 0], [1, 1]]]
sv_result = sv_result.sum(axis=(0, 1)).astype(np.float32)
-
self._hsv_vtl_data[i][j] = np.array((h_result * 0.3542, abs(sv_result[0]) * 63.75, abs(sv_result[1]) * 63.75), dtype=np.uint8)
-
self.ps_describe.emit(12)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.80))
self.save_rgb_full_data(self._hsv_vtl_data, 5)
self.save_rgb_chnl_data(self._hsv_vtl_data, 5)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
def run_6(self, process_scope):
- """
- Run horizontal hsv space edge data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self.hsv_data, np.ndarray):
self.run_4((process_scope[0], process_scope[1] * 0.35))
pro_scope = (process_scope[0] + process_scope[1] * 0.35, process_scope[1] * 0.65)
-
else:
pro_scope = tuple(process_scope)
-
- # get extended hsv data.
self.run_hsv_extend()
-
self.ps_describe.emit(13)
self.ps_proceses.emit(int(pro_scope[0]))
self._hsv_hrz_data = np.zeros((self.hsv_data.shape[0], self.hsv_data.shape[1], 3), dtype=np.uint8)
-
- # generating hsv horizontal edge data.
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.40))
for i in range(self.hsv_data.shape[0]):
for j in range(self.hsv_data.shape[1]):
@@ -422,52 +246,34 @@ def run_6(self, process_scope):
h_result_1 = 360.0 - h_result_1 if h_result_1 > 180.0 else h_result_1
h_result_2 = 360.0 - h_result_2 if h_result_2 > 180.0 else h_result_2
h_result = h_result_0 + h_result_1 * 2 + h_result_2
-
sv_result = self._hsv_ext_data[i:i + 3, j:j + 3, 1:3] * [[[-1, -1], [-2, -2], [-1, -1]], [[0, 0], [0, 0], [0, 0]], [[1, 1], [2, 2], [1, 1]]]
sv_result = sv_result.sum(axis=(0, 1)).astype(np.float32)
-
self._hsv_hrz_data[i][j] = np.array((h_result * 0.3542, abs(sv_result[0]) * 63.75, abs(sv_result[1]) * 63.75), dtype=np.uint8)
-
self.ps_describe.emit(14)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.80))
self.save_rgb_full_data(self._hsv_hrz_data, 6)
self.save_rgb_chnl_data(self._hsv_hrz_data, 6)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
def run_7(self, process_scope):
- """
- Run final hsv space edge data.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- """
-
if not isinstance(self._hsv_vtl_data, np.ndarray):
self.run_5((process_scope[0], process_scope[1] * 0.60))
pro_scope = (process_scope[0] + process_scope[1] * 0.60, process_scope[1] * 0.40)
-
else:
pro_scope = tuple(process_scope)
-
if not isinstance(self._hsv_hrz_data, np.ndarray):
self.run_6((pro_scope[0], pro_scope[1] * 0.50))
pro_scope = (pro_scope[0] + pro_scope[1] * 0.50, pro_scope[1] * 0.50)
-
else:
pro_scope = tuple(pro_scope)
-
- # generating rgb final edge data.
self.ps_describe.emit(15)
self.ps_proceses.emit(int(pro_scope[0]))
fnl_results = (np.sqrt(self._hsv_vtl_data.astype(np.uint32) ** 2 + self._hsv_hrz_data.astype(np.uint32) ** 2) / np.sqrt(2)).astype(np.uint8)
-
self.ps_describe.emit(16)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1] * 0.80))
self.save_rgb_full_data(fnl_results, 7)
self.save_rgb_chnl_data(fnl_results, 7)
-
self.ps_describe.emit(0)
self.ps_proceses.emit(int(pro_scope[0] + pro_scope[1]))
self._hsv_ext_data = None
@@ -475,543 +281,328 @@ def run_7(self, process_scope):
self._hsv_hrz_data = None
def save_load_data(self, load_image):
- """
- Save load image from clipboard, etc.
-
- Args:
- load_image (QImage): display image data.
- """
-
i = 0
image_path = self._temp_dir.path() + os.sep + "load_{}.png"
while os.path.isfile(image_path.format(i)):
i += 1
-
image_path = image_path.format(i)
-
try:
load_image.save(image_path)
-
except Exception as err:
return None
-
if os.path.isfile(image_path):
return image_path
-
else:
return None
def save_rgb_full_data(self, rgb_data, prefix):
- """
- Save rgb full channel image (0_0.png for category 0 and 4 and channel 0).
-
- Args:
- rgb_data (3D array): rgb image array.
- prefix (int): graph category as image name prefix.
- """
-
rgb = QImage(rgb_data, rgb_data.shape[1], rgb_data.shape[0], rgb_data.shape[1] * 3, QImage.Format_RGB888)
rgb.save(self._temp_dir.path() + os.sep + "{}_0.png".format(prefix))
-
if prefix == 0:
self.ps_finished.emit(0)
self.ps_finished.emit(40)
-
else:
self.ps_finished.emit(prefix * 10)
def save_rgb_chnl_data(self, rgb_data, prefix):
- """
- Save r, g, b, not r, not g and not b channel images separately.
-
- Args:
- rgb_data (3D array): rgb image array.
- prefix (int): graph category as image name prefix.
- """
-
z_chl = np.zeros((rgb_data.shape[0], rgb_data.shape[1]), dtype=np.uint8)
-
r_chl = np.stack((rgb_data[:, :, 0], z_chl, z_chl), axis=2)
r_chl = QImage(r_chl, r_chl.shape[1], r_chl.shape[0], r_chl.shape[1] * 3, QImage.Format_RGB888)
r_chl.save(self._temp_dir.path() + os.sep + "{}_1.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 1)
-
g_chl = np.stack((z_chl, rgb_data[:, :, 1], z_chl), axis=2)
g_chl = QImage(g_chl, g_chl.shape[1], g_chl.shape[0], g_chl.shape[1] * 3, QImage.Format_RGB888)
g_chl.save(self._temp_dir.path() + os.sep + "{}_2.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 2)
-
b_chl = np.stack((z_chl, z_chl, rgb_data[:, :, 1]), axis=2)
b_chl = QImage(b_chl, b_chl.shape[1], b_chl.shape[0], b_chl.shape[1] * 3, QImage.Format_RGB888)
b_chl.save(self._temp_dir.path() + os.sep + "{}_3.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 3)
-
n_r_chl = np.stack((z_chl, rgb_data[:, :, 1], rgb_data[:, :, 2]), axis=2)
n_r_chl = QImage(n_r_chl, n_r_chl.shape[1], n_r_chl.shape[0], n_r_chl.shape[1] * 3, QImage.Format_RGB888)
n_r_chl.save(self._temp_dir.path() + os.sep + "{}_4.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 4)
-
n_g_chl = np.stack((rgb_data[:, :, 0], z_chl, rgb_data[:, :, 2]), axis=2)
n_g_chl = QImage(n_g_chl, n_g_chl.shape[1], n_g_chl.shape[0], n_g_chl.shape[1] * 3, QImage.Format_RGB888)
n_g_chl.save(self._temp_dir.path() + os.sep + "{}_5.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 5)
-
n_b_chl = np.stack((rgb_data[:, :, 0], rgb_data[:, :, 1], z_chl), axis=2)
n_b_chl = QImage(n_b_chl, n_b_chl.shape[1], n_b_chl.shape[0], n_b_chl.shape[1] * 3, QImage.Format_RGB888)
n_b_chl.save(self._temp_dir.path() + os.sep + "{}_6.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 6)
def save_hsv_chnl_data(self, hsv_data, prefix):
- """
- Save h, s, v, not h, not s and not v channel images separately.
-
- Args:
- hsv_data (3D array): hsv image array.
- prefix (int): graph category as image name prefix.
- """
-
ones = np.ones(hsv_data.shape[:2])
zeros = np.zeros(hsv_data.shape[:2])
-
h_chl = Color.hsv2rgb_array(np.stack((hsv_data[:, :, 0], ones, ones), axis=2))
h_chl = QImage(h_chl, h_chl.shape[1], h_chl.shape[0], h_chl.shape[1] * 3, QImage.Format_RGB888)
h_chl.save(self._temp_dir.path() + os.sep + "{}_1.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 1)
-
s_chl = Color.hsv2rgb_array(np.stack((zeros, hsv_data[:, :, 1], ones), axis=2))
s_chl = QImage(s_chl, s_chl.shape[1], s_chl.shape[0], s_chl.shape[1] * 3, QImage.Format_RGB888)
s_chl.save(self._temp_dir.path() + os.sep + "{}_2.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 2)
-
v_chl = Color.hsv2rgb_array(np.stack((zeros, ones, hsv_data[:, :, 2]), axis=2))
v_chl = QImage(v_chl, v_chl.shape[1], v_chl.shape[0], v_chl.shape[1] * 3, QImage.Format_RGB888)
v_chl.save(self._temp_dir.path() + os.sep + "{}_3.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 3)
-
n_h_chl = Color.hsv2rgb_array(np.stack((zeros, hsv_data[:, :, 1], hsv_data[:, :, 2]), axis=2))
n_h_chl = QImage(n_h_chl, n_h_chl.shape[1], n_h_chl.shape[0], n_h_chl.shape[1] * 3, QImage.Format_RGB888)
n_h_chl.save(self._temp_dir.path() + os.sep + "{}_4.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 4)
-
n_s_chl = Color.hsv2rgb_array(np.stack((hsv_data[:, :, 0], ones, hsv_data[:, :, 2]), axis=2))
n_s_chl = QImage(n_s_chl, n_s_chl.shape[1], n_s_chl.shape[0], n_s_chl.shape[1] * 3, QImage.Format_RGB888)
n_s_chl.save(self._temp_dir.path() + os.sep + "{}_5.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 5)
-
n_v_chl = Color.hsv2rgb_array(np.stack((hsv_data[:, :, 0], hsv_data[:, :, 1], ones), axis=2))
n_v_chl = QImage(n_v_chl, n_v_chl.shape[1], n_v_chl.shape[0], n_v_chl.shape[1] * 3, QImage.Format_RGB888)
n_v_chl.save(self._temp_dir.path() + os.sep + "{}_6.png".format(prefix))
self.ps_finished.emit(prefix * 10 + 6)
def load_image(self, category, channel):
- """
- Load image with category and channel.
-
- Args:
- category (int): graph category index.
- channel (int): graph channel index.
- """
-
if category in (0, 4) and channel == 0:
img_path = os.sep.join((self._temp_dir.path(), "0_0.png"))
-
else:
img_path = os.sep.join((self._temp_dir.path(), "{}_{}.png".format(category, channel)))
-
if os.path.isfile(img_path):
try:
img_data = Image.open(img_path).convert("RGB")
-
except Exception as err:
img_data = None
-
if img_data:
self.ori_display_data = np.array(img_data, dtype=np.uint8)
self.display = QImage(self.ori_display_data, self.ori_display_data.shape[1], self.ori_display_data.shape[0], self.ori_display_data.shape[1] * 3, QImage.Format_RGB888)
-
self.res_display_data = self.ori_display_data
self.rev_display_data = None
-
else:
self.display = None
self.res_display_data = None
self.rev_display_data = None
-
else:
self.display = None
def run_enhance_rgb(self, process_scope, values):
- """
- Enhance rgb display by factor. Modify r, g or (and) b values to enhance the contrast of image.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (region, separation, factor, reserve).
- """
-
if not isinstance(self.ori_display_data, np.ndarray):
return
-
reg, separ, fact, res, sigma = values
-
if res and isinstance(self.res_display_data, np.ndarray):
display_data = self.res_display_data
-
else:
display_data = np.array(self.ori_display_data, dtype=np.uint8)
-
if isinstance(separ, (int, float)):
separ = [separ,] * len(reg)
-
else:
separ = list(separ)
-
for i in range(len(reg)):
separ[i] = float(separ[i]) * 1.000000392 # 255.0001 / 255.0
separ[i] = 0.0 if separ[i] < 0.0 else separ[i]
separ[i] = 255.0001 if separ[i] > 255.0001 else separ[i]
-
if isinstance(fact, (int, float)):
fact = [fact,] * len(reg)
-
else:
fact = list(fact)
-
for i in range(len(reg)):
fact[i] = float(fact[i])
fact[i] = 0.0 if fact[i] < 0.0 else fact[i]
fact[i] = 1.0 if fact[i] > 1.0 else fact[i]
-
sigma = float(sigma)
sigma = 0.0 if sigma < 0.0 else sigma
sigma = 1.0 if sigma > 1.0 else sigma
-
for k, k_separ, k_fact in zip(reg, separ, fact):
if k_fact == 0.0:
continue
-
data = np.array(display_data[:, :, k], dtype=np.float64)
selection = np.where(data >= k_separ)
-
if sigma == 0.0:
expd = np.zeros(data.shape)
expd[np.where(data == int(k_separ))] = k_fact
-
elif sigma == 1.0:
expd = np.ones(data.shape) * k_fact
-
else:
expd = 0.001 * (10 ** (4.5 * sigma)) * -1
expd = np.exp(((data - k_separ) / 255.0) ** 2 / expd) * k_fact
-
data = data * (1.0 - expd)
data[selection] = data[selection] + expd[selection] * 255.0
-
display_data[:, :, k] = np.array(data, dtype=np.uint8)
-
self.res_display_data = display_data
self.rev_display_data = None
-
self.display = QImage(display_data, display_data.shape[1], display_data.shape[0], display_data.shape[1] * 3, QImage.Format_RGB888)
self.ps_enhanced.emit(1)
def run_enhance_hsv(self, process_scope, values):
- """
- Enhance hsv display by factor. Modify h, s or (and) v values to enhance the contrast of image.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (region, separation, factor, reserve).
- """
-
if not isinstance(self.ori_display_data, np.ndarray):
return
-
reg, separ, fact, res, sigma = values
-
if res and isinstance(self.rev_display_data, np.ndarray):
display_data = self.rev_display_data
-
elif res and isinstance(self.res_display_data, np.ndarray):
display_data = Color.rgb2hsv_array(self.res_display_data)
-
else:
display_data = Color.rgb2hsv_array(self.ori_display_data)
-
if isinstance(separ, (int, float)):
separ = [separ,] * len(reg)
-
else:
separ = list(separ)
-
for i in range(len(reg)):
if reg[i] == 0:
separ[i] = float(separ[i]) * 1.000000278 # 360.0001 / 360.0
separ[i] = 0.0 if separ[i] < 0.0 else separ[i]
separ[i] = 360.0001 if separ[i] > 360.0001 else separ[i]
-
else:
separ[i] = float(separ[i]) * 1.0001
separ[i] = 0.0 if separ[i] < 0.0 else separ[i]
separ[i] = 1.0001 if separ[i] > 1.0001 else separ[i]
-
if isinstance(fact, (int, float)):
fact = [fact,] * len(reg)
-
else:
fact = list(fact)
-
for i in range(len(reg)):
fact[i] = float(fact[i])
fact[i] = 0.0 if fact[i] < 0.0 else fact[i]
fact[i] = 1.0 if fact[i] > 1.0 else fact[i]
-
sigma = float(sigma)
sigma = 0.0 if sigma < 0.0 else sigma
sigma = 1.0 if sigma > 1.0 else sigma
-
for k, k_separ, k_fact in zip(reg, separ, fact):
if k_fact == 0.0:
continue
-
data = np.array(display_data[:, :, k], dtype=np.float64)
-
if k == 0:
data = Color((k_separ, 1.0, 1.0), tp="hsv").ref_h_array(data)
-
if sigma == 0.0:
expd = np.zeros(data.shape)
expd[np.where((data > -1E-5) & (data < 1E-5))] = k_fact
-
elif sigma == 1.0:
expd = np.ones(data.shape) * k_fact
-
else:
expd = 0.001 * (10 ** (4.5 * sigma)) * -1
expd = np.exp((data / 180.0) ** 2 / expd) * k_fact
-
data = data * (1.0 - expd)
-
selection = np.where(data < 0.0)
expd[selection] = expd[selection] * -1
-
data = data + expd * 180.0 + k_separ
-
else:
selection = np.where(data >= k_separ)
-
if sigma == 0.0:
expd = np.zeros(data.shape)
expd[np.where((data - k_separ > -1E-5) & (data - k_separ < 1E-5))] = k_fact
-
elif sigma == 1.0:
expd = np.ones(data.shape) * k_fact
-
else:
expd = 0.001 * (10 ** (4.5 * sigma)) * -1
expd = np.exp((data - k_separ) ** 2 / expd) * k_fact
-
data = data * (1.0 - expd)
data[selection] = data[selection] + expd[selection]
-
display_data[:, :, k] = data
-
self.rev_display_data = display_data
-
display_data = Color.hsv2rgb_array(display_data)
-
self.res_display_data = display_data
-
self.display = QImage(display_data, display_data.shape[1], display_data.shape[0], display_data.shape[1] * 3, QImage.Format_RGB888)
self.ps_enhanced.emit(1)
def run_inverse_rgb(self, process_scope, values):
- """
- Inverse rgb display. Modify r, g or (and) b values to inverse the contrast of image.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (region, reserve).
- """
-
if not isinstance(self.ori_display_data, np.ndarray):
return
-
reg, res = values
-
if res and isinstance(self.res_display_data, np.ndarray):
display_data = self.res_display_data
-
else:
display_data = np.array(self.ori_display_data, dtype=np.uint8)
-
for k in reg:
display_data[:, :, k] = 255 - display_data[:, :, k]
-
self.res_display_data = display_data
self.rev_display_data = None
-
self.display = QImage(display_data, display_data.shape[1], display_data.shape[0], display_data.shape[1] * 3, QImage.Format_RGB888)
self.ps_enhanced.emit(1)
def run_inverse_hsv(self, process_scope, values):
- """
- Inverse hsv display. Modify h, s or (and) v values to inverse the contrast of image.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (region, reserve).
- """
-
if not isinstance(self.ori_display_data, np.ndarray):
return
-
reg, res = values
-
if res and isinstance(self.rev_display_data, np.ndarray):
display_data = self.rev_display_data
-
elif res and isinstance(self.res_display_data, np.ndarray):
display_data = Color.rgb2hsv_array(self.res_display_data)
-
else:
display_data = Color.rgb2hsv_array(self.ori_display_data)
-
for k in reg:
if k == 0:
display_data[:, :, 0] = display_data[:, :, 0] + 180.0
-
else:
display_data[:, :, k] = 1.0 - display_data[:, :, k]
-
self.rev_display_data = display_data
-
display_data = Color.hsv2rgb_array(display_data)
-
self.res_display_data = display_data
-
self.display = QImage(display_data, display_data.shape[1], display_data.shape[0], display_data.shape[1] * 3, QImage.Format_RGB888)
self.ps_enhanced.emit(1)
def run_cover_rgb(self, process_scope, values):
- """
- Cover rgb display. Modify r, g or (and) b values to cover the channel of image.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (region, reserve, path).
- """
-
if not isinstance(self.ori_display_data, np.ndarray):
return
-
reg, res, path = values
-
if res and isinstance(self.res_display_data, np.ndarray):
display_data = self.res_display_data
-
else:
display_data = np.array(self.ori_display_data, dtype=np.uint8)
-
if os.path.isfile(path):
try:
data = Image.open(path).convert("RGB")
data = np.array(data, dtype=np.uint8)
-
except Exception as err:
data = None
self.ps_enhanced.emit(3)
-
if isinstance(data, np.ndarray):
if data.shape == display_data.shape:
for k in reg:
display_data[:, :, k] = data[:, :, k]
-
else:
self.ps_enhanced.emit(2)
-
else:
self.ps_enhanced.emit(3)
-
self.res_display_data = display_data
self.rev_display_data = None
-
self.display = QImage(display_data, display_data.shape[1], display_data.shape[0], display_data.shape[1] * 3, QImage.Format_RGB888)
self.ps_enhanced.emit(1)
def run_cover_hsv(self, process_scope, values):
- """
- Cover hsv display. Modify h, s or (and) v values to cover the channel of image.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (region, reserve, path).
- """
-
if not isinstance(self.ori_display_data, np.ndarray):
return
-
reg, res, path = values
-
if res and isinstance(self.rev_display_data, np.ndarray):
display_data = self.rev_display_data
-
elif res and isinstance(self.res_display_data, np.ndarray):
display_data = Color.rgb2hsv_array(self.res_display_data)
-
else:
display_data = Color.rgb2hsv_array(self.ori_display_data)
-
if os.path.isfile(path):
try:
data = Image.open(path).convert("RGB")
data = np.array(data, dtype=np.uint8)
-
except Exception as err:
data = None
self.ps_enhanced.emit(3)
-
if isinstance(data, np.ndarray):
if data.shape == display_data.shape:
data = Color.rgb2hsv_array(data)
-
for k in reg:
display_data[:, :, k] = data[:, :, k]
-
else:
self.ps_enhanced.emit(2)
-
else:
self.ps_enhanced.emit(3)
-
self.rev_display_data = display_data
-
display_data = Color.hsv2rgb_array(display_data)
-
self.res_display_data = display_data
-
self.display = QImage(display_data, display_data.shape[1], display_data.shape[0], display_data.shape[1] * 3, QImage.Format_RGB888)
self.ps_enhanced.emit(1)
def run_extract(self, process_scope, values):
- """
- Extract a set of colors in different extract types.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (random number, color type).
- """
-
if not isinstance(self.ori_display_data, np.ndarray):
return
-
rand_num, color_type = values
-
if isinstance(self.res_display_data, np.ndarray):
display_data = self.res_display_data
-
else:
display_data = self.ori_display_data
-
extracts = extract_image(display_data, rand_num, color_type)
self.ps_extracts.emit(extracts)
diff --git a/src/main/python/clibs/server.py b/src/main/python/clibs/server.py
index 6e7ff39..6affabc 100644
--- a/src/main/python/clibs/server.py
+++ b/src/main/python/clibs/server.py
@@ -19,10 +19,6 @@
class ResultServer(QThread):
- """
- ResultServer object.
- """
-
ps_iset = pyqtSignal(str)
ps_oset = pyqtSignal(str)
ps_idpt = pyqtSignal(str)
@@ -32,12 +28,7 @@ class ResultServer(QThread):
ps_exit = pyqtSignal(bool)
def __init__(self, args, port=None):
- """
- Init ResultServer object by port.
- """
-
super().__init__()
-
self.req = Request
self.req.args = args
self.req.ps_iset = self.ps_iset
@@ -47,20 +38,13 @@ def __init__(self, args, port=None):
self.req.ps_cidx = self.ps_cidx
self.req.ps_star = self.ps_star
self.req.ps_exit = self.ps_exit
-
self._port = port
self._server = None
def run(self):
- """
- Start running in thread.
- """
-
try:
self._server = TCPServer(("localhost", self._port), self.req)
-
except Exception as err:
self._server = None
-
if self._server:
self._server.serve_forever()
diff --git a/src/main/python/main.py b/src/main/python/main.py
index 61154d5..230d9c5 100644
--- a/src/main/python/main.py
+++ b/src/main/python/main.py
@@ -17,7 +17,7 @@
"""
__VERSION__ = """
-v2.8.27-x2d3s3-pre
+v2.8.35-x3d3s3-pre
"""
__AUTHOR__ = """
@@ -25,7 +25,7 @@
"""
__DATE__ = """
-June 25, 2023
+July 16, 2023
"""
__HELP__ = """
@@ -144,9 +144,9 @@
from getopt import getopt
from fbs_runtime.application_context.PyQt5 import ApplicationContext
from PyQt5.QtWidgets import QWidget, QMainWindow, QApplication, QGridLayout, QMessageBox, QShortcut, QPushButton, QSizePolicy
-from PyQt5.QtCore import Qt, QCoreApplication, QTemporaryDir, QUrl, QTranslator, QSettings, QT_VERSION_STR
+from PyQt5.QtCore import Qt, QCoreApplication, QTemporaryDir, QUrl, QTranslator, QSettings, QByteArray, QT_VERSION_STR
from PyQt5.Qt import PYQT_VERSION_STR
-from PyQt5.QtGui import QIcon, QPixmap, QImage, QDesktopServices, QKeySequence, QFontDatabase
+from PyQt5.QtGui import QGuiApplication, QIcon, QPixmap, QImage, QDesktopServices, QKeySequence, QFontDatabase
from cguis.design.main_window import Ui_MainWindow
from cguis.resource import view_rc
from clibs.server import ResultServer
@@ -173,44 +173,29 @@
class Rickrack(QMainWindow, Ui_MainWindow):
- """
- Rickrack main window framework.
- """
-
def __init__(self, resources, sys_argv):
- """
- Init main window.
- """
-
super().__init__()
self.setupUi(self)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
+ self.setAttribute(Qt.WA_InputMethodEnabled)
self._sys_argv = sys_argv
-
reset_all_args = self._sys_argv["reset"] in ("settings", "setting", "all") or self._sys_argv["temporary"]
self._args = Args(resources, resetall=reset_all_args, uselang=self._sys_argv["lang"])
self._args.global_temp_dir = QTemporaryDir()
-
- if self._args.geometry_args:
- self._geo_args = QSettings(self._args.geometry_args, QSettings.IniFormat)
-
+ try:
+ geo_args = QSettings(self._args.geometry_args, QSettings.IniFormat)
+ except Exception as err:
+ geo_args = None
+ self._geo_args = geo_args
self._save_settings_before_close = True
self._connected_keymaps = {}
self._curr_view_idx = 0
-
- # load translations.
+ self._curr_docks = None
self._func_tr_()
-
- # init qt args.
app_icon = QIcon()
app_icon.addPixmap(QPixmap(":/images/images/icon_128.png"), QIcon.Normal, QIcon.Off)
self.setWindowIcon(app_icon)
self.setMinimumSize(600, 460)
-
self._setup_workarea()
self._setup_result()
self._setup_rule()
@@ -220,16 +205,12 @@ def __init__(self, resources, sys_argv):
self._setup_channel()
self._setup_transformation()
self._setup_settings()
-
- # set dock window integrations.
self.tabifyDockWidget(self.operation_dock_widget, self.script_dock_widget)
self.tabifyDockWidget(self.mode_dock_widget, self.transformation_dock_widget)
self.tabifyDockWidget(self.rule_dock_widget, self.channel_dock_widget)
self.operation_dock_widget.raise_()
self.mode_dock_widget.raise_()
self.rule_dock_widget.raise_()
-
- # set dock window visibilities.
self.rule_dock_widget.visibilityChanged.connect(lambda x: self.actionRule.setChecked(self.rule_dock_widget.isVisible()))
self.channel_dock_widget.visibilityChanged.connect(lambda x: self.actionChannel.setChecked(self.channel_dock_widget.isVisible()))
self.operation_dock_widget.visibilityChanged.connect(lambda x: self.actionOperation.setChecked(self.operation_dock_widget.isVisible()))
@@ -237,8 +218,6 @@ def __init__(self, resources, sys_argv):
self.mode_dock_widget.visibilityChanged.connect(lambda x: self.actionMode.setChecked(self.mode_dock_widget.isVisible()))
self.transformation_dock_widget.visibilityChanged.connect(lambda x: self.actionTransformation.setChecked(self.transformation_dock_widget.isVisible()))
self.result_dock_widget.visibilityChanged.connect(lambda x: self.actionResult.setChecked(self.result_dock_widget.isVisible()))
-
- # set menu actions.
self.actionOpen.triggered.connect(self._wget_operation.exec_open)
self.actionSave.triggered.connect(self._wget_operation.exec_save)
self.actionImport.triggered.connect(self._wget_operation.exec_import)
@@ -247,18 +226,15 @@ def __init__(self, resources, sys_argv):
self.actionSaveImage.triggered.connect(self._ins_save_image)
self.actionQuit.triggered.connect(self.close)
self.actionDirectQuit.triggered.connect(self.close_without_save)
-
self.actionCreate.triggered.connect(self._ins_create)
self.actionLocate.triggered.connect(self._ins_locate)
self.actionDerive.triggered.connect(self._ins_derive)
self.actionAttach.triggered.connect(self._ins_attach)
self.actionSettings.triggered.connect(self._wget_settings.showup)
-
self.actionWheel.triggered.connect(self._switch_to_wheel)
self.actionImage.triggered.connect(self._switch_to_image)
self.actionBoard.triggered.connect(self._switch_to_board)
self.actionDepot.triggered.connect(self._switch_to_depot)
-
self.actionRule.triggered.connect(self._inner_show_or_hide(self.rule_dock_widget))
self.actionChannel.triggered.connect(self._inner_show_or_hide(self.channel_dock_widget))
self.actionOperation.triggered.connect(self._inner_show_or_hide(self.operation_dock_widget))
@@ -267,86 +243,49 @@ def __init__(self, resources, sys_argv):
self.actionTransformation.triggered.connect(self._inner_show_or_hide(self.transformation_dock_widget))
self.actionResult.triggered.connect(self._inner_show_or_hide(self.result_dock_widget))
self.actionAll.triggered.connect(self._inner_all_show_or_hide)
-
self.actionHomepage.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(self._args.info_main_site)))
self.actionUpdate.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(self._args.info_update_site)))
+ self.actionForum.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(self._args.info_dissc_site)))
self.actionAbout.triggered.connect(lambda x: self._show_about())
self.actionInfo.triggered.connect(lambda x: QDesktopServices.openUrl(QUrl(self._args.info_aucc_site)))
-
- # setup toolbar.
+ self.actionInspired_R.triggered.connect(lambda x: self._change_layout(0))
+ self.actionInspired_L.triggered.connect(lambda x: self._change_layout(1))
+ self.actionSpecific_R.triggered.connect(lambda x: self._change_layout(2))
+ self.actionSpecific_L.triggered.connect(lambda x: self._change_layout(3))
+ self.actionConcise_R.triggered.connect(lambda x: self._change_layout(4))
+ self.actionConcise_L.triggered.connect(lambda x: self._change_layout(5))
self._setup_toolbar()
-
- # setup short keys.
self._setup_skey()
-
- # setup server.
self._setup_server()
-
- # install translator.
self._tr = QTranslator()
self._app = QApplication.instance()
self._install_translator()
-
- # focus on wheel.
self._wget_wheel.setFocus()
-
- # load works.
self._load_last_work()
-
if self._sys_argv["input"]:
if self._sys_argv["input"].split(".")[-1].lower() in ("png", "bmp", "jpg", "jpeg", "tif", "tiff", "webp"):
self._switch_to_image()
self._wget_image.open_image(self._sys_argv["input"])
-
else:
try:
with open(self._sys_argv["input"], "r", encoding="utf-8") as f:
color_dict = json.load(f)
-
except Exception as err:
color_dict = None
-
if isinstance(color_dict, dict) and "type" in color_dict:
if color_dict["type"] == "depot":
self._switch_to_depot()
self._wget_operation.dp_open(color_dict, direct_dict=True, dp_path=os.path.dirname(os.path.abspath(self._sys_argv["input"])))
-
elif color_dict["type"] == "set":
self._wget_operation.dp_import(color_dict, direct_dict=True)
-
- # show args loading errors.
if self._args.load_settings_failed:
self._wget_operation.warning(self._wget_operation.main_errs[self._args.load_settings_failed - 1])
-
- # restore main window state.
self._default_state = self.saveState()
self._default_size = self.size()
-
- if self._args.geometry_args:
- main_win_state = self._geo_args.value('main_win_state', None)
- main_win_geometry = self._geo_args.value('main_win_geometry', None)
-
- if main_win_state:
- try:
- self.restoreState(main_win_state)
-
- except Exception as err:
- pass
-
- if main_win_geometry:
- try:
- self.restoreGeometry(main_win_geometry)
-
- except Exception as err:
- pass
-
+ self._change_layout()
self._setup_geometry()
QApplication.desktop().screenCountChanged.connect(self._setup_geometry)
-
- # set main window on top.
self.setWindowFlag(Qt.WindowStaysOnTopHint, on=self._args.win_on_top)
-
- # actions.
self.actionRule.setChecked(self.rule_dock_widget.isVisible())
self.actionChannel.setChecked(self.channel_dock_widget.isVisible())
self.actionOperation.setChecked(self.operation_dock_widget.isVisible())
@@ -354,7 +293,6 @@ def __init__(self, resources, sys_argv):
self.actionMode.setChecked(self.mode_dock_widget.isVisible())
self.actionTransformation.setChecked(self.transformation_dock_widget.isVisible())
self.actionResult.setChecked(self.result_dock_widget.isVisible())
-
if self._sys_argv["window"] >= 0:
self.rule_dock_widget.setVisible(bool(self._sys_argv["window"] // 2 // 2 // 2 // 2 // 2 // 2 % 2))
self.channel_dock_widget.setVisible(bool(self._sys_argv["window"] // 2 // 2 // 2 // 2 // 2 % 2))
@@ -363,349 +301,220 @@ def __init__(self, resources, sys_argv):
self.mode_dock_widget.setVisible(bool(self._sys_argv["window"] // 2 // 2 % 2))
self.transformation_dock_widget.setVisible(bool(self._sys_argv["window"] // 2 % 2))
self.result_dock_widget.setVisible(bool(self._sys_argv["window"] % 2))
-
- # install stylesheet.
if os.path.isdir(os.sep.join((resources, "fonts"))):
for font in os.listdir(os.sep.join((resources, "fonts"))):
if font.split(".")[-1].lower() in ("ttf", "otf"):
QFontDatabase.addApplicationFont(os.sep.join((resources, "fonts", font)))
-
+ self._wheel_icon = None
+ self._image_icon = None
+ self._board_icon = None
+ self._depot_icon = None
+ self._sel_wheel_icon = None
+ self._sel_image_icon = None
+ self._sel_board_icon = None
+ self._sel_depot_icon = None
self._setup_interface_style(change_pn_colors=False)
-
- # history.
self._history = History(self._args)
self._history.backup()
self._setup_history()
def _setup_geometry(self):
- """
- Keep window visiable when screen count changed.
- """
-
scr_count = QApplication.desktop().screenCount()
-
if scr_count >= 0:
cur_geometry = self.geometry()
cur_in_window = False
-
for sc_idx in range(scr_count):
scr_geometry = QApplication.desktop().availableGeometry(sc_idx)
-
if scr_geometry.x() < cur_geometry.x() < scr_geometry.x() + scr_geometry.width() and scr_geometry.y() < cur_geometry.y() < scr_geometry.y() + scr_geometry.height():
cur_in_window = True
break
-
if not cur_in_window:
scr_geometry = QApplication.desktop().availableGeometry(0)
-
new_x = (scr_geometry.width() - cur_geometry.width()) / 2
new_y = (scr_geometry.height() - cur_geometry.height()) / 2
new_x = 0 if new_x < 0 else new_x
new_y = 0 if new_y < 0 else new_y
-
self.setGeometry(new_x, new_y, cur_geometry.width(), cur_geometry.height())
def _setup_workarea(self):
- """
- Setup workarea (wheel, image or depot).
- """
-
def _wheel_status(value):
- """
- Show information about wheel behavior in statusbar.
- """
-
color_sign = self._color_descs[value[0]] + self._color_descs[value[1] + 10]
self.statusbar.showMessage(self._status_descs[4].format(color_sign))
def _image_status(value):
- """
- Show information about image behavior in statusbar.
- """
-
if len(value) == 2:
self.statusbar.showMessage(self._status_descs[1].format(*value))
-
elif len(value) == 4:
self.statusbar.showMessage(self._status_descs[2].format(*value))
-
else:
color_sign = self._color_descs[value[4][0]] + self._color_descs[value[4][1] + 10]
self.statusbar.showMessage(self._status_descs[5].format(*value[:4], color_sign))
def _board_status(value):
- """
- Show information about board behavior in statusbar.
- """
-
if value[0] == 0:
self.statusbar.showMessage(self._status_descs[8].format(value[1], value[2], value[3], value[4] + 1))
-
elif value[0] == 1:
self.statusbar.showMessage(self._status_descs[7].format(value[1]))
-
else:
self.statusbar.showMessage(self._status_descs[6])
def _depot_status(value):
- """
- Show information about depot behavior in statusbar.
- """
-
self.statusbar.showMessage(self._status_descs[3].format(*value))
def _transfer_image(value):
- """
- Transfer image from board to image view.
- """
-
self._switch_to_image()
self._wget_image.open_image(value, direct=True)
-
central_widget_grid_layout = QGridLayout(self.central_widget)
central_widget_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_wheel = Wheel(self.central_widget, self._args)
self._wget_image = Image(self.central_widget, self._args)
self._wget_board = Board(self.central_widget, self._args)
self._wget_depot = Depot(self.central_widget, self._args)
-
self._wget_wheel.ps_status_changed.connect(_wheel_status)
self._wget_image.ps_status_changed.connect(_image_status)
self._wget_board.ps_status_changed.connect(_board_status)
self._wget_depot.ps_status_changed.connect(_depot_status)
-
self._wget_board.ps_transfer_image.connect(_transfer_image)
-
self._wget_wheel.show()
self._wget_image.hide()
self._wget_board.hide()
self._wget_depot.hide()
-
central_widget_grid_layout.addWidget(self._wget_wheel)
central_widget_grid_layout.addWidget(self._wget_image)
central_widget_grid_layout.addWidget(self._wget_board)
central_widget_grid_layout.addWidget(self._wget_depot)
-
- # assit color changed.
self._wget_image.ps_assit_pt_changed.connect(self._wget_wheel.change_assit_point)
self._wget_board.ps_assit_pt_changed.connect(self._wget_wheel.change_assit_point)
def _setup_result(self):
- """
- Setup result (cube).
- """
-
result_grid_layout = QGridLayout(self.result_dock_contents)
result_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_cube_table = CubeTable(self.result_dock_contents, self._args)
result_grid_layout.addWidget(self._wget_cube_table)
-
self._wget_wheel.ps_color_changed.connect(lambda x: self._wget_cube_table.update_color())
self._wget_wheel.ps_index_changed.connect(lambda x: self._wget_cube_table.update_index())
-
self._wget_image.ps_color_changed.connect(lambda x: self._wget_cube_table.update_color())
-
self._wget_board.ps_index_changed.connect(lambda x: self._wget_cube_table.update_index())
self._wget_board.ps_value_changed.connect(lambda x: self._wget_mode.update_grid_vales())
self._wget_board.ps_color_changed.connect(lambda x: self._wget_cube_table.update_color())
-
self._wget_cube_table.ps_color_changed.connect(lambda x: self._wget_wheel.update())
self._wget_cube_table.ps_color_changed.connect(lambda x: self._wget_image.update_color_loc())
self._wget_cube_table.ps_color_changed.connect(lambda x: self._wget_board.update_index())
self._wget_cube_table.ps_color_changed.connect(lambda x: self._wget_depot.update_index())
-
self._wget_board.ps_linked.connect(lambda x: self._wget_cube_table.update_all())
self._wget_depot.ps_linked.connect(lambda x: self._wget_cube_table.update_all())
def _setup_history(self):
- """
- Setup history.
- """
-
self._wget_wheel.ps_history_backup.connect(self._inner_backup)
self._wget_image.ps_history_backup.connect(self._inner_backup)
self._wget_board.ps_history_backup.connect(self._inner_backup)
self._wget_depot.ps_history_backup.connect(self._inner_backup)
self._wget_cube_table.ps_history_backup.connect(self._inner_backup)
-
self._wget_operation.ps_opened.connect(self._inner_backup)
self._wget_operation.ps_update.connect(self._inner_backup)
-
self._wget_wheel.ps_undo.connect(self._inner_undo_or_redo)
self._wget_image.ps_undo.connect(self._inner_undo_or_redo)
self._wget_board.ps_undo.connect(self._inner_undo_or_redo)
self._wget_depot.ps_undo.connect(self._inner_undo_or_redo)
def _setup_toolbar(self):
- """
- Setup toolbar.
- """
-
self.toolbar.addAction(self.actionWheel)
self.toolbar.addAction(self.actionImage)
self.toolbar.addAction(self.actionBoard)
self.toolbar.addAction(self.actionDepot)
-
separator = QWidget(self)
separator.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.toolbar.addWidget(separator)
-
self.toolbar.addAction(self.actionSettings)
self.toolbar.addAction(self.actionAbout)
def _setup_rule(self):
- """
- Setup rule.
- """
-
rule_grid_layout = QGridLayout(self.rule_dock_contents)
rule_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_rule = Rule(self.rule_dock_contents, self._args)
rule_grid_layout.addWidget(self._wget_rule)
-
self._wget_rule.ps_rule_changed.connect(lambda x: self._wget_cube_table.modify_rule())
self._wget_image.ps_modify_rule.connect(lambda x: self._wget_rule.update_rule())
def _setup_mode(self):
- """
- Setup mode.
- """
-
mode_grid_layout = QGridLayout(self.mode_dock_contents)
mode_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_mode = Mode(self.mode_dock_contents, self._args)
mode_grid_layout.addWidget(self._wget_mode)
-
self._update_info_cbox(0)
-
self._wget_mode.ps_mode_changed.connect(lambda x: self._wget_cube_table.modify_box_visibility())
self._wget_mode.ps_assistp_changed.connect(lambda x: self._wget_board.update())
self._wget_mode.ps_info_changed.connect(lambda x: self._update_info_args())
self._wget_mode.ps_color_sys_changed.connect(lambda x: self._wget_wheel.update())
-
- # mouse tracking method.
self._wget_wheel.setMouseTracking(bool(self._args.show_info_pts[0]))
self._wget_image.setMouseTracking(bool(self._args.show_info_pts[1]))
self._wget_board.setMouseTracking(bool(self._args.show_info_pts[2]))
def _setup_operation(self):
- """
- Setup operation.
- """
-
operation_grid_layout = QGridLayout(self.operation_dock_contents)
operation_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_operation = Operation(self.operation_dock_contents, self._args)
operation_grid_layout.addWidget(self._wget_operation)
- # 0 create color set.
- # 1 reset.
- #
- # 2 open image.
- # 3 save image.
- # 4 pick-up.
- #
- # 5 save image.
- # 6 switch fix.
- # 7 switch ref.
- # 8 reset.
- #
- # 9 attach set.
- # 10 export set.
- # 11 detail set.
-
def _functn(value):
if self._curr_view_idx == 0:
if value == 0:
self._wget_wheel.insert_assit_point((15 * np.random.random() + 15) * np.random.choice([1,-1]), 0.3 * np.random.random() - 0.15, 0)
-
if value == 1:
self._ins_create()
-
elif value == 2:
self._wget_wheel.reset_assit_point()
-
elif value == 3:
self._switch_to_board()
-
elif self._curr_view_idx == 1:
if value == 0:
self._ins_open_image()
-
elif value == 1:
self._ins_save_image()
-
elif value == 2:
self._ins_locate()
-
elif value == 3:
self._switch_to_board()
-
elif self._curr_view_idx == 2:
if value == 0:
self._ins_save_image()
-
elif value == 1:
self._wget_board.clear_or_gen_grid_list()
-
elif value == 2:
self._wget_board.clear_or_gen_assit_color_list()
-
elif value == 3:
self._wget_board.reset_locations()
-
elif self._curr_view_idx == 3:
if value == 0:
self._wget_depot.import_set()
-
if value == 1:
self._ins_attach()
-
elif value == 2:
self._wget_depot.export_set()
-
elif value == 3:
self._wget_depot.detail_set()
-
self._inner_backup()
-
self._wget_operation.ps_functn.connect(_functn)
-
self._wget_operation.ps_update.connect(lambda x: self._wget_cube_table.update_color())
self._wget_operation.ps_update.connect(lambda x: self._wget_rule.update_rule())
self._wget_operation.ps_update.connect(lambda x: self._wget_mode.update_grid_vales())
self._wget_operation.ps_opened.connect(lambda x: self._wget_depot.initialize())
-
self._wget_depot.ps_update.connect(lambda x: self._wget_cube_table.update_color())
self._wget_depot.ps_update.connect(lambda x: self._wget_rule.update_rule())
self._wget_depot.ps_update.connect(lambda x: self._wget_mode.update_grid_vales())
self._wget_depot.ps_export.connect(self._wget_operation.exec_export)
-
self._wget_wheel.ps_dropped.connect(lambda x: self._inner_import(x))
self._wget_board.ps_dropped.connect(lambda x: self._inner_import(x))
self._wget_depot.ps_dropped.connect(lambda x: self._inner_open(x))
self._wget_depot.ps_appended.connect(lambda x: self._inner_append(x))
-
self._wget_depot.ps_open_image_url.connect(lambda x: self._wget_image.open_image(x[0], with_full_locs=x[1]))
-
self._wget_operation.show_import_export()
def _setup_script(self):
- """
- Setup script.
- """
-
script_grid_layout = QGridLayout(self.script_dock_contents)
script_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_script = Script(self.script_dock_contents, self._args)
script_grid_layout.addWidget(self._wget_script)
-
self._wget_script.ps_filter.connect(lambda x: self._wget_image.open_image("", script=x))
self._wget_script.ps_crop.connect(self._wget_image.crop_image)
self._wget_script.ps_freeze.connect(self._wget_image.freeze_image)
@@ -715,74 +524,42 @@ def _setup_script(self):
self._wget_script.ps_extract.connect(self._wget_image.extract_image)
def _setup_channel(self):
- """
- Setup channel.
- """
-
channel_grid_layout = QGridLayout(self.channel_dock_contents)
channel_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_channel = Channel(self.channel_dock_contents, self._args)
channel_grid_layout.addWidget(self._wget_channel)
-
self._wget_channel.ps_channel_changed.connect(lambda x: self._wget_image.open_category())
self._wget_image.ps_image_changed.connect(lambda x: self._wget_channel.reset())
self._wget_image.ps_recover_channel.connect(lambda x: self._wget_channel.recover())
def _setup_transformation(self):
- """
- Setup transformation.
- """
-
transformation_grid_layout = QGridLayout(self.transformation_dock_contents)
transformation_grid_layout.setContentsMargins(2, 2, 2, 2)
-
self._wget_transformation = Transformation(self.transformation_dock_contents, self._args)
transformation_grid_layout.addWidget(self._wget_transformation)
-
self._wget_transformation.ps_home.connect(lambda x: self._wget_image.home())
self._wget_transformation.ps_move.connect(lambda x: self._wget_image.move(x[0], x[1]))
self._wget_transformation.ps_zoom.connect(lambda x: self._wget_image.zoom(x, "default"))
-
self._wget_transformation.ps_home.connect(lambda x: self._wget_board.home())
self._wget_transformation.ps_move.connect(lambda x: self._wget_board.move(x[0], x[1]))
self._wget_transformation.ps_zoom.connect(lambda x: self._wget_board.zoom(x))
-
self._wget_transformation.ps_home.connect(lambda x: self._wget_depot.home())
self._wget_transformation.ps_move.connect(lambda x: self._wget_depot.move(x[0], x[1]))
self._wget_transformation.ps_zoom.connect(lambda x: self._wget_depot.zoom(x))
-
self._wget_transformation.ps_replace.connect(self._wget_image.replace_color)
self._wget_transformation.ps_enhance.connect(self._wget_image.enhance_image)
def _setup_settings(self):
- """
- Setup settings.
- """
-
- def _restore_layout():
- """
- Restore to original layout.
- """
-
- self.restoreState(self._default_state)
- self.resize(self._default_size)
-
self._wget_settings = Settings(self, self._args)
-
self._wget_settings.ps_rule_changed.connect(self._wget_cube_table.modify_rule)
self._wget_settings.ps_lang_changed.connect(self._install_translator)
self._wget_settings.ps_skey_changed.connect(self._setup_skey)
self._wget_settings.ps_settings_changed.connect(self._inner_update)
self._wget_settings.ps_clean_up.connect(self._wget_depot.clean_up)
- self._wget_settings.ps_restore_layout.connect(_restore_layout)
+ self._wget_settings.ps_restore_layout.connect(lambda: self._change_layout(layout_src=None))
self._wget_settings.ps_theme_changed.connect(lambda x: self._setup_interface_style(change_pn_colors=x))
def _setup_server(self):
- """
- Start server if port exist.
- """
-
if self._sys_argv["port"]:
self._server = ResultServer(self._args, port=self._sys_argv["port"])
self._server.ps_iset.connect(lambda x: self._inner_import((x, False)))
@@ -790,330 +567,228 @@ def _setup_server(self):
self._server.ps_idpt.connect(lambda x: self._inner_open((x, False)))
self._server.ps_odpt.connect(lambda x: self._wget_operation.dp_save(x, True))
self._server.ps_cidx.connect(lambda x: self._inner_modify_color(*x))
-
self._choice_dialog = Choice(self, self._args)
self._server.ps_star.connect(self._choice_dialog.showup)
-
self._server.ps_exit.connect(lambda x: self.close_with_verify() if x else self.close_without_save())
-
self._server.start()
-
else:
self._server = None
self._choice_dialog = None
def _translate_server(self):
- """
- Update server translations.
- """
-
if self._sys_argv["port"] and self._choice_dialog:
self._choice_dialog._func_tr_()
self._choice_dialog.update_text()
def _update_info_args(self):
- """
- Update interface info pts.
- """
-
curr_wget = None
-
if self._wget_wheel.isVisible():
curr_wget = self._wget_wheel
idx = 0
-
elif self._wget_image.isVisible():
curr_wget = self._wget_image
idx = 1
-
elif self._wget_board.isVisible():
curr_wget = self._wget_board
idx = 2
-
else:
return
-
value = self._wget_mode.get_info()
self._args.show_info_pts[idx] = value
-
self._wget_wheel.setMouseTracking(bool(self._args.show_info_pts[0]))
self._wget_image.setMouseTracking(bool(self._args.show_info_pts[1]))
self._wget_board.setMouseTracking(bool(self._args.show_info_pts[2]))
def _update_info_cbox(self, view_idx=None):
- """
- Update interface info pts.
- """
-
idx = 0
-
if self._wget_image.isVisible():
idx = 1
-
elif self._wget_board.isVisible():
idx = 2
-
value = self._args.show_info_pts[idx]
self._wget_mode.update_info(value in (1, 3), value > 1)
- def _load_last_work(self):
- """
- Recovery the work quit last time.
- """
+ def _change_layout(self, layout_src=""):
+ if isinstance(layout_src, str) and self._args.geometry_args:
+ main_win_layout = 0
+ main_win_state = self._geo_args.value('main_win_state', None)
+ main_win_geometry = self._geo_args.value('main_win_geometry', None)
+ elif isinstance(layout_src, int):
+ main_win_layout = layout_src
+ main_win_state = QByteArray.fromBase64(bytes(self._args.layouts[layout_src], 'ascii'))
+ main_win_geometry = None
+ else:
+ main_win_layout = 0
+ main_win_state = self._default_state
+ main_win_geometry = None
+ self.resize(self._default_size)
+ if main_win_state:
+ try:
+ self.restoreState(main_win_state)
+ except Exception as err:
+ pass
+ if main_win_geometry:
+ try:
+ self.restoreGeometry(main_win_geometry)
+ except Exception as err:
+ pass
- # dont load last work when start with temporary tag.
+ def _load_last_work(self):
if self._sys_argv["temporary"]:
return
-
- # get storing dir.
if self._args.store_loc:
store_path = self._args.resources
-
else:
store_path = self._args.usr_store
-
- # create recommend deopt.
if not os.path.isdir(os.sep.join((store_path, "MyColors"))):
os.makedirs(os.sep.join((store_path, "MyColors")))
-
- # loading deopt.
if os.path.isfile(os.sep.join((store_path, "depot.json"))) and self._sys_argv["reset"] not in ("depot", "work", "all"):
self._wget_operation.dp_open(os.sep.join((store_path, "depot.json")))
-
- # loading set.
if os.path.isfile(os.sep.join((store_path, "set.json"))) and self._sys_argv["reset"] not in ("set", "work", "all"):
self._wget_operation.dp_import(os.sep.join((store_path, "set.json")))
def _inner_backup(self, accept=True):
- """
- Backup in history.
- """
-
self._history.backup()
self._wget_cube_table.update_color()
def _inner_undo_or_redo(self, undo=True):
- """
- Undo or redo in history.
- """
-
self._args.sys_activated_assit_idx = -1
-
if undo:
self._history.undo()
self._wget_rule.update_rule()
self._wget_cube_table.update_color()
-
else:
self._history.redo()
self._wget_rule.update_rule()
self._wget_cube_table.update_color()
def _inner_modify_color(self, idx, color):
- """
- Modify color in color set by idx and color.
- """
-
if idx and idx in range(5):
self._args.sys_activated_idx = int(idx)
self._args.sys_activated_assit_idx = -1
-
fmt_color = Color(color, tp="hsv", overflow=self._args.sys_color_set.get_overflow())
self._args.sys_color_set.modify(self._args.hm_rule, self._args.sys_activated_idx, fmt_color)
-
self._wget_cube_table.update_color()
self._wget_cube_table.update_index()
def _switch_to_wheel(self):
- """
- For connection in _setup_operation with create sign.
- """
-
self._curr_view_idx = 0
+ if self._sel_wheel_icon:
+ self.actionWheel.setIcon(self._sel_wheel_icon)
+ self.actionImage.setIcon(self._image_icon)
+ self.actionBoard.setIcon(self._board_icon)
+ self.actionDepot.setIcon(self._depot_icon)
self._wget_operation.update_functn_text(0)
-
+ if self._wget_wheel.isVisible():
+ self._inner_all_show_or_hide_current()
self._wget_wheel.show()
self._wget_image.hide()
self._wget_board.hide()
self._wget_board.hide_detail()
self._wget_depot.hide()
self._wget_depot.hide_detail()
- #
# self.statusbar.showMessage(self._status_descs[0])
-
- if self.rule_dock_widget.isVisible():
- self.rule_dock_widget.raise_()
-
- # if self.operation_dock_widget.isVisible():
- # self.operation_dock_widget.raise_()
-
- if self.mode_dock_widget.isVisible():
- self.mode_dock_widget.raise_()
-
self._update_info_cbox(0)
self._wget_operation.show_import_export()
-
+ self._wget_wheel.init_key()
self._wget_wheel.setFocus()
def _switch_to_image(self):
- """
- For connection in _setup_operation with locate sign.
- """
-
self._curr_view_idx = 1
+ if self._sel_image_icon:
+ self.actionWheel.setIcon(self._wheel_icon)
+ self.actionImage.setIcon(self._sel_image_icon)
+ self.actionBoard.setIcon(self._board_icon)
+ self.actionDepot.setIcon(self._depot_icon)
self._wget_operation.update_functn_text(1)
-
- self._wget_wheel.hide()
+ if self._wget_image.isVisible():
+ self._inner_all_show_or_hide_current()
self._wget_image.show()
+ self._wget_wheel.hide()
self._wget_board.hide()
self._wget_board.hide_detail()
self._wget_depot.hide()
self._wget_depot.hide_detail()
- #
# self.statusbar.showMessage(self._status_descs[0])
-
- if self.channel_dock_widget.isVisible():
- self.channel_dock_widget.raise_()
-
- """
- if self.script_dock_widget.isVisible():
- self.script_dock_widget.raise_()
- """
-
- if self.transformation_dock_widget.isVisible():
- self.transformation_dock_widget.raise_()
-
self._update_info_cbox(1)
self._wget_operation.show_import_export()
-
+ self._wget_image.init_key()
self._wget_image.setFocus()
def _switch_to_board(self):
- """
- For connection in _setup_operation with derive sign.
- """
-
self._curr_view_idx = 2
+ if self._sel_board_icon:
+ self.actionWheel.setIcon(self._wheel_icon)
+ self.actionImage.setIcon(self._image_icon)
+ self.actionBoard.setIcon(self._sel_board_icon)
+ self.actionDepot.setIcon(self._depot_icon)
self._wget_operation.update_functn_text(2)
-
+ if self._wget_board.isVisible():
+ self._inner_all_show_or_hide_current()
+ self._wget_board.show()
self._wget_wheel.hide()
self._wget_image.hide()
- self._wget_board.show()
self._wget_depot.hide()
self._wget_depot.hide_detail()
-
- if self.rule_dock_widget.isVisible():
- self.rule_dock_widget.raise_()
-
- # if self.operation_dock_widget.isVisible():
- # self.operation_dock_widget.raise_()
-
- if self.mode_dock_widget.isVisible():
- self.mode_dock_widget.raise_()
-
self._update_info_cbox(2)
self._wget_operation.show_import_export()
-
+ self._wget_board.init_key()
self._wget_board.setFocus()
def _switch_to_depot(self):
- """
- For connection in _setup_operation with attach sign.
- """
-
self._curr_view_idx = 3
+ if self._sel_depot_icon:
+ self.actionWheel.setIcon(self._wheel_icon)
+ self.actionImage.setIcon(self._image_icon)
+ self.actionBoard.setIcon(self._board_icon)
+ self.actionDepot.setIcon(self._sel_depot_icon)
self._wget_operation.update_functn_text(3)
-
+ if self._wget_depot.isVisible():
+ self._inner_all_show_or_hide_current()
+ self._wget_depot.show()
self._wget_wheel.hide()
self._wget_image.hide()
self._wget_board.hide()
self._wget_board.hide_detail()
- self._wget_depot.show()
- #
# self.statusbar.showMessage(self._status_descs[0])
-
- if self.rule_dock_widget.isVisible():
- self.rule_dock_widget.raise_()
-
- # if self.operation_dock_widget.isVisible():
- # self.operation_dock_widget.raise_()
-
- if self.transformation_dock_widget.isVisible():
- self.transformation_dock_widget.raise_()
-
self._wget_operation.show_open_and_save()
-
+ self._wget_depot.init_key()
self._wget_depot.setFocus()
def _ins_create(self):
- """
- Create a set of colors from wheel immediately.
- """
-
if not self._wget_wheel.isVisible():
self._switch_to_wheel()
-
self._wget_cube_table.create_set(direct=True)
def _ins_open_image(self):
- """
- Locate a set of colors from image immediately.
- """
-
if not self._wget_image.isVisible():
self._switch_to_image()
-
self._wget_image.open_image_dialog()
def _ins_save_image(self):
- """
- Locate a set of colors from image immediately.
- """
-
if self._wget_image.isVisible():
self._wget_image.save_image()
-
elif self._wget_board.isVisible():
self._wget_board.save_image()
def _ins_locate(self):
- """
- Locate a set of colors from image immediately.
- """
-
if not self._wget_image.isVisible():
self._switch_to_image()
-
if not self._wget_image.image3c.display:
self._ins_open_image()
-
self._wget_image.extract_image(0)
def _ins_derive(self):
- """
- Derive a set of colors from board immediately.
- """
-
if not self._wget_board.isVisible():
self._switch_to_board()
-
self._wget_board.reset_locations()
def _ins_attach(self):
- """
- Attach a set of colors into depot immediately.
- """
-
if not self._wget_depot.isVisible():
self._switch_to_depot()
-
self._wget_depot.attach_set()
def _inner_update(self):
- """
- Update setable wgets.
- """
-
self._args.sys_color_set.set_overflow(self._args.overflow)
self._args.sys_color_set.set_hsv_ranges(self._args.h_range, self._args.s_range, self._args.v_range)
self._wget_wheel.update()
@@ -1125,30 +800,18 @@ def _inner_update(self):
self._wget_rule.update_rule()
self._wget_mode.update_mode()
self._update_info_cbox()
-
self.update()
def _inner_show_or_hide(self, wget):
- """
- Change hidden wget to shown state and change shown wget to hidden state.
- """
-
def _func_():
if wget.isVisible():
wget.hide()
-
else:
wget.show()
-
# self.statusbar.showMessage(self._status_descs[0])
-
return _func_
def _inner_all_show_or_hide(self):
- """
- Change all hidden wget to shown state and change shown wget to hidden state.
- """
-
if self.rule_dock_widget.isVisible() and self.channel_dock_widget.isVisible() and self.operation_dock_widget.isVisible() and self.script_dock_widget.isVisible() and self.mode_dock_widget.isVisible() and self.transformation_dock_widget.isVisible() and self.result_dock_widget.isVisible():
self.rule_dock_widget.hide()
self.channel_dock_widget.hide()
@@ -1157,7 +820,6 @@ def _inner_all_show_or_hide(self):
self.mode_dock_widget.hide()
self.transformation_dock_widget.hide()
self.result_dock_widget.hide()
-
else:
self.rule_dock_widget.show()
self.channel_dock_widget.show()
@@ -1166,54 +828,65 @@ def _inner_all_show_or_hide(self):
self.mode_dock_widget.show()
self.transformation_dock_widget.show()
self.result_dock_widget.show()
-
# self.statusbar.showMessage(self._status_descs[0])
- def _inner_open(self, depot_file):
- """
- Open a depot file.
- """
+ def _inner_all_show_or_hide_current(self):
+ curr_docks = (
+ self.rule_dock_widget.isVisible(),
+ self.channel_dock_widget.isVisible(),
+ self.operation_dock_widget.isVisible(),
+ self.script_dock_widget.isVisible(),
+ self.mode_dock_widget.isVisible(),
+ self.transformation_dock_widget.isVisible(),
+ self.result_dock_widget.isVisible(),
+ )
+ if True in curr_docks:
+ self.rule_dock_widget.hide()
+ self.channel_dock_widget.hide()
+ self.operation_dock_widget.hide()
+ self.script_dock_widget.hide()
+ self.mode_dock_widget.hide()
+ self.transformation_dock_widget.hide()
+ self.result_dock_widget.hide()
+ self._curr_docks = curr_docks
+ else:
+ if True in self._curr_docks:
+ self.rule_dock_widget.setVisible(self._curr_docks[0])
+ self.channel_dock_widget.setVisible(self._curr_docks[1])
+ self.operation_dock_widget.setVisible(self._curr_docks[2])
+ self.script_dock_widget.setVisible(self._curr_docks[3])
+ self.mode_dock_widget.setVisible(self._curr_docks[4])
+ self.transformation_dock_widget.setVisible(self._curr_docks[5])
+ self.result_dock_widget.setVisible(self._curr_docks[6])
+ else:
+ self.rule_dock_widget.show()
+ self.channel_dock_widget.show()
+ self.operation_dock_widget.show()
+ self.script_dock_widget.show()
+ self.mode_dock_widget.show()
+ self.transformation_dock_widget.show()
+ self.result_dock_widget.show()
+ def _inner_open(self, depot_file):
self._wget_operation.dp_open(depot_file[0], direct_dict=depot_file[1])
-
self.update()
def _inner_import(self, set_file):
- """
- Import a set file.
- """
-
self._wget_operation.dp_import(set_file[0], direct_dict=set_file[1])
-
self.update()
def _inner_append(self, set_file):
- """
- Append a set file.
- """
-
color_list = self._wget_operation.dp_import(set_file[0], direct_dict=set_file[1], return_set=True)
-
- # The color list is none if dp_import failed, thus should be discarded.
- # Func attach_set(None) represent add color set from wheel.
if color_list:
self._wget_depot.attach_set(color_list=color_list)
-
- # self.update() is completed by self._wget_depot.attach_set(color_list=color_list) above.
# self.update()
def _install_translator(self):
- """
- Translate Rickrack interface.
- """
-
self._app.removeTranslator(self._tr)
-
if self._args.lang != "default":
lang = os.sep.join((self._args.resources, "langs", self._args.lang))
self._tr.load(lang)
self._app.installTranslator(self._tr)
-
self._func_tr_()
self._wget_wheel._func_tr_()
self._wget_image._func_tr_()
@@ -1228,7 +901,6 @@ def _install_translator(self):
self._wget_settings._func_tr_()
self._wget_settings.retranslateUi(self._wget_settings)
self.retranslateUi(self)
-
self._wget_board.update_text()
self._wget_depot.update_text()
self._wget_rule.update_text()
@@ -1239,243 +911,190 @@ def _install_translator(self):
self._wget_mode.update_text()
self._wget_script.update_text()
self._wget_settings.update_text()
-
self._translate_server()
-
- # set window title.
if self._args.lang[:2].lower() in ("zh", "ja", "ko"):
main_info = "焰火十二卷 {}".format("-".join((self._args.info_version_zh.split("-")[0], self._args.info_version_zh.split("-")[2])))
-
if self._sys_argv["port"]:
port_info = "端口:{}".format(self._sys_argv["port"])
main_info = self._info_descs[12].format(main_info, port_info)
-
else:
main_info = "Rickrack {}".format("-".join((self._args.info_version_en.split("-")[0], self._args.info_version_en.split("-")[2])))
-
if self._sys_argv["port"]:
port_info = "Port: {}".format(self._sys_argv["port"])
main_info = self._info_descs[12].format(main_info, port_info)
-
self.setWindowTitle(main_info)
-
- # set ready status.
self.setStatusTip(self._status_descs[0])
-
self.update()
def _setup_interface_style(self, change_pn_colors=True):
- """
- Setup theme.
- """
-
curr_positive_color = ( 80, 80, 80)
curr_negative_color = (245, 245, 245)
curr_wheel_ed_color = (255, 255, 255)
-
- # similar to code in __init__.
app_icon = QIcon()
app_icon.addPixmap(QPixmap(":/images/images/icon_128.png"), QIcon.Normal, QIcon.Off)
-
if self._args.style_id == 0:
qstyle = ""
-
- self.actionWheel.setIcon(app_icon)
- self.actionImage.setIcon(app_icon)
- self.actionBoard.setIcon(app_icon)
- self.actionDepot.setIcon(app_icon)
- self.actionSettings.setIcon(app_icon)
- self.actionAbout.setIcon(app_icon)
- self.actionInfo.setIcon(app_icon)
- self.actionSave.setIcon(app_icon)
- self.actionOpen.setIcon(app_icon)
- self.actionSaveImage.setIcon(app_icon)
- self.actionOpenImage.setIcon(app_icon)
- self.actionImport.setIcon(app_icon)
- self.actionExport.setIcon(app_icon)
- self.actionQuit.setIcon(app_icon)
- self.actionDirectQuit.setIcon(app_icon)
-
else:
- with open(os.sep.join((self._args.resources, "styles", "default.qss")), encoding="utf-8") as qf:
- qstyle = qf.read()
-
+ qss_file = os.sep.join((self._args.resources, "styles", "default.qss"))
+ if os.path.isfile(qss_file):
+ try:
+ with open(qss_file, encoding="utf-8") as qf:
+ qstyle = qf.read()
+ except Exception as err:
+ qstyle = ""
+ else:
+ qstyle = ""
ffmy = ", ".join(["\"{}\"".format(ff) for ff in self._args.font_family])
ffmy = ffmy if ffmy else "\"\""
-
qstyle = qstyle.replace("$qc_font_family", ffmy)
qstyle = qstyle.replace("$qc_font_weight", str(self._args.font_weight * 100))
qstyle = qstyle.replace("$qc_font_size", str(self._args.font_size) + "px")
-
- # forecolors.
- #
- # white, light grey.
if self._args.style_id in (1, 2):
qc_char = Color.hsv2hec((0, 0, 0.1))
qc_char_over = Color.hsv2hec((0, 0, 0.0))
-
gen_h = 0.0
gen_s = 0.0
gen_v = 1.0 - (self._args.style_id - 1) * 0.2
-
qc_list = Color.hsv2hec((gen_h, gen_s, gen_v - 0.08))
qc_list_over = Color.hsv2hec((gen_h, gen_s, gen_v - 0.16))
qc_list_selected = Color.hsv2hec((gen_h, gen_s, 0.35))
-
qc_workarea = Color.hsv2hec((gen_h, gen_s, gen_v))
qc_workarea_over = Color.hsv2hec((gen_h, gen_s, gen_v - 0.05))
-
- # dary grey, black.
elif self._args.style_id in (3, 4):
qc_char = Color.hsv2hec((0, 0, 0.9))
qc_char_over = Color.hsv2hec((0, 0, 1.0))
-
gen_h = 0.0
gen_s = 0.0
gen_v = 0.4 - (self._args.style_id - 3) * 0.25
-
qc_list = Color.hsv2hec((gen_h, gen_s, gen_v + 0.08))
- qc_list_over = Color.hsv2hec((gen_h, gen_s, gen_v + 0.16))
+ qc_list_over = Color.hsv2hec((gen_h, gen_s, gen_v + 0.24))
qc_list_selected = Color.hsv2hec((gen_h, gen_s, 1.0))
-
qc_workarea = Color.hsv2hec((gen_h, gen_s, gen_v))
qc_workarea_over = Color.hsv2hec((gen_h, gen_s, gen_v + 0.1))
-
- # light colors.
elif self._args.style_id in (5, 6, 7, 8, 9, 10):
qc_char = Color.hsv2hec((0, 0, 0.1))
qc_char_over = Color.hsv2hec((0, 0, 0.0))
-
- gen_h = (self._args.style_id - 5) * 60.0 + 25.0
+ if self._args.style_id % 2 == 1:
+ gen_h = (self._args.style_id - 5) * 60.0 + 25.0
+ else:
+ gen_h = (self._args.style_id - 5) * 60.0 - 5.0
gen_s = 0.05
gen_v = 1.0
-
qc_list = Color.hsv2hec((gen_h + 10.0, gen_s + 0.24, gen_v - 0.02))
qc_list_over = Color.hsv2hec((gen_h - 10.0, gen_s + 0.32, gen_v - 0.03))
qc_list_selected = Color.hsv2hec((gen_h - 30.0, gen_s + 0.42, 0.90))
-
qc_workarea = "FFFFFF"
qc_workarea_over = Color.hsv2hec((gen_h + 5.0, gen_s + 0.1, gen_v - 0.01))
-
- # dark colors.
elif self._args.style_id in (11, 12, 13, 14, 15, 16):
qc_char = Color.hsv2hec((0, 0, 0.9))
qc_char_over = Color.hsv2hec((0, 0, 1.0))
-
- gen_h = (self._args.style_id - 11) * 60.0 + 5.0
+ if self._args.style_id % 2 == 1:
+ gen_h = (self._args.style_id - 11) * 60.0 + 25.0
+ else:
+ gen_h = (self._args.style_id - 11) * 60.0 - 5.0
gen_s = 1.0
gen_v = 0.05
-
- qc_list = Color.hsv2hec((gen_h + 10.0, gen_s - 0.24, gen_v + 0.24))
+ qc_list = Color.hsv2hec((gen_h + 10.0, gen_s - 0.24, gen_v + 0.16))
qc_list_over = Color.hsv2hec((gen_h - 10.0, gen_s - 0.32, gen_v + 0.36))
qc_list_selected = Color.hsv2hec((gen_h - 30.0, gen_s - 0.32, 0.64))
-
qc_workarea = "000000"
qc_workarea_over = Color.hsv2hec((gen_h + 5.0, gen_s - 0.1, gen_v + 0.06))
-
- # backcolors.
- #
- # white, light grey.
if self._args.bakgd_id in (1, 2):
qc_char = Color.hsv2hec((0, 0, 0.1))
qc_char_over = Color.hsv2hec((0, 0, 0.0))
-
gen_h = 0.0
gen_s = 0.0
gen_v = 1.0 - (self._args.bakgd_id - 1) * 0.2
-
qc_list = Color.hsv2hec((gen_h, gen_s, gen_v - 0.08))
-
qc_workarea = Color.hsv2hec((gen_h, gen_s, gen_v))
qc_workarea_over = Color.hsv2hec((gen_h, gen_s, gen_v - 0.05))
-
- # dary grey, black.
elif self._args.bakgd_id in (3, 4):
qc_char = Color.hsv2hec((0, 0, 0.9))
qc_char_over = Color.hsv2hec((0, 0, 1.0))
-
gen_h = 0.0
gen_s = 0.0
gen_v = 0.4 - (self._args.bakgd_id - 3) * 0.25
-
qc_list = Color.hsv2hec((gen_h, gen_s, gen_v + 0.08))
-
qc_workarea = Color.hsv2hec((gen_h, gen_s, gen_v))
qc_workarea_over = Color.hsv2hec((gen_h, gen_s, gen_v + 0.1))
-
- # light colors.
elif self._args.bakgd_id in (5, 6, 7, 8, 9, 10):
qc_char = Color.hsv2hec((0, 0, 0.1))
qc_char_over = Color.hsv2hec((0, 0, 0.0))
-
- gen_h = (self._args.bakgd_id - 5) * 60.0 + 25.0
+ if self._args.bakgd_id % 2 == 1:
+ gen_h = (self._args.bakgd_id - 5) * 60.0 + 25.0
+ else:
+ gen_h = (self._args.bakgd_id - 5) * 60.0 - 5.0
gen_s = 0.05
gen_v = 1.0
-
qc_list = Color.hsv2hec((gen_h + 10.0, gen_s + 0.24, gen_v - 0.02))
-
qc_workarea = "FFFFFF"
qc_workarea_over = Color.hsv2hec((gen_h + 5.0, gen_s + 0.1, gen_v - 0.01))
-
- # dark colors.
elif self._args.bakgd_id in (11, 12, 13, 14, 15, 16):
qc_char = Color.hsv2hec((0, 0, 0.9))
qc_char_over = Color.hsv2hec((0, 0, 1.0))
-
- gen_h = (self._args.bakgd_id - 11) * 60.0 + 5.0
+ if self._args.bakgd_id % 2 == 1:
+ gen_h = (self._args.bakgd_id - 11) * 60.0 + 25.0
+ else:
+ gen_h = (self._args.bakgd_id - 11) * 60.0 - 5.0
gen_s = 1.0
gen_v = 0.05
-
qc_list = Color.hsv2hec((gen_h + 10.0, gen_s - 0.24, gen_v + 0.24))
-
qc_workarea = "000000"
qc_workarea_over = Color.hsv2hec((gen_h + 5.0, gen_s - 0.1, gen_v + 0.06))
-
- forecolor = qc_list_selected
- backcolor = qc_list_over
-
- wheel_icon = get_icon("wheel", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon)
- image_icon = get_icon("image", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon)
- board_icon = get_icon("board", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon)
- depot_icon = get_icon("depot", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon)
-
- self.actionWheel.setIcon(wheel_icon)
- self.actionImage.setIcon(image_icon)
- self.actionBoard.setIcon(board_icon)
- self.actionDepot.setIcon(depot_icon)
-
- self.actionCreate.setIcon(wheel_icon)
- self.actionLocate.setIcon(image_icon)
- self.actionDerive.setIcon(board_icon)
- self.actionAttach.setIcon(depot_icon)
-
- open_icon = get_icon("open", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon)
- save_icon = get_icon("save", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon)
-
+ if self._args.style_id < 5:
+ forecolor = qc_list_selected
+ backcolor = qc_list_selected
+ curropc = 0.6
+ else:
+ forecolor = qc_list_selected
+ backcolor = qc_list_over
+ curropc = 1.0
+ self._sel_wheel_icon = get_icon("wheel", forecolor, backcolor, curropc, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self._sel_image_icon = get_icon("image", forecolor, backcolor, curropc, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self._sel_board_icon = get_icon("board", forecolor, backcolor, curropc, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self._sel_depot_icon = get_icon("depot", forecolor, backcolor, curropc, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self._wheel_icon = get_icon("sel_wheel", forecolor, backcolor, 0.0, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self._image_icon = get_icon("sel_image", forecolor, backcolor, 0.0, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self._board_icon = get_icon("sel_board", forecolor, backcolor, 0.0, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self._depot_icon = get_icon("sel_depot", forecolor, backcolor, 0.0, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self.actionWheel.setIcon(self._sel_wheel_icon if self._curr_view_idx == 0 else self._wheel_icon)
+ self.actionImage.setIcon(self._sel_image_icon if self._curr_view_idx == 1 else self._image_icon)
+ self.actionBoard.setIcon(self._sel_board_icon if self._curr_view_idx == 2 else self._board_icon)
+ self.actionDepot.setIcon(self._sel_depot_icon if self._curr_view_idx == 3 else self._depot_icon)
+ self.actionCreate.setIcon(self._wheel_icon)
+ self.actionLocate.setIcon(self._image_icon)
+ self.actionDerive.setIcon(self._board_icon)
+ self.actionAttach.setIcon(self._depot_icon)
+ open_icon = get_icon("open", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon)
+ save_icon = get_icon("save", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon)
self.actionOpen.setIcon(open_icon)
self.actionSave.setIcon(save_icon)
self.actionOpenImage.setIcon(open_icon)
self.actionSaveImage.setIcon(save_icon)
-
self.actionImport.setIcon(open_icon)
self.actionExport.setIcon(save_icon)
-
- self.actionSettings.setIcon(get_icon("settings", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
- self.actionHomepage.setIcon(get_icon("home", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
- self.actionUpdate.setIcon(get_icon("update", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
- self.actionQuit.setIcon(get_icon("quit", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
- self.actionDirectQuit.setIcon(get_icon("quit", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
- self.actionAbout.setIcon(get_icon("about", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
- self.actionInfo.setIcon(get_icon("info", forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
-
+ self.actionSettings.setIcon(get_icon("settings", forecolor, backcolor, curropc, 0.0, self._args.global_temp_dir.path(), app_icon))
+ self.actionHomepage.setIcon(get_icon("home", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
+ self.actionUpdate.setIcon(get_icon("update", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
+ self.actionForum.setIcon(get_icon("forum", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
+ self.actionQuit.setIcon(get_icon("quit", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
+ self.actionDirectQuit.setIcon(get_icon("quit", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
+ self.actionAbout.setIcon(get_icon("about", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
+ self.actionInfo.setIcon(get_icon("info", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
+ layout_l = get_icon("layout_l", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon)
+ layout_r = get_icon("layout_r", forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon)
+ self.actionInspired_L.setIcon(layout_l)
+ self.actionSpecific_L.setIcon(layout_l)
+ self.actionConcise_L.setIcon(layout_l)
+ self.actionInspired_R.setIcon(layout_r)
+ self.actionSpecific_R.setIcon(layout_r)
+ self.actionConcise_R.setIcon(layout_r)
for btn_idx in range(7):
name = ("up", "down", "left", "right", "reset", "zoom_in", "zoom_out")[btn_idx]
- self._wget_transformation.move_btns[btn_idx].setIcon(get_icon(name, forecolor, backcolor, self._args.global_temp_dir.path(), app_icon))
-
+ self._wget_transformation.move_btns[btn_idx].setIcon(get_icon(name, forecolor, backcolor, 1.0, 0.0, self._args.global_temp_dir.path(), app_icon))
curr_positive_color = Color.hec2rgb(qc_list_selected)
curr_negative_color = Color.hec2rgb(qc_list)
curr_wheel_ed_color = Color.hec2rgb(qc_workarea_over)
-
qstyle = qstyle.replace("$qc_workarea_over", "#" + qc_workarea_over)
qstyle = qstyle.replace("$qc_workarea", "#" + qc_workarea)
qstyle = qstyle.replace("$qc_char_over", "#" + qc_char_over)
@@ -1483,510 +1102,351 @@ def _setup_interface_style(self, change_pn_colors=True):
qstyle = qstyle.replace("$qc_list_selected", "#" + qc_list_selected)
qstyle = qstyle.replace("$qc_list_over", "#" + qc_list_over)
qstyle = qstyle.replace("$qc_list", "#" + qc_list)
-
if change_pn_colors:
self._args.modify_settings("positive_color", curr_positive_color)
self._args.modify_settings("negative_color", curr_negative_color)
self._args.modify_settings("wheel_ed_color", curr_wheel_ed_color)
-
self._wget_settings.setup_colors()
-
self._app.setStyleSheet(qstyle)
self._wget_image.init_icon()
def _show_about(self):
- """
- Show Rickrack information.
- """
-
if self._args.lang[:2].lower() in ("zh", "ja", "ko"):
info = "焰火十二卷(调色板软件)"
-
else:
info = "Rickrack (Color Palette Generator)"
-
info = "{} ".format(info)
-
if self._args.lang[:2].lower() in ("zh", "ja", "ko"):
info += self._info_descs[1].format(self._args.info_version_zh) + " "
info += self._info_descs[2].format(self._args.info_author_zh) + " "
info += self._info_descs[3].format(self._args.info_date_zh) + " "
-
else:
info += self._info_descs[1].format(self._args.info_version_en) + " "
info += self._info_descs[2].format(self._args.info_author_en) + " "
info += self._info_descs[3].format(self._args.info_date_en) + " "
-
info += self._info_descs[4] # + " "
-
info += "
"
-
info += self._info_descs[5] + " "
- info += self._info_descs[9] + " "
info += self._info_descs[10] + " "
info += self._info_descs[8].format(QT_VERSION_STR, PYQT_VERSION_STR) # + " "
-
if self._args.lang[:2].lower() not in ("zh", "en"):
info += " " + self._info_descs[13]
-
info += "
"
-
info = "{}".format(info)
-
box = QMessageBox(self)
box.setWindowTitle(self._info_descs[0])
box.setText(info)
- resized_img = QImage(":/images/images/info_256.png").scaled(256, 640, Qt.KeepAspectRatio, Qt.SmoothTransformation)
- resized_img.setDevicePixelRatio(2)
+ resized_img = QImage(":/images/images/info_256.png").scaled(128 * self.devicePixelRatioF(), 360 * self.devicePixelRatioF(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
+ resized_img.setDevicePixelRatio(self.devicePixelRatioF())
box.setIconPixmap(QPixmap.fromImage(resized_img))
-
ok_btn = QPushButton()
ok_btn.setText(self._info_descs[6])
box.addButton(ok_btn, QMessageBox.RejectRole)
box.setDefaultButton(ok_btn)
-
visit_btn = QPushButton()
visit_btn.clicked.connect(lambda x: QDesktopServices.openUrl(QUrl(self._args.info_main_site)))
visit_btn.setText(self._info_descs[7])
box.addButton(visit_btn, QMessageBox.AcceptRole)
-
aucc_btn = QPushButton()
aucc_btn.clicked.connect(lambda x: QDesktopServices.openUrl(QUrl(self._args.info_aucc_site)))
aucc_btn.setText(self._info_descs[11])
box.addButton(aucc_btn, QMessageBox.AcceptRole)
-
+ aucc_btn = QPushButton()
+ aucc_btn.clicked.connect(lambda x: QDesktopServices.openUrl(QUrl(self._args.info_font_site)))
+ aucc_btn.setText(self._info_descs[14])
+ box.addButton(aucc_btn, QMessageBox.AcceptRole)
box.exec_()
def _chg_win_on_top(self):
- """
- Change the on top hint state of window.
- """
-
self._args.win_on_top = not self._args.win_on_top
self.setWindowFlag(Qt.WindowStaysOnTopHint, on=self._args.win_on_top)
-
if not self.isVisible():
self.show()
def close_with_verify(self):
- """
- If info window of board or depot is not closed, than close info window instead of main window.
- """
-
if self._wget_board.hide_detail() or self._wget_depot.hide_detail():
return
-
if self._wget_image.cancel_croping_or_locating():
return
-
if self._wget_settings.isVisible():
self._wget_settings.hide()
-
return
-
self._save_settings_before_close = True
self.close()
def close_without_save(self):
- """
- Close the main window without saving settings.
- """
-
self._save_settings_before_close = False
self.close()
def rename(self, source, target):
- """
- Delete target if it exist.
- """
-
if os.path.isfile(target):
os.remove(target)
-
os.rename(source, target)
def save_main_settings(self):
- """
- Save settings before closing the main window.
- """
-
- # get storing dir.
if self._args.store_loc:
store_path = self._args.resources
-
else:
store_path = self._args.usr_store
-
- # storing deopt.
if not os.path.isdir(os.sep.join((store_path, "History", "Depots"))):
os.makedirs(os.sep.join((store_path, "History", "Depots")))
-
if os.path.isfile(os.sep.join((store_path, "depot.temp"))):
os.remove(os.sep.join((store_path, "depot.temp")))
-
self._wget_operation.dp_save(os.sep.join((store_path, "depot.temp")), True)
-
if os.path.isfile(os.sep.join((store_path, "depot.temp"))):
if self._args.max_history_files and os.path.isfile(os.sep.join((store_path, "depot.json"))):
json_hash = ""
temp_hash = ""
-
with open(os.sep.join((store_path, "depot.json")), "rb") as frp:
json_hash = hashlib.md5(frp.read()).hexdigest()
-
with open(os.sep.join((store_path, "depot.temp")), "rb") as frp:
temp_hash = hashlib.md5(frp.read()).hexdigest()
-
if json_hash != temp_hash or (not json_hash) or (not temp_hash):
for backup_file in os.listdir(os.sep.join((store_path, "History", "Depots"))):
if os.path.isfile(os.sep.join((store_path, "History", "Depots", backup_file))):
if backup_file[:6] == "depot_" and backup_file[-13:] == "_bak_{:0>3d}.json".format(self._args.max_history_files - 1):
os.remove(os.sep.join((store_path, "History", "Depots", backup_file)))
-
continue
-
for i in range(self._args.max_history_files - 1):
if os.path.isfile(os.sep.join((store_path, "History", "Depots", backup_file))) and backup_file[:6] == "depot_" and backup_file[-13:] == "_bak_{:0>3d}.json".format(i):
self.rename(os.sep.join((store_path, "History", "Depots", backup_file)), os.sep.join((store_path, "History", "Depots", backup_file[:-13] + "_bak_{:0>3d}.json".format(i + 1))))
-
self.rename(os.sep.join((store_path, "depot.json")), os.sep.join((store_path, "History", "Depots", "depot_{}_bak_000.json".format(time.strftime("%Y%m%d_%H%M%S", time.localtime())))))
self.rename(os.sep.join((store_path, "depot.temp")), os.sep.join((store_path, "depot.json")))
-
else:
self.rename(os.sep.join((store_path, "depot.temp")), os.sep.join((store_path, "depot.json")))
-
- # storing set.
if not os.path.isdir(os.sep.join((store_path, "History", "Sets"))):
os.makedirs(os.sep.join((store_path, "History", "Sets")))
-
if os.path.isfile(os.sep.join((store_path, "set.temp"))):
os.remove(os.sep.join((store_path, "set.temp")))
-
self._wget_operation.dp_export(os.sep.join((store_path, "set.temp")), True)
-
if os.path.isfile(os.sep.join((store_path, "set.temp"))):
if self._args.max_history_files and os.path.isfile(os.sep.join((store_path, "set.json"))):
json_hash = ""
temp_hash = ""
-
with open(os.sep.join((store_path, "set.json")), "rb") as frp:
json_hash = hashlib.md5(frp.read()).hexdigest()
-
with open(os.sep.join((store_path, "set.temp")), "rb") as frp:
temp_hash = hashlib.md5(frp.read()).hexdigest()
-
if json_hash != temp_hash or (not json_hash) or (not temp_hash):
for backup_file in os.listdir(os.sep.join((store_path, "History", "Sets"))):
if os.path.isfile(os.sep.join((store_path, "History", "Sets", backup_file))):
if backup_file[:4] == "set_" and backup_file[-13:] == "_bak_{:0>3d}.json".format(self._args.max_history_files - 1):
os.remove(os.sep.join((store_path, "History", "Sets", backup_file)))
-
continue
-
for i in range(self._args.max_history_files - 1):
if os.path.isfile(os.sep.join((store_path, "History", "Sets", backup_file))) and backup_file[:4] == "set_" and backup_file[-13:] == "_bak_{:0>3d}.json".format(i):
self.rename(os.sep.join((store_path, "History", "Sets", backup_file)), os.sep.join((store_path, "History", "Sets", backup_file[:-13] + "_bak_{:0>3d}.json".format(i + 1))))
-
self.rename(os.sep.join((store_path, "set.json")), os.sep.join((store_path, "History", "Sets", "set_{}_bak_000.json".format(time.strftime("%Y%m%d_%H%M%S", time.localtime())))))
self.rename(os.sep.join((store_path, "set.temp")), os.sep.join((store_path, "set.json")))
-
else:
self.rename(os.sep.join((store_path, "set.temp")), os.sep.join((store_path, "set.json")))
-
- # delete temp files.
for backup_file in os.listdir(store_path):
if os.path.isfile(os.sep.join((store_path, backup_file))) and backup_file[-5:] == ".temp":
os.remove(os.sep.join((store_path, backup_file)))
-
if self._args.geometry_args:
self._geo_args.setValue('main_win_state', self.saveState())
self._geo_args.setValue('main_win_geometry', self.saveGeometry())
-
self._args.save_settings()
- # ---------- ---------- ---------- Shortcut ---------- ---------- ---------- #
-
def _setup_skey(self):
- """
- Set main window shortcuts.
- """
-
self.actionHomepage.setShortcuts(self._args.shortcut_keymaps[0])
self.actionUpdate.setShortcuts(self._args.shortcut_keymaps[1])
self.actionAbout.setShortcuts(self._args.shortcut_keymaps[2])
self.actionInfo.setShortcuts(self._args.shortcut_keymaps[50])
-
self.actionOpen.setShortcuts(self._args.shortcut_keymaps[6])
self.actionSave.setShortcuts(self._args.shortcut_keymaps[7])
self.actionImport.setShortcuts(self._args.shortcut_keymaps[8])
self.actionExport.setShortcuts(self._args.shortcut_keymaps[9])
-
self.actionCreate.setShortcuts(self._args.shortcut_keymaps[10])
self.actionLocate.setShortcuts(self._args.shortcut_keymaps[11])
self.actionDerive.setShortcuts(self._args.shortcut_keymaps[12])
self.actionAttach.setShortcuts(self._args.shortcut_keymaps[13])
-
self.actionWheel.setShortcuts(self._args.shortcut_keymaps[52])
self.actionImage.setShortcuts(self._args.shortcut_keymaps[53])
self.actionBoard.setShortcuts(self._args.shortcut_keymaps[54])
self.actionDepot.setShortcuts(self._args.shortcut_keymaps[55])
-
self.actionSettings.setShortcuts(self._args.shortcut_keymaps[3])
self.actionAll.setShortcuts(self._args.shortcut_keymaps[49])
-
for skey in self._args.shortcut_keymaps[4]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.close_with_verify)
-
for skey in self._args.shortcut_keymaps[5]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.close_without_save)
-
for skey in self._args.shortcut_keymaps[14]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_cube_table.clipboard_act("rgb"))
-
for skey in self._args.shortcut_keymaps[15]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_cube_table.clipboard_act("hsv"))
-
for skey in self._args.shortcut_keymaps[16]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_cube_table.clipboard_act("hec"))
-
for skey in self._args.shortcut_keymaps[17]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_wheel.clipboard_all("rgb"))
-
for skey in self._args.shortcut_keymaps[18]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_wheel.clipboard_all("hsv"))
-
for skey in self._args.shortcut_keymaps[19]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_wheel.clipboard_all("hec"))
-
for actv_idx, skey_idx in zip(range(5), (25, 24, 23, 26, 27)):
for skey in self._args.shortcut_keymaps[skey_idx]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_cube_table.active_by_num(actv_idx))
-
for skey in self._args.shortcut_keymaps[28]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_transformation.move_up)
-
for skey in self._args.shortcut_keymaps[29]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_transformation.move_down)
-
for skey in self._args.shortcut_keymaps[30]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_transformation.move_left)
-
for skey in self._args.shortcut_keymaps[31]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_transformation.move_right)
-
for skey in self._args.shortcut_keymaps[34]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_transformation.reset_home)
-
for skey in self._args.shortcut_keymaps[32]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_transformation.zoom_in)
-
for skey in self._args.shortcut_keymaps[33]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._wget_transformation.zoom_out)
-
for skey in self._args.shortcut_keymaps[48]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self._chg_win_on_top)
-
for skey in self._args.shortcut_keymaps[47]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(lambda: self._inner_undo_or_redo(True))
-
for skey in self._args.shortcut_keymaps[56]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(lambda: self._inner_undo_or_redo(False))
-
self._wget_wheel.update_skey()
self._wget_image.update_skey()
self._wget_board.update_skey()
self._wget_depot.update_skey()
- # ---------- ---------- ---------- Event Funcs ---------- ---------- ---------- #
-
def closeEvent(self, event):
- """
- Actions before close Rickrack.
- """
-
if self._sys_argv["output"]:
self._wget_operation.dp_export(self._sys_argv["output"], True)
-
result_text = export_text([(self._args.sys_color_set, self._args.hm_rule, "Console Results", "", (time.time(), time.time()), self._args.sys_grid_locations, self._args.sys_grid_assitlocs, self._args.sys_grid_list, self._args.sys_grid_values),])
-
for line in result_text.split("\n"):
if line and len(line) > 3:
if line[2] in [str(i) for i in range(10)] and int(line[2]) == self._args.sys_activated_idx:
print("+ *{}".format(line[1:]))
-
else:
print("+ {}".format(line))
else:
print("+")
-
if self._save_settings_before_close and not self._sys_argv["temporary"]:
self.save_main_settings()
-
self._args.remove_temp_dir()
-
self._wget_wheel.close()
self._wget_image.close()
self._wget_depot.close()
-
event.accept()
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._info_descs = (
_translate("Rickrack", "About"),
_translate("Rickrack", "Version: {}"),
@@ -1998,12 +1458,12 @@ def _func_tr_(self):
_translate("Rickrack", "Visit Website"),
_translate("Rickrack", "Rickrack uses Qt version {} (PyQt version {}) licensed under GNU General Public License. Please see qt.io/licensing for an overview of Qt licensing."),
_translate("Rickrack", "All images, documents and translations in Rickrack code repository are licensed under Creative Commons Attribution-NonCommercial-ShareAlike License 4.0 (CC BY-NC-SA 4.0) unless stating additionally."),
- _translate("Rickrack", "Rickrack default uses LXGW WenKai font for interface display, which is an open-source Chinese font derived from Fontworks' Klee One. This font is open-sourced under SIL Open Font License 1.1."),
+ _translate("Rickrack", "Rickrack default uses Noto Sans font family for interface display. These fonts are open-sourced under SIL Open Font License 1.1."),
_translate("Rickrack", "Support Rickrack!"),
_translate("Rickrack", "{} ({})"),
_translate("Rickrack", "The internationalization (i18n) and localization (l10n) of Rickrack are based on Google Translate."),
+ _translate("Rickrack", "Download Full Fonts"),
)
-
self._status_descs = (
_translate("Rickrack", "Ready."),
_translate("Rickrack", "Image Size: {} x {}."),
@@ -2015,7 +1475,6 @@ def _func_tr_(self):
_translate("Rickrack", "Assistant Points Count for Current Control Points: {}."),
_translate("Rickrack", "Board Volume: Row {}, Col {}; Total {}, Index {}."),
)
-
self._color_descs = (
_translate("Rickrack", "Deep "),
_translate("Rickrack", "Snow "),
@@ -2038,7 +1497,6 @@ def _func_tr_(self):
_translate("Rickrack", "Orange"),
_translate("Rickrack", "Pink"),
)
-
_QColorDialog = (
_translate("QColorDialog", "Hu&e:"),
_translate("QColorDialog", "&Sat:"),
@@ -2055,7 +1513,6 @@ def _func_tr_(self):
_translate("QColorDialog", "&Custom colors"),
_translate("QColorDialog", "&Add to Custom Colors"),
)
-
_QPlatformTheme = (
_translate("QPlatformTheme", "OK"),
_translate("QPlatformTheme", "Save"),
@@ -2076,7 +1533,6 @@ def _func_tr_(self):
_translate("QPlatformTheme", "Reset"),
_translate("QPlatformTheme", "Restore Defaults"),
)
-
_QLineEdit = (
_translate("QLineEdit", "&Undo"),
_translate("QLineEdit", "&Redo"),
@@ -2086,86 +1542,61 @@ def _func_tr_(self):
_translate("QLineEdit", "Delete"),
_translate("QLineEdit", "Select All"),
)
-
_QAbstractSpinBox = (
_translate("QAbstractSpinBox", "&Select All"),
_translate("QAbstractSpinBox", "&Step up"),
_translate("QAbstractSpinBox", "Step &down"),
)
-
-
if __name__ == "__main__":
argv_opts, argv_left = getopt(sys.argv[1:], "hvtr:i:o:w:e:l:p:", ["help", "version", "temporary", "reset=", "input=", "output=", "export=", "window=", "sequence=", "lang=", "locale=", "port="])
sys_argv = {"temporary": False, "reset": "", "input": None, "output": None, "window": -1, "lang": "", "port": None}
-
- # init args.
for opt_name,opt_value in argv_opts:
if opt_name in ("-h", "--help"):
print("\n+" + "-" * 34 + " Rickrack " + "-" * 34 + "+")
print(__HELP__)
sys.exit()
-
elif opt_name in ("-v", "--version"):
print("Rickrack {} ({})\n".format(__VERSION__[1:-1], __DATE__[1:-1]))
sys.exit()
-
elif opt_name in ("-t", "--temporary"):
sys_argv["temporary"] = True
-
elif opt_name in ("-r", "--reset"):
if opt_value.lower() in ("settings", "setting", "layout", "geometry", "set", "depot", "work", "all"):
sys_argv["reset"] = opt_value.lower()
-
elif opt_name in ("-i", "--input"):
if os.path.isfile(opt_value):
sys_argv["input"] = opt_value
-
elif opt_name in ("-o", "--output", "--export"):
if os.path.isdir(os.path.dirname(opt_value)) and opt_value.split(".")[-1] in ("dps", "txt", "aco", "ase", "gpl", "xml"):
sys_argv["output"] = opt_value
-
elif opt_name in ("-w", "--window"):
if opt_value and check_is_num(opt_value, length=3):
sys_argv["window"] = int(opt_value)
-
elif opt_name in ("-e", "--sequence"):
if opt_value and check_is_num(opt_value, length=7, scope=("0", "1")):
num = 0
-
for i in range(len(opt_value)):
num = num + int(opt_value[len(opt_value) - i - 1]) * 2 ** i
-
sys_argv["window"] = num
-
elif opt_name in ("-l", "--lang", "--locale"):
if len(opt_value) > 1:
sys_argv["lang"] = opt_value
-
elif opt_name in ("-p", "--port"):
if opt_value and check_is_num(opt_value, length=5):
port = int(opt_value)
-
if 0 < port < 65536:
sys_argv["port"] = port
-
if not sys_argv["input"] and argv_left and os.path.isfile(argv_left[-1]):
sys_argv["input"] = argv_left[-1]
-
- # high dpi.
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
-
- # init software.
+ QGuiApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
appctxt = ApplicationContext()
-
DPS = DPSplash(appctxt.get_resource('.'), sys_argv)
DPS.show()
-
DP = Rickrack(appctxt.get_resource('.'), sys_argv)
DP.show()
-
DPS.finish(DP)
DPS.deleteLater()
-
exit_code = appctxt.app.exec_()
sys.exit(exit_code)
diff --git a/src/main/python/ricore/args.py b/src/main/python/ricore/args.py
index 42def65..6a560bb 100644
--- a/src/main/python/ricore/args.py
+++ b/src/main/python/ricore/args.py
@@ -25,27 +25,12 @@
class Args(object):
- """
- Args object. Manage setting args.
- """
-
def __init__(self, resources, resetall=False, uselang=""):
- """
- Init Args object.
- """
-
- # software version.
- self.info_version_zh = "v2.8.27-x2d3s3-预览版"
- self.info_version_en = "v2.8.27-x2d3s3-pre"
-
- # update date.
- self.info_date_zh = "2023年6月25日"
- self.info_date_en = "June 25, 2023"
-
- # temporary dir.
+ self.info_version_zh = "v2.8.35-x3d3s3-预览版"
+ self.info_version_en = "v2.8.35-x3d3s3-pre"
+ self.info_date_zh = "2023年7月16日"
+ self.info_date_en = "July 16, 2023"
self.global_temp_dir = None
-
- # global args.
self.global_hm_rules = (
"analogous",
"monochromatic",
@@ -56,13 +41,11 @@ def __init__(self, resources, resetall=False, uselang=""):
"shades",
"custom",
)
-
self.global_overflows = (
"cutoff",
"return",
"repeat",
)
-
self.global_white_ref = (
((109.850, 100.000, 35.585), (111.144, 100.000, 35.200)),
((99.0927, 100.000, 85.313), (99.178, 100.000, 84.3493)),
@@ -85,292 +68,232 @@ def __init__(self, resources, resetall=False, uselang=""):
((100.966, 100.000, 64.370), (103.866, 100.000, 65.627)),
((108.046, 100.000, 39.228), (111.428, 100.000, 40.353)),
)
-
self.global_log = False
-
- # load languages.
all_langs = (
- "en", "ar", "be", "bg", "ca", "cs", "da", "de", "el", "eo",
- "es", "et", "fi", "fr", "hr", "hu", "is", "it", "iw", "ja",
- "ko", "lt", "lv", "mk", "nl", "no", "pl", "pt", "ro", "ru",
- "sh", "sk", "sl", "sq", "sr", "sv", "th", "tr", "uk", "vn",
+ "en", "ar", "be", "bg", "ca", "cs", "da", "de", "el", "eo",
+ "es", "et", "fi", "fr", "hr", "hu", "is", "it", "iw", "ja",
+ "ko", "lt", "lv", "mk", "nl", "no", "pl", "pt", "ro", "ru",
+ "sh", "sk", "sl", "sq", "sr", "sv", "th", "tr", "uk", "vn",
"zh",
)
-
lang_paths = [(41, "default"),]
-
langs_dir = os.sep.join((resources, "langs"))
if not os.path.isdir(langs_dir):
os.makedirs(langs_dir)
-
for lang in os.listdir(langs_dir):
if os.path.isfile(os.sep.join((langs_dir, lang))) and lang.split(".")[-1] == "qm":
glang = re.split("\.|_|-", lang)
-
while "" in glang:
glang.remove("")
-
if glang:
glang = glang[0].lstrip().rstrip()
-
else:
glang = ""
-
if glang in all_langs:
lang_paths.append((all_langs.index(glang), lang[:-3]))
-
self.usr_langs = tuple(lang_paths)
-
- # software information.
self.info_main_site = "https://eigenmiao.com/rickrack"
self.info_update_site = "https://github.com/eigenmiao/Rickrack/releases"
-
- # author information.
+ self.info_dissc_site = "https://github.com/eigenmiao/Rickrack/discussions?discussions_q="
+ self.info_font_site = "https://fonts.google.com/noto/fonts"
self.info_author_zh = "本征喵函数"
self.info_author_en = "Eigenmiao"
-
- # init settings.
- self.usr_store = os.sep.join((os.path.expanduser('~'), "Documents", "Rickrack"))
+ self.home_dir = os.path.expanduser('~')
+ self.doc_name = "Documents"
+ self.pic_name = "Pictures"
+ if not os.path.isfile(os.sep.join([self.home_dir, ".config", "user-dirs.dirs"])):
+ try:
+ with open(os.sep.join([self.home_dir, ".config", "user-dirs.dirs"]), "r") as f:
+ data = f.read().split()
+ except Exception as err:
+ data = []
+ for line in data:
+ if "DOCUMENTS" in line:
+ self.doc_name = line.split("\"")[-2].split("/")[-1]
+ elif "PICTURES" in line:
+ self.pic_name = line.split("\"")[-2].split("/")[-1]
+ self.usr_store = os.sep.join((self.home_dir, self.doc_name, "Rickrack"))
self.resources = resources
self.load_settings_failed = 0
-
self.init_settings()
-
- # init setable but not initable settings.
self.stab_ucells = tuple()
self.stab_column = 3
-
- # special system settings.
self.sys_activated_idx = 0
self.sys_activated_assit_idx = -1
self.sys_color_set = ColorSet(self.h_range, self.s_range, self.v_range, overflow=self.overflow, dep_wtp=self.dep_wtp)
self.sys_color_set.create(self.hm_rule)
-
- # load settings.
- self.geometry_args = None
-
+ self.geometry_args = ""
+ if os.path.isfile(os.sep.join((self.resources, "layouts.ini"))):
+ with open(os.sep.join((self.resources, "layouts.ini")), "r", encoding="utf-8") as f:
+ self.layouts = json.load(f)
+ else:
+ self.layouts = ("", "", "", "", "", "",)
if not resetall:
if self.store_loc:
self.load_settings(os.sep.join((self.resources, "settings.json")))
self.geometry_args = os.sep.join((self.resources, "geometry.ini"))
-
else:
self.load_settings(os.sep.join((self.usr_store, "settings.json")))
self.geometry_args = os.sep.join((self.usr_store, "geometry.ini"))
-
if uselang:
self.modify_settings("lang", uselang)
-
- # special system settings.
self.sys_category = 0
self.sys_channel = 0
-
self.sys_grid_locations = [(0.5, 0.5), (0.85, 0.85), (0.15, 0.85), (0.85, 0.15), (0.15, 0.15)]
self.sys_grid_assitlocs = [[], [], [], [], []]
self.sys_grid_list = [[], []]
self.sys_grid_values = {"col": 9, "ctp": ("r", "g", "b"), "sum_factor": 1.0, "dim_factor": 1.0, "assist_factor": 0.4, "rev_grid": False}
-
- # for choice requirement in server.
self.sys_choice_stat = []
-
- # for links in board and depot view.
self.sys_link_colors = [False, False]
-
- # for main and assit points in image view.
self.sys_color_locs = [None, None, None, None, None]
self.sys_assit_color_locs = [[], [], [], [], []]
self.sys_image_url = ""
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def init_settings(self):
- """
- Init default settings.
- """
-
- # load default language.
default_locale = locale.getdefaultlocale()[0]
default_locale = str(default_locale).lower() if default_locale else ""
-
user_prefer_locale = "en"
-
if len(default_locale) > 1:
self.lang = default_locale[:2]
-
else:
self.lang = user_prefer_locale
-
if self.lang not in [x[1] for x in self.usr_langs]:
if user_prefer_locale in [x[1] for x in self.usr_langs]:
self.lang = user_prefer_locale
-
else:
self.lang = "default"
-
if self.lang == "zh":
self.info_main_site = "https://eigenmiao.com/yanhuo"
-
elif self.lang in ("eo", "ru", "ja", "fr", "de", "es"):
self.info_main_site = "https://eigenmiao.com/yanhuo/{}.html".format(self.lang)
-
else:
self.info_main_site = "https://eigenmiao.com/rickrack"
-
- # load local store tag.
- self.store_loc = False
-
+ self.store_loc = True
if os.path.isfile(os.sep.join((self.resources, "settings.json"))):
try:
with open(os.sep.join((self.resources, "settings.json")), "r", encoding="utf-8") as sf:
uss = json.load(sf)
-
except Exception as err:
uss = None
-
if isinstance(uss, dict) and "store_loc" in uss:
self.store_loc = bool(uss["store_loc"])
-
- # need verify and mkdirs.
if self.store_loc:
self.usr_color = os.sep.join((self.resources, "MyColors"))
self.usr_image = os.sep.join((self.resources, "samples"))
-
else:
- self.usr_color = os.sep.join((os.path.expanduser('~'), "Documents", "Rickrack", "MyColors"))
- self.usr_image = os.sep.join((os.path.expanduser('~'), "Pictures"))
-
+ self.usr_color = os.sep.join((self.home_dir, self.doc_name, "Rickrack", "MyColors"))
+ self.usr_image = os.sep.join((self.home_dir, self.pic_name))
if not os.path.isdir(self.usr_color):
os.makedirs(self.usr_color)
-
if not os.path.isdir(self.usr_image):
os.makedirs(self.usr_image)
-
self.hm_rule = "analogous"
self.overflow = "return"
self.press_move = True
self.color_sys = 0
- self.show_rgb = True
- self.show_hsv = True
+ self.show_rgb = False
+ self.show_hsv = False
self.show_info_pts = [3, 3, 3]
-
self.h_range = (0.0, 360.0)
self.s_range = (0.2, 0.5)
self.v_range = (0.8, 1.0)
-
self.wheel_ratio = 0.8
self.volum_ratio = 0.8
self.cubic_ratio = 0.9
self.coset_ratio = 0.8
self.board_ratio = 0.9
-
self.s_tag_radius = 0.09
self.v_tag_radius = 0.09
-
self.rev_direct = True
-
self.zoom_step = 1.1
self.move_step = 5
-
self.rand_num = 10000
self.circle_dist = 12
-
- self.positive_wid = 3
- self.negative_wid = 3
- self.wheel_ed_wid = 3
-
+ self.positive_wid = 1
+ self.negative_wid = 1
+ self.wheel_ed_wid = 1
self.positive_color = (255, 255, 255)
- self.negative_color = ( 59, 59, 59)
- self.wheel_ed_color = ( 64, 64, 64)
-
+ self.negative_color = ( 0, 0, 0)
+ self.wheel_ed_color = ( 0, 0, 0)
# self.main_win_state = ""
# self.main_win_geometry = ""
-
self.max_history_files = 10
self.max_history_steps = 20
self.export_grid_extns = "_Grid"
self.export_swatch_ctp = "rgb"
-
self.r_prefix = ("", "")
self.rgb_prefix = ("(", ", ", ")")
self.hec_prefix = ("'#", "'")
self.lst_prefix = ("[", ", ", "]")
-
self.win_on_top = False
-
self.font_size = 12
- self.font_weight = 6
- self.font_family = ("LXGW WenKai",)
+ self.font_weight = 4
+ self.font_family = ("Noto Sans",)
self.bakgd_id = 0
- self.style_id = 4
-
+ self.style_id = 0
self.white_illuminant = 5
self.white_observer = 0
-
self.export_ase_type = "process"
-
self.shortcut_keymaps = (
- ("F1", "Alt+H", ), # 00 "Homepage"
- ("F2", "Alt+U", ), # 01 "Update"
- ("F3", "Alt+B", ), # 02 "About"
- ("`", "Alt+T", ), # 03 "Settings"
- ("Esc", ), # 04 "Close"
- ("Alt+Q", ), # 05 "No_Save_Close"
- ("Ctrl+O", "Alt+O", ), # 06 "Open"
- ("Ctrl+S", "Alt+S", ), # 07 "Save"
- ("Ctrl+I", "Alt+I", ), # 08 "Import"
- ("Ctrl+E", "Alt+E", ), # 09 "Export"
- ("Ctrl+W", "Alt+C", ), # 10 "Create"
- ("Ctrl+G", "Alt+L", ), # 11 "Locate"
- ("Ctrl+B", "Alt+D", ), # 12 "Derive"
- ("Ctrl+D", "Alt+A", ), # 13 "Attach"
- ("R", ), # 14 "Clipboard_Cur_RGB"
- ("H", ), # 15 "Clipboard_Cur_HSV"
- ("X", ), # 16 "Clipboard_Cur_Hec"
- ("Shift+R", ), # 17 "Clipboard_All_RGB"
- ("Shift+H", ), # 18 "Clipboard_All_HSV"
- ("Shift+X", ), # 19 "Clipboard_All_Hec"
- ("Ctrl+R", ), # 20 "Clipboard_Set_RGB"
- ("Ctrl+H", ), # 21 "Clipboard_Set_HSV"
- ("Ctrl+X", ), # 22 "Clipboard_Set_Hec"
- ("1", "6", ), # 23 "Activate_Color_2"
- ("2", "7", ), # 24 "Activate_Color_1"
- ("3", "8", ), # 25 "Activate_Color_0"
- ("4", "9", ), # 26 "Activate_Color_3"
- ("5", "0", ), # 27 "Activate_Color_4"
- ("Up", ), # 28 "Move_Up"
- ("Down", ), # 29 "Move_Down"
- ("Left", ), # 30 "Move_Left"
- ("Right", ), # 31 "Move_Right"
- ("=", "+", "*", ), # 32 "Zoom_In"
- ("-", "_", "/", ), # 33 "Zoom_Out"
- ("Home", ), # 34 "Reset_Home"
- ("End", ), # 35 "End"
- ("PgUp", ), # 36 "PageUp"
- ("PgDown", ), # 37 "PageDown"
- ("Insert", "I", ), # 38 "Insert"
- ("Del", ), # 39 "Delete"
- ("D", ), # 40 "Delete_Ver"
- ("F", ), # 41 "Show_Info"
- ("Tab", "S", ), # 42 "Switch"
- ("Space", "Ctrl+Space", ), # 43 "Show_Hide"
- ("Shift+Tab", ), # 44 "Gen_Clear"
- ("Ctrl+C", ), # 45 "Copy"
- ("Ctrl+V", ), # 46 "Paste"
- ("Ctrl+Z", "U", ), # 47 "Withdraw"
- ("Ctrl+T", ), # 48 "On_Top"
- ("Ctrl+A", ), # 49 "Show_Hide_All"
- ("F4", "Alt+Z", ), # 50 "Support"
- ("Ctrl+Tab", ), # 51 "Gen_Assit"
- ("F5", ), # 52 "Wheel_View"
- ("F6", ), # 53 "Image_View"
- ("F7", ), # 54 "Board_View"
- ("F8", ), # 55 "Depot_View"
- ("Shift+Z", "Z", ), # 56 "Redo"
+ ("F1", "Alt+H", ),
+ ("F2", "Alt+U", ),
+ ("F3", "Alt+B", ),
+ ("`", "Alt+T", ),
+ ("Esc", ),
+ ("Alt+Q", ),
+ ("Ctrl+O", "Alt+O", ),
+ ("Ctrl+S", "Alt+S", ),
+ ("Ctrl+I", "Alt+I", ),
+ ("Ctrl+E", "Alt+E", ),
+ ("Ctrl+W", "Alt+C", ),
+ ("Ctrl+G", "Alt+L", ),
+ ("Ctrl+B", "Alt+D", ),
+ ("Ctrl+D", "Alt+A", ),
+ ("R", ),
+ ("H", ),
+ ("X", ),
+ ("Shift+R", ),
+ ("Shift+H", ),
+ ("Shift+X", ),
+ ("Ctrl+R", ),
+ ("Ctrl+H", ),
+ ("Ctrl+X", ),
+ ("1", "6", ),
+ ("2", "7", ),
+ ("3", "8", ),
+ ("4", "9", ),
+ ("5", "0", ),
+ ("Up", ),
+ ("Down", ),
+ ("Left", ),
+ ("Right", ),
+ ("=", "+", "*", ),
+ ("-", "_", "/", ),
+ ("Home", ),
+ ("End", ),
+ ("PgUp", ),
+ ("PgDown", ),
+ ("Insert", "I", ),
+ ("Del", ),
+ ("D", ),
+ ("F", ),
+ ("Tab", "S", ),
+ ("Space", "Ctrl+Space", ),
+ ("Shift+Tab", ),
+ ("Ctrl+C", ),
+ ("Ctrl+V", ),
+ ("Ctrl+Z", "U", ),
+ ("Ctrl+T", ),
+ ("Ctrl+A", ),
+ ("F4", "Alt+Z", ),
+ ("Ctrl+Tab", ),
+ ("F5", ),
+ ("F6", ),
+ ("F7", ),
+ ("F8", ),
+ ("Shift+Z", "Z", ),
)
-
- self.info_aucc_site = "https://afdian.net/a/eigenmiao"
-
- # dependent args.
+ self.info_aucc_site = "https://eigenmiao.com/yanhuo/support.html"
self.dep_circle_dist_2 = self.circle_dist ** 2
self.dep_circle_dist_wid = self.circle_dist + (self.positive_wid + self.negative_wid) * 2
self.dep_circle_dist_wid_2 = self.dep_circle_dist_wid ** 2
@@ -380,17 +303,11 @@ def init_settings(self):
self.dep_wtp_rev_s, self.dep_wtp_rev_n = (("v", 2), ("s", 1))[self.dep_rtp]
def save_settings(self):
- """
- Save settings to file.
- """
-
- # saving args.
settings = {
"version": self.info_version_en,
"site": self.info_main_site,
"date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
}
-
items = (
"usr_color", "usr_image", "store_loc", "hm_rule", "overflow", "lang", "press_move", "color_sys",
"show_rgb", "show_hsv", "show_info_pts", "h_range", "s_range", "v_range",
@@ -403,34 +320,23 @@ def save_settings(self):
"win_on_top", "font_size", "font_weight", "font_family", "bakgd_id", "style_id", "white_illuminant", "white_observer", "export_ase_type",
"shortcut_keymaps",
)
-
for item in items:
value = getattr(self, item)
settings[item] = value
-
- # saving color depot.
- # depot is stored as freestanding files.
-
- # storing.
if self.store_loc:
try:
with open(os.sep.join((self.resources, "settings.json")), "w", encoding="utf-8") as sf:
json.dump(settings, sf, ensure_ascii=False)
-
except Exception as err:
if self.global_log:
print(err)
-
- self.store_loc = False
-
+ self.store_loc = True
else:
try:
with open(os.sep.join((self.usr_store, "settings.json")), "w", encoding="utf-8") as sf:
json.dump(settings, sf, ensure_ascii=False)
-
with open(os.sep.join((self.resources, "settings.json")), "w", encoding="utf-8") as sf:
json.dump({"store_loc": False, "lang": self.lang}, sf, ensure_ascii=False)
-
except Exception as err:
if self.global_log:
print(err)
@@ -491,393 +397,242 @@ def modify_settings(self, item, value):
"export_ase_type": lambda vl: self.pfmt_str_in_list(vl, ("spot", "global", "process"), self.export_ase_type),
"shortcut_keymaps": lambda vl: self.pfmt_shortcut_keymaps(vl, self.shortcut_keymaps),
}
-
if item in items:
setattr(self, item, items[item](value))
-
if item in ("circle_dist", "positive_wid", "negative_wid"):
self.dep_circle_dist_2 = self.circle_dist ** 2
self.dep_circle_dist_wid = self.circle_dist + (self.positive_wid + self.negative_wid) * 2
self.dep_circle_dist_wid_2 = self.dep_circle_dist_wid ** 2
-
elif item == "color_sys":
self.dep_rtp = self.color_sys % 2
self.dep_wtp = self.color_sys // 2
self.dep_wtp_s, self.dep_wtp_n = (("s", 1), ("v", 2))[self.dep_rtp]
self.dep_wtp_rev_s, self.dep_wtp_rev_n = (("v", 2), ("s", 1))[self.dep_rtp]
self.sys_color_set.set_color_system(self.dep_wtp)
-
elif item == "lang":
if self.lang == "zh":
self.info_main_site = "https://eigenmiao.com/yanhuo"
- self.info_aucc_site = "https://afdian.net/a/eigenmiao"
-
+ self.info_aucc_site = "https://eigenmiao.com/yanhuo/support.html"
+ self.info_dissc_site = "https://eigenmiao.com/yanhuo/discuss.html"
elif self.lang in ("eo", "ru", "ja", "fr", "de", "es"):
self.info_main_site = "https://eigenmiao.com/yanhuo/{}.html".format(self.lang)
- self.info_aucc_site = "https://ko-fi.com/eigenmiao"
-
+ self.info_aucc_site = "https://eigenmiao.com/rickrack/support.html"
+ self.info_dissc_site = "https://eigenmiao.com/rickrack/discuss.html"
else:
self.info_main_site = "https://eigenmiao.com/rickrack"
- self.info_aucc_site = "https://ko-fi.com/eigenmiao"
+ self.info_aucc_site = "https://eigenmiao.com/rickrack/support.html"
+ self.info_dissc_site = "https://eigenmiao.com/rickrack/discuss.html"
def backup_settings(self, settings_file):
- """
- Move settings.json as settings_bak.json when load settings failed.
-
- Parameters:
- settings_file - string. settings file path.
- """
-
if os.path.isfile(settings_file):
if os.path.isfile(settings_file[:-5] + "_bak.json"):
os.remove(settings_file[:-5] + "_bak.json")
-
os.rename(settings_file, settings_file[:-5] + "_bak.json")
def load_settings(self, settings_file):
- """
- Modify default settings by user settings.
-
- Parameters:
- settings_file - string. settings file path.
- """
-
uss = {}
-
if os.path.isfile(settings_file):
try:
with open(settings_file, "r", encoding="utf-8") as sf:
uss = json.load(sf)
-
except Exception as err:
self.load_settings_failed = 1
self.backup_settings(settings_file)
-
if isinstance(uss, dict) and uss:
if "version" in uss:
vid = self.check_version_x(uss["version"])
-
- if vid == 0 or vid > 2:
+ if vid < 3:
+ uss["circle_dist"] = 16
+ uss["font_size"] = 16
+ uss["font_family"] = ["Noto Sans", ", Noto Sans SC", "Noto Sans TC", "Noto Sans JP"]
+ if vid == 0 or vid > 3:
self.load_settings_failed = 2
self.backup_settings(settings_file)
uss = {}
-
else:
self.load_settings_failed = 3
self.backup_settings(settings_file)
uss = {}
-
if "style_id" in uss and "bakgd_id" not in uss:
uss["bakgd_id"] = 0
-
for item in uss:
self.modify_settings(item, uss[item])
- # ---------- ---------- ---------- Classmethods ---------- ---------- ---------- #
-
def pfmt_path(self, value, default):
- """
- Parse directory path.
- """
-
ans = str(value)
-
if os.path.isdir(ans):
return ans
-
return default
def pfmt_info_list(self, value, default):
- """
- [0-3, 0-3, 0-3]
- """
-
if isinstance(value, (tuple, list)) and len(value) > 2:
w, i, b = value[:3]
-
if not (isinstance(w, int) and 0 <= w < 4):
w = default[0]
-
if not (isinstance(i, int) and 0 <= i < 4):
i = default[1]
-
if not (isinstance(b, int) and 0 <= b < 4):
b = default[2]
-
return [w, i, b]
-
return default
def pfmt_num_pair_in_scope(self, value, scope, dtype, default):
- """
- Parse number pair in scope.
- """
-
try:
ans = (dtype(value[0]), dtype(value[1]))
-
except Exception as err:
ans = None
-
if ans != None and scope[0] <= ans[0] <= scope[1] and scope[0] <= ans[1] <= scope[1] and ans[0] <= ans[1]:
return ans
-
return default
def pfmt_str_in_list(self, value, lst, default):
- """
- Parse string in list.
- """
-
ans = str(value)
-
if ans in lst:
return ans
-
return default
def pfmt_num_in_scope(self, value, scope, dtype, default):
- """
- Parse number in scope.
- """
-
try:
ans = dtype(value)
-
except Exception as err:
ans = None
-
if ans != None and scope[0] <= ans <= scope[1]:
return ans
-
return default
def pfmt_value(self, value, dtype, default):
- """
- Parse value in designed dtype.
- """
-
try:
ans = dtype(value)
-
except Exception as err:
ans = None
-
if ans != None:
return ans
-
return default
def pfmt_file_name(self, value, default):
- """
- Parse string without special chars.
- """
-
name_stri = re.split(r"[\v\a\f\n\r\t!@#$%^&\*]", str(value))
-
while "" in name_stri:
name_stri.remove("")
-
if name_stri:
name_stri = name_stri[0].lstrip().rstrip()
-
else:
name_stri = ""
-
if name_stri:
return name_stri
-
return default
def pfmt_rgb_color(self, value, default):
- """
- Parse value in designed color.
- """
-
try:
ans = (int(value[0]), int(value[1]), int(value[2]))
-
except Exception as err:
ans = None
-
if ans != None and 0 <= ans[0] <= 255 and 0 <= ans[2] <= 255 and 0 <= ans[2] <= 255:
return ans
-
return default
def pfmt_stab_ucells(self, value):
- """
- Parse value in designed color.
- """
-
stab_ucells = []
-
try:
for cslst in value:
colors = []
-
for color in cslst[0]:
ans = (float(color[0]), float(color[1]), float(color[2]))
-
if 0.0 <= ans[0] <= 360.0 and 0.0 <= ans[2] <= 1.0 and 0.0 <= ans[2] <= 1.0:
colors.append(ans)
-
else:
break
-
hm_rule = str(cslst[1])
-
if hm_rule not in self.global_hm_rules:
hm_rule = ""
-
if len(colors) == 5 and hm_rule:
cr_name = "" if len(cslst) < 3 else str(cslst[2])
cr_desc = "" if len(cslst) < 4 else str(cslst[3])
cr_time = (-1.0, -1.0) if len(cslst) < 5 else (float(cslst[4][0]), float(cslst[4][1]))
stab_ucells.append((tuple(colors), hm_rule, cr_name, cr_desc, cr_time))
-
except Exception as err:
if self.global_log:
print(err)
-
print(b"\xd1\xe6\xbb\xf0\xca\xae\xb6\xfe\xbe\xed\xa3\xac\xb1\xbe\xd5\xf7\xdf\xf7\xba\xaf\xca\xfd".decode("gbk"))
print()
-
return stab_ucells
def pfmt_prefix(self, prefix, length, default):
- """
- Parse r g b prefix.
- """
-
if isinstance(prefix, (tuple, list)) and len(prefix) == length:
is_a_prefix = True
-
for stri in prefix:
if not isinstance(stri, str):
is_a_prefix = False
break
-
if is_a_prefix:
return tuple(prefix)
-
return default
def pfmt_shortcut_keymaps(self, value, default):
- """
- Parse shortcut keymaps.
- """
-
if isinstance(value, (tuple, list)) and isinstance(default, (tuple, list)) and len(value) == len(default):
shortcuts = []
used_names = []
-
for skey_idx in range(len(default)):
if isinstance(value[skey_idx], (tuple, list)):
cked_names = [check_key(name) for name in value[skey_idx]]
-
else:
cked_names = default[skey_idx]
-
rved_names = []
-
for name in cked_names:
if name and name not in used_names:
used_names.append(name)
rved_names.append(name)
-
shortcuts.append(tuple(rved_names))
-
return tuple(shortcuts)
-
return default
-
@classmethod
- def check_version_x(cls, version):
- """
- Check if settings file version is compatible.
- """
+ def check_version_x(cls, version):
ans = re.match(r"^v.+?-x(\d+)d.+?s.+-.*", str(version))
-
if ans:
return int(ans.group(1))
-
elif re.match(r"^v2\.[12].*", str(version)):
return 1
-
else:
return 0
-
@classmethod
- def check_version_d(cls, version):
- """
- Check if color depot file version is compatible.
- """
+ def check_version_d(cls, version):
ans = re.match(r"^v.+?-x.+?d(\d+)s.+-.*", str(version))
-
if ans:
return int(ans.group(1))
-
elif re.match(r"^v2\.[12].*", str(version)):
return 1
-
else:
return 0
-
@classmethod
- def check_version_s(cls, version):
- """
- Check if color set file version is compatible.
- """
+ def check_version_s(cls, version):
ans = re.match(r"^v.+?-x.+?d.+?s(\d+).*-.*", str(version))
-
if ans:
return int(ans.group(1))
-
elif re.match(r"^v2\.[12].*", str(version)):
return 1
-
else:
return 0
def check_temp_dir(self):
- """
- Check if temporary directory valid.
- """
-
return self.global_temp_dir and self.global_temp_dir.isValid() and os.path.isdir(self.global_temp_dir.path())
def remove_temp_dir(self):
- """
- Remove temporary directory.
- """
-
if not self.global_temp_dir:
return
-
temp_dir = self.global_temp_dir.path()
self.global_temp_dir.remove()
-
if os.path.isdir(temp_dir):
try:
shutil.rmtree(temp_dir, ignore_errors=True)
-
except Exception as err:
pass
-
class TestArgs(unittest.TestCase):
- """
- Test Args object.
- """
-
def test_check_version_x(self):
items = (
("v2.2.8-pre", 1),
-
("v2.3.0-x2d1s1-pre", 2),
("v2.3.0-x1d2s1-pre", 1),
("v2.3.0-x1d1s2-pre", 1),
@@ -887,7 +642,6 @@ def test_check_version_x(self):
("v2.3.0-x123d1s1-pre", 123),
("v2.3.0-x1d123s1-pre", 1),
("v2.3.0-x1d1s123-pre", 1),
-
("v2.3.0-x2d1s1k3-pre", 2),
("v2.3.0-x1d2s1k3-pre", 1),
("v2.3.0-x1d1s2k3-pre", 1),
@@ -897,7 +651,6 @@ def test_check_version_x(self):
("v2.3.0-x123d1s1r-pre", 123),
("v2.3.0-x1d123s1r-pre", 1),
("v2.3.0-x1d1s123r-pre", 1),
-
("v2.3.0-x2-pre", 0),
("v2.3.0-x1-pre", 0),
("v2.3.0-x1-pre", 0),
@@ -908,14 +661,12 @@ def test_check_version_x(self):
("v2.3.0-x1d1r-pre", 0),
("v2.3.0-x1d1r-pre", 0),
)
-
for itm, ans in items:
self.assertEqual(Args.check_version_x(itm), ans, msg=itm)
def test_check_version_d(self):
items = (
("v2.2.8-pre", 1),
-
("v2.3.0-x2d1s1-pre", 1),
("v2.3.0-x1d2s1-pre", 2),
("v2.3.0-x1d1s2-pre", 1),
@@ -925,7 +676,6 @@ def test_check_version_d(self):
("v2.3.0-x123d1s1-pre", 1),
("v2.3.0-x1d123s1-pre", 123),
("v2.3.0-x1d1s123-pre", 1),
-
("v2.3.0-x2d1s1k3-pre", 1),
("v2.3.0-x1d2s1k3-pre", 2),
("v2.3.0-x1d1s2k3-pre", 1),
@@ -935,7 +685,6 @@ def test_check_version_d(self):
("v2.3.0-x123d1s1r-pre", 1),
("v2.3.0-x1d123s1r-pre", 123),
("v2.3.0-x1d1s123r-pre", 1),
-
("v2.3.0-d1-pre", 0),
("v2.3.0-d2-pre", 0),
("v2.3.0-d1-pre", 0),
@@ -946,14 +695,12 @@ def test_check_version_d(self):
("v2.3.0-d123r-pre", 0),
("v2.3.0-d1s1r-pre", 0),
)
-
for itm, ans in items:
self.assertEqual(Args.check_version_d(itm), ans, msg=itm)
def test_check_version_s(self):
items = (
("v2.2.8-pre", 1),
-
("v2.3.0-x2d1s1-pre", 1),
("v2.3.0-x1d2s1-pre", 1),
("v2.3.0-x1d1s2-pre", 2),
@@ -963,7 +710,6 @@ def test_check_version_s(self):
("v2.3.0-x123d1s1-pre", 1),
("v2.3.0-x1d123s1-pre", 1),
("v2.3.0-x1d1s123-pre", 123),
-
("v2.3.0-x2d1s1k3-pre", 1),
("v2.3.0-x1d2s1k3-pre", 1),
("v2.3.0-x1d1s2k3-pre", 2),
@@ -973,7 +719,6 @@ def test_check_version_s(self):
("v2.3.0-x123d1s1r-pre", 1),
("v2.3.0-x1d123s1r-pre", 1),
("v2.3.0-x1d1s123r-pre", 123),
-
("v2.3.0-s1-pre", 0),
("v2.3.0-s1-pre", 0),
("v2.3.0-s2-pre", 0),
@@ -984,10 +729,7 @@ def test_check_version_s(self):
("v2.3.0-23s1r-pre", 0),
("v2.3.0-s123r-pre", 0),
)
-
for itm, ans in items:
self.assertEqual(Args.check_version_s(itm), ans, msg=itm)
-
-
if __name__ == "__main__":
unittest.main()
diff --git a/src/main/python/ricore/check.py b/src/main/python/ricore/check.py
index 58bb185..73ee6a4 100644
--- a/src/main/python/ricore/check.py
+++ b/src/main/python/ricore/check.py
@@ -18,218 +18,135 @@
def check_key(name):
- """
- Check the name of keymap.
- """
-
if isinstance(name, str):
if name == "+":
return name
-
else:
nsplit = name.split("+")
-
if len(nsplit) == 1:
if nsplit[0] and nsplit[0] in [i.upper() for i in [chr(32 + i) for i in range(95)]] + ["Space", "Tab", "Esc", "Up", "Down", "Left", "Right", "PgUp", "PgDown", "Home", "End", "Insert", "Del"] + ["F{}".format(i + 1) for i in range(12)]:
return name
-
elif len(nsplit) == 2:
if nsplit[0] and nsplit[1] and nsplit[0] in ("Shift", "Alt", "Ctrl") and nsplit[1] in [i.upper() for i in [chr(32 + i) for i in range(95)]] + ["Space", "Tab", "Del", "Insert"]:
return name
-
return None
def check_file_name(name):
- """
- Parse string without special chars for file name.
- """
-
name_stri = ""
allow_chars = [chr(48 + i) for i in range(10)] + [chr(65 + i) for i in range(26)] + [chr(97 + i) for i in range(26)] + ["(", ")", "[", "]", "_", "-", "+", "=", ".", ",", " "]
-
for stri in str(name):
if stri in allow_chars:
name_stri = name_stri + stri
-
return name_stri.lstrip().rstrip()
def check_is_num(num_str, length=0, scope=[str(i) for i in range(10)]):
- """
- Parse if is a number string.
- """
-
stri = str(num_str)
is_num = True
-
if isinstance(length, int) and length > 0 and len(stri) > length:
is_num = False
-
if is_num:
for num in stri:
if num not in scope:
is_num = False
break
-
return is_num
def check_nonempt_str_lst(str_lst):
- """
- Parse not empty string list.
- """
-
fmt_lst = []
-
if isinstance(str_lst, (tuple, list)):
for vl in str_lst:
str_vl = check_file_name(vl)
-
if str_vl:
fmt_lst.append(str_vl)
-
return tuple(fmt_lst)
def check_image_desc(desc, parse_full_locs=True):
- """
- Parse image url and full loc from desc.
- """
-
if "::" not in desc:
return "", []
-
image_url = ""
full_locs = [[], [], [], [], []]
-
items = str(desc).split("::")
-
for pre_item in items:
item = ""
-
if pre_item[:3] == "img" and "=" in pre_item:
item = pre_item.split("=")[1].lstrip().rstrip()
-
else:
continue
-
if os.path.isfile(item) and item.split(".")[-1] in ("png", "bmp", "jpg", "jpeg", "tif", "tiff", "webp"):
image_url = str(item)
-
break
-
if image_url and parse_full_locs:
for pre_item in items:
item = ""
-
if pre_item[:3] == "loc" and "=" in pre_item:
item = pre_item.split("=")[1].lstrip().rstrip()
-
else:
continue
-
if check_is_num(item, scope=[str(i) for i in range(10)] + [".", ",", ";", "N"]):
item_str_lst = item.split(";;")
-
if len(item_str_lst) == 5:
for idx in range(5):
loc_str_lst = item_str_lst[idx].split(";")
-
for loc_str in loc_str_lst:
if loc_str == "N":
full_locs[idx].append(None)
-
else:
loc = loc_str.split(",")
-
if len(loc) == 2 and check_is_num(loc[0], scope=[str(i) for i in range(10)] + [".",]) and check_is_num(loc[1], scope=[str(i) for i in range(10)] + [".",]) and loc[0].count(".") < 2 and loc[1].count(".") < 2:
loc = (float(loc[0]), float(loc[1]))
-
if 0.0 <= loc[0] <= 1.0 and 0.0 <= loc[1] <= 1.0:
full_locs[idx].append(loc)
-
else:
return image_url, []
-
else:
full_locs = [[], [], [], [], []]
-
if full_locs[0] or full_locs[1] or full_locs[2] or full_locs[3] or full_locs[4]:
break
-
else:
return image_url, []
-
return image_url, full_locs
def fmt_name(name):
- """
- Delete prefix and endfix of name.
- """
-
stri = str(name).lstrip().rstrip()
stri_prefix = ("Rickrack ", "Rickrack-", "Rickrack:")
stri_endfix = tuple([str(i) for i in range(10)] + ["-", ":", " "])
-
while len(stri) >= 9 and stri[:9] in stri_prefix:
stri = stri[9:].lstrip()
-
while len(stri) >= 1 and stri[-1] in stri_endfix:
stri = stri[:-1]
-
if stri:
return stri
-
else:
return "Rickrack"
def fmt_im_time(im_time):
- """
- Verify and normalize value im_time.
-
- Args:
- im_time (tuple or list): default value.
-
- Returns:
- corrected time.
- """
-
current_time = time.time()
-
init_time = 0
modify_time = 0
-
if isinstance(im_time, (tuple, list)):
if len(im_time) > 1:
init_time, modify_time = im_time[:2]
-
else:
init_time = im_time[0]
modify_time = 0
-
elif isinstance(im_time, (float, int)):
init_time = im_time
modify_time = 0
-
else:
init_time = 0
modify_time = 0
-
if isinstance(init_time, (int, float)):
init_time = float(init_time)
else:
init_time = 0
-
if isinstance(modify_time, (int, float)):
modify_time = float(modify_time)
else:
modify_time = 0
-
init_time = 0 if init_time < 0 else init_time
init_time = current_time if init_time > current_time else init_time
-
modify_time = 0 if modify_time < 0 else modify_time
modify_time = current_time if modify_time > current_time else modify_time
-
modify_time = init_time if modify_time < init_time else modify_time
-
cr_time = (init_time, modify_time)
-
return cr_time
diff --git a/src/main/python/ricore/color.py b/src/main/python/ricore/color.py
index 87d3e4d..5f18a71 100644
--- a/src/main/python/ricore/color.py
+++ b/src/main/python/ricore/color.py
@@ -19,1269 +19,687 @@
class FakeColor(object):
- """
- FakeColor object. Storing rgb, hsv and hex code (hec) color without functional methods.
- """
-
def __init__(self, rgb, hsv, hec):
- """
- Init FakeColor ojbect.
-
- Args:
- rgb (tuple or list): rgb color.
- rgb (tuple or list): hsv color.
- hec (str): hex code (hec).
- """
-
self.rgb = Color.fmt_rgb(rgb)
self.hsv = Color.fmt_hsv(hsv)
self.hec = Color.fmt_hec(hec)
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def export(self):
- """
- Export color in dict type (for json file).
-
- Returns:
- color dict {"rgb": rgb_color_list, "hsv": hsv_color_list, "hex_code": hex code (hec)}.
- """
-
return {"rgb": self.rgb.tolist(), "hsv": self.hsv.tolist(), "hex_code": self.hec}
-
class Color(object):
- """
- Color object. Storing rgb, hsv and hex code (hec) color.
- """
-
def __init__(self, item, tp="color", overflow="cutoff"):
- """
- Init Color ojbect.
-
- Args:
- item (tuple, list, str or Color): rgb, hsv, hex code (hec) or another Color object.
- tp (str): type of color, in "rgb", "hsv", "hec" and "color".
- overflow (str): method to manipulate overflowed s and v values, in "cutoff", "return" and "repeat".
- """
-
self.set_overflow(overflow)
-
if isinstance(tp, str) and tp in ("rgb", "hsv", "hec", "color"):
self.setti(item, tp)
-
else:
raise ValueError("expect tp in str type and list 'rgb', 'hsv', 'hec' and 'color': {}.".format(tp))
- # ---------- ---------- ---------- Setting and Getting Funcs ---------- ---------- ---------- #
-
def setti(self, item, tp):
- """
- Set color item.
-
- Args:
- item (tuple, list, str, int, float or Color): rgb, hsv, hex code (hec), r, g, b, h, s, v or another Color object.
- tp (str): type of color, in "rgb", "hsv", "hec", "r", "g", "b", "h", "s", "v" and "color".
- """
-
if not isinstance(tp, str):
raise ValueError("expect tp in str type: {}.".format(tp))
-
if tp.lower() == "color":
if isinstance(item, (Color, FakeColor)):
self._rgb, self._hsv, self._hec = self.fmt_rgb(item.rgb), self.fmt_hsv(item.hsv), self.fmt_hec(item.hec)
-
else:
raise ValueError("expect item in Color type: {}.".format(item))
-
elif tp.lower() == "rgb":
self._rgb = self.fmt_rgb(item)
self._hsv = self.rgb2hsv(self._rgb)
self._hec = self.rgb2hec(self._rgb)
-
elif tp.lower() == "hsv":
self._hsv = self.fmt_hsv(item, overflow=self._overflow)
self._rgb = self.hsv2rgb(self._hsv)
self._hec = self.hsv2hec(self._hsv)
-
elif tp.lower() == "hec":
self._hec = self.fmt_hec(item)
self._rgb = self.hec2rgb(self._hec)
self._hsv = self.hec2hsv(self._hec)
-
elif tp.lower() == "r":
rgb = list(self._rgb)
rgb[0] = item
self.setti(rgb, "rgb")
-
elif tp.lower() == "g":
rgb = list(self._rgb)
rgb[1] = item
self.setti(rgb, "rgb")
-
elif tp.lower() == "b":
rgb = list(self._rgb)
rgb[2] = item
self.setti(rgb, "rgb")
-
elif tp.lower() == "h":
hsv = list(self._hsv)
hsv[0] = item
self.setti(hsv, "hsv")
-
elif tp.lower() == "s":
hsv = list(self._hsv)
hsv[1] = item
self.setti(hsv, "hsv")
-
elif tp.lower() == "v":
hsv = list(self._hsv)
hsv[2] = item
self.setti(hsv, "hsv")
-
else:
raise ValueError("expect tp in list 'rgb', 'hsv', 'hec', 'r', 'g', 'b', 'h', 's', 'v' and 'color'.")
def getti(self, tp):
- """
- Get color item.
-
- Args:
- tp (str): type of color, in "rgb", "hsv", "hec", "r", "g", "b", "h", "s", "v" and "color".
-
- Returns:
- rgb, hsv, hex code (hec), r, g, b, h, s, v or another Color object.
- """
-
if not isinstance(tp, str):
raise ValueError("expect tp in str type: {}.".format(tp))
-
if tp.lower() == "color":
return Color(self)
-
elif tp.lower() == "rgb":
return tuple(self._rgb)
-
elif tp.lower() == "hsv":
return tuple(self._hsv)
-
elif tp.lower() == "hec":
return str(self._hec)
-
elif tp.lower() == "r":
return int(self._rgb[0])
-
elif tp.lower() == "g":
return int(self._rgb[1])
-
elif tp.lower() == "b":
return int(self._rgb[2])
-
elif tp.lower() == "h":
return float(self._hsv[0])
-
elif tp.lower() == "s":
return float(self._hsv[1])
-
elif tp.lower() == "v":
return float(self._hsv[2])
-
else:
raise ValueError("expect tp in list 'rgb', 'hsv', 'hec', 'r', 'g', 'b', 'h', 's', 'v' and 'color'.")
def set_overflow(self, overflow):
- """
- Set the overflow method.
-
- Args:
- overflow (str): method to manipulate overflowed s and v values, in "cutoff", "return" and "repeat".
- """
-
if isinstance(overflow, str) and overflow in ("cutoff", "return", "repeat"):
self._overflow = str(overflow)
-
else:
raise ValueError("expect value in str type and list 'cutoff', 'return', 'repeat': {}.".format(overflow))
def get_overflow(self):
- """
- Get the overflow method.
- """
-
return str(self._overflow)
- # ---------- ---------- ---------- Inner Funcs ---------- ---------- ---------- #
-
def __str__(self):
- """
- Str format.
- """
-
return "Color(hec {})".format(self.hec)
def __repr__(self):
- """
- Repr format.
- """
-
return "Color(hec {})".format(self.hec)
-
'''
- def __eq__(self, other):
- """
- Compare two colors by equal.
-
- Args:
- other (Color): another Color object for compare.
-
- Returns:
- True or False.
- """
+ def __eq__(self, other):
if isinstance(other, Color):
return self._hec == other.hec
-
else:
raise ValueError("expect other in Color type: {}.".format(other))
def __ne__(self, other):
- """
- Compare two colors by not equal.
-
- Args:
- other (Color): another Color object for compare.
-
- Returns:
- True or False.
- """
-
if isinstance(other, Color):
return self._hec != other.hec
-
else:
raise ValueError("expect other in Color type: {}.".format(other))
'''
-
- # ---------- ---------- ---------- Properties and Setters ---------- ---------- ---------- #
-
@property
+
def rgb(self):
return self.getti("rgb")
-
@property
+
def hsv(self):
return self.getti("hsv")
-
@property
+
def hec(self):
return self.getti("hec")
-
@property
+
def r(self):
return self.getti("r")
-
@property
+
def g(self):
return self.getti("g")
-
@property
+
def b(self):
return self.getti("b")
-
@property
+
def h(self):
return self.getti("h")
-
@property
+
def s(self):
return self.getti("s")
-
@property
+
def v(self):
return self.getti("v")
-
@property
+
def color(self):
return self.getti("color")
-
@rgb.setter
+
def rgb(self, item):
self.setti(item, "rgb")
-
@hsv.setter
+
def hsv(self, item):
self.setti(item, "hsv")
-
@hec.setter
+
def hec(self, item):
self.setti(item, "hec")
-
@r.setter
+
def r(self, item):
self.setti(item, "r")
-
@g.setter
+
def g(self, item):
self.setti(item, "g")
-
@b.setter
+
def b(self, item):
self.setti(item, "b")
-
@h.setter
+
def h(self, item):
self.setti(item, "h")
-
@s.setter
+
def s(self, item):
self.setti(item, "s")
-
@v.setter
+
def v(self, item):
self.setti(item, "v")
-
@color.setter
+
def color(self, item):
self.setti(item, "color")
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def export(self):
- """
- Export color in dict type (for json file).
-
- Returns:
- color dict {"rgb": rgb_color_list, "hsv": hsv_color_list, "hex_code": hex code (hec)}.
- """
-
return {"rgb": self._rgb.tolist(), "hsv": self._hsv.tolist(), "hex_code": self._hec}
def ref_h(self, hue):
- """
- Get reference hue angle by hue.
-
- Args:
- hue (int or float): hue value.
-
- Returns:
- relative hue angle.
- """
-
if self.h < 180.0:
if hue < self.h + 180.0:
return hue - self.h
-
else:
return hue - (self.h + 360.0)
-
else:
if hue < self.h - 180.0:
return hue - (self.h - 360.0)
-
else:
return hue - self.h
def ref_h_array(self, hue_array):
- """
- Get reference hue angle array by hue.
-
- Args:
- hue (int or float): hue array value.
-
- Returns:
- relative hue angle array.
- """
-
data = np.array(hue_array, dtype=np.float64)
-
if self.h < 180.0:
p1 = np.where(data < self.h + 180.0)
p2 = np.where(data >= self.h + 180.0)
-
data[p1] = data[p1] - self.h
data[p2] = data[p2] - (self.h + 360.0)
-
else:
p1 = np.where(data < self.h - 180.0)
p2 = np.where(data >= self.h - 180.0)
-
data[p1] = data[p1] - (self.h - 360.0)
data[p2] = data[p2] - self.h
-
return data
-
- # ---------- ---------- ---------- Classmethods ---------- ---------- ---------- #
-
@classmethod
- def fmt_rgb(cls, rgb):
- """
- Class method. Format item to standard rgb color.
-
- Args:
- rgb (tuple or list): color item to be formated.
-
- Returns:
- standard rgb color.
- """
+ def fmt_rgb(cls, rgb):
if len(rgb) == 3:
_rgb = np.rint(rgb)
_rgb[np.where(_rgb < 0)] = 0
_rgb[np.where(_rgb > 255)] = 255
-
return _rgb.astype(np.uint8)
-
else:
raise ValueError("expect rgb color in length 3 and int: {}.".format(rgb))
-
@classmethod
- def fmt_rgb_array(cls, rgb_array):
- """
- Class method. Format item to standard rgb array.
-
- Args:
- rgb_array (3D array): array item to be formated.
-
- Returns:
- standard rgb array.
- """
+ def fmt_rgb_array(cls, rgb_array):
if isinstance(rgb_array, np.ndarray) and len(rgb_array.shape) == 3 and rgb_array.shape[2] == 3:
_rgb = np.rint(rgb_array)
_rgb[np.where(_rgb < 0)] = 0
_rgb[np.where(_rgb > 255)] = 255
-
return _rgb.astype(np.uint8)
-
else:
raise ValueError("expect rgb array in length 3: {}.".format(rgb_array))
-
@classmethod
- def fmt_hsv(cls, hsv, overflow="cutoff"):
- """
- Class method. Format item to standard hsv color.
-
- Args:
- hsv (tuple or list): color item to be formated.
- overflow (str): method to manipulate overflowed s and v values, in "cutoff", "return" and "repeat".
-
- Returns:
- standard hsv color.
- """
+ def fmt_hsv(cls, hsv, overflow="cutoff"):
if not isinstance(overflow, str):
raise ValueError("expect overflow in str type: {}.".format(overflow))
-
if len(hsv) == 3:
_h, _s, _v = hsv
-
if not (0.0 <= _s <= 1.0 and 0.0 <= _v <= 1.0):
if overflow.lower() == "cutoff":
_s = 0.0 if _s < 0.0 else _s
_s = 1.0 if _s > 1.0 else _s
_v = 0.0 if _v < 0.0 else _v
_v = 1.0 if _v > 1.0 else _v
-
elif overflow.lower() == "return":
_s = _s % 1.0 if _s // 1.0 % 2.0 == 0.0 else 1.0 - (_s % 1.0)
_v = _v % 1.0 if _v // 1.0 % 2.0 == 0.0 else 1.0 - (_v % 1.0)
-
elif overflow.lower() == "repeat":
_s = _s % 1.0
_v = _v % 1.0
-
else:
raise ValueError("expect overflow in list 'cutoff', 'return' and 'repeat'.")
-
_h = round(_h % 360.0 * 1E5) / 1E5
_s = round(_s * 1E5) / 1E5
_v = round(_v * 1E5) / 1E5
-
return np.array((_h, _s, _v), dtype=np.float32)
-
else:
raise ValueError("expect hsv color in length 3 and float: {}.".format(hsv))
-
@classmethod
- def fmt_hsv_array(cls, hsv_array):
- """
- Class method. Format item to standard hsv array.
-
- Args:
- hsv_array (3D array): array item to be formated.
-
- Returns:
- standard hsv array.
- """
+ def fmt_hsv_array(cls, hsv_array):
if isinstance(hsv_array, np.ndarray) and len(hsv_array.shape) == 3 and hsv_array.shape[2] == 3:
_h = hsv_array[:, :, 0]
_s = hsv_array[:, :, 1]
_v = hsv_array[:, :, 2]
-
_s[np.where(_s < 0.0)] = 0.0
_s[np.where(_s > 1.0)] = 1.0
_v[np.where(_v < 0.0)] = 0.0
_v[np.where(_v > 1.0)] = 1.0
-
_h = np.round(_h % 360.0 * 1E5) / 1E5
_s = np.round(_s * 1E5) / 1E5
_v = np.round(_v * 1E5) / 1E5
-
return np.stack((_h, _s, _v), axis=2).astype(np.float32)
-
else:
raise ValueError("expect hsv color in length 3: {}.".format(hsv_array))
-
@classmethod
- def fmt_hec(cls, hec):
- """
- Class method. Format item to standard hex code (hec) color.
-
- Args:
- hec (str): color item to be formated.
-
- Returns:
- standard hex code (hec) color.
- """
+ def fmt_hec(cls, hec):
_hec = re.match(r"[0-9A-F]+", str(hec).upper())
-
if _hec and len(_hec[0]) == 6:
return _hec[0]
-
else:
raise ValueError("expect hec color in hex type and length 6: {}.".format(hec))
-
@classmethod
- def fmt_lab(cls, lab):
- """
- Class method. Format item to standard lab color.
-
- Args:
- lab (tuple or list): color item to be formated.
-
- Returns:
- standard lab color.
- """
+ def fmt_lab(cls, lab):
if len(lab) == 3:
_l, _a, _b = lab
-
_l = 0.0 if _l < 0.0 else _l
_l = 100.0 if _l > 100.0 else _l
-
_a = -128.0 if _a < -128.0 else _a
_a = 128.0 if _a > 128.0 else _a
-
_b = -128.0 if _b < -128.0 else _b
_b = 128.0 if _b > 128.0 else _b
-
return np.array((_l, _a, _b), dtype=np.float32)
-
else:
raise ValueError("expect lab color in length 3 and float: {}.".format(lab))
-
@classmethod
- def fmt_cmyk(cls, cmyk):
- """
- Class method. Format item to standard cmyk color.
-
- Args:
- cmyk (tuple or list): color item to be formated.
-
- Returns:
- standard cmyk color.
- """
+ def fmt_cmyk(cls, cmyk):
if len(cmyk) == 4:
_cmyk = np.array(cmyk)
_cmyk[np.where(_cmyk < 0.0)] = 0.0
_cmyk[np.where(_cmyk > 1.0)] = 1.0
-
return _cmyk.astype(np.float32)
-
else:
raise ValueError("expect cmyk color in length 4 and float: {}.".format(cmyk))
-
@classmethod
- def findall_hec_lst(cls, hec):
- """
- Class method. Format item to standard hex code (hec) color.
-
- Args:
- hec (str): color item to be formated.
-
- Returns:
- standard hex code (hec) color.
- """
+ def findall_hec_lst(cls, hec):
_hec = re.findall(r"[0-9A-F]+", str(hec).upper())
_hec = ["" if len(i) < 6 else i[:6] for i in _hec]
-
while "" in _hec:
_hec.remove("")
-
return _hec
-
@classmethod
- def sys_rgb2ryb(cls, h):
- """
- Class method. Transfer hue of rgb to hue of ryb.
- """
+ def sys_rgb2ryb(cls, h):
_h = h % 360
-
if 0 <= _h < 60:
return _h / 60 * 120
-
elif 60 <= _h < 240:
return (_h - 60) / 180 * 120 + 120
-
else:
return _h
-
@classmethod
- def sys_ryb2rgb(cls, h):
- """
- Class method. Transfer hue of ryb to hue of rgb.
- """
+ def sys_ryb2rgb(cls, h):
_h = h % 360
-
if 0 <= _h < 120:
return _h / 120 * 60
-
elif 120 <= _h < 240:
return (_h - 120) / 120 * 180 + 60
-
else:
return _h
-
@classmethod
- def stri2color(cls, stri):
- """
- Find the first possible color in string.
-
- Args:
- stri (str): rgb, hsv or hec color string.
-
- Returns:
- color.
- """
+ def stri2color(cls, stri):
_stri = re.findall(r"[0-9A-F\.]+", str(stri).upper())
-
if len(_stri) > 2:
_num = re.findall(r"[0-9\.]+", str(stri))
-
if len(_num) > 2:
_a, _b, _c = _num[:3]
_a = float(".".join(_a.split(".")[:2])) if "." in _a else int(_a)
_b = float(".".join(_b.split(".")[:2])) if "." in _b else int(_b)
_c = float(".".join(_c.split(".")[:2])) if "." in _c else int(_c)
-
if _a > 255:
return Color((_a, _b, _c), tp="hsv")
-
elif _b > 1.0 or _c > 1.0:
return Color((_a, _b, _c), tp="rgb")
-
elif isinstance(_a, float) or isinstance(_b, float) or isinstance(_c, float):
return Color((_a, _b, _c), tp="hsv")
-
else:
return Color((_a, _b, _c), tp="rgb")
-
else:
return None
-
elif len(_stri) > 0:
if len(_stri[0]) > 5:
return Color(Color.fmt_hec(_stri[0]), tp="hec")
-
return None
-
else:
return None
-
@classmethod
- def rgb2hsv(cls, rgb):
- """
- Translate rgb color into hsv color.
-
- Args:
- rgb (tuple or list): rgb color.
-
- Returns:
- hsv color.
- """
+ def rgb2hsv(cls, rgb):
color = cls.fmt_rgb(rgb)
-
v = max(color) / 255.0
if abs(v - 0) < 1E-5:
color = np.array((255, 0, 0))
-
else:
color = color / v
-
s = 1 - min(color) / 255.0
if abs(s - 0) < 1E-5:
color = np.array((255, 0, 0))
-
else:
color = (color - 255 * (1 - s)) / s
color = np.rint(color).astype(np.uint8)
-
if color[0] == 255:
if color[2] == 0:
- # red to yellow, 0 to 60.
h = color[1] / 255 * 60
-
elif color[1] == 0:
- # magenta to red, 300 to 360.
h = 360 - color[2] / 255 * 60
-
else:
raise ValueError("value 0 is not found in red area: {}.".format(color))
-
elif color[1] == 255:
if color[0] == 0:
- # green to cyan, 120 to 180.
h = 120 + color[2] / 255 * 60
-
elif color[2] == 0:
- # yellow to green, 60 to 120.
h = 120 - color[0] / 255 * 60
-
else:
raise ValueError("value 0 is not found in green area: {}.".format(color))
-
elif color[2] == 255:
if color[1] == 0:
- # blue to magenta, 240 to 300.
h = 240 + color[0] / 255 * 60
-
elif color[0] == 0:
- # cyan to blue, 180 to 240.
h = 240 - color[1] / 255 * 60
-
else:
raise ValueError("value 0 is not found in blue area: {}.".format(color))
-
else:
raise ValueError("value 255 is not found in color: {}.".format(color))
-
return cls.fmt_hsv((h, s, v))
-
@classmethod
- def rgb2hsv_array(cls, rgb_array):
- """
- Translate rgb array into hsv array.
-
- Args:
- rgb (3D array): rgb array.
-
- Returns:
- hsv array.
- """
+ def rgb2hsv_array(cls, rgb_array):
colors = cls.fmt_rgb_array(rgb_array).astype(np.float64)
-
v = np.max(colors, axis=2) / 255.0
v[np.where(v < 1E-5)] = 1E-12
-
colors[:, :, 0] = colors[:, :, 0] / v
colors[:, :, 1] = colors[:, :, 1] / v
colors[:, :, 2] = colors[:, :, 2] / v
colors[np.where(v < 1E-5)] = np.array((255, 0, 0))
v[np.where(v < 1E-5)] = 0
-
s = 1 - np.min(colors, axis=2) / 255.0
s[np.where(s < 1E-5)] = 1E-12
-
colors[:, :, 0] = (colors[:, :, 0] - 255 * (1 - s)) / s
colors[:, :, 1] = (colors[:, :, 1] - 255 * (1 - s)) / s
colors[:, :, 2] = (colors[:, :, 2] - 255 * (1 - s)) / s
colors[np.where(s < 1E-5)] = np.array((255, 0, 0))
colors = np.rint(colors).astype(np.uint8)
s[np.where(s < 1E-5)] = 0
-
h = np.zeros(v.shape, dtype=np.float32)
-
- # cyan to blue, 180 to 240.
pos = np.where((colors[:, :, 2] == 255) & (colors[:, :, 0] == 0))
h[pos] = 240 - colors[pos][:, 1] / 255 * 60
-
- # blue to magenta, 240 to 300.
pos = np.where((colors[:, :, 2] == 255) & (colors[:, :, 1] == 0))
h[pos] = 240 + colors[pos][:, 0] / 255 * 60
-
- # yellow to green, 60 to 120.
pos = np.where((colors[:, :, 1] == 255) & (colors[:, :, 2] == 0))
h[pos] = 120 - colors[pos][:, 0] / 255 * 60
-
- # green to cyan, 120 to 180.
pos = np.where((colors[:, :, 1] == 255) & (colors[:, :, 0] == 0))
h[pos] = 120 + colors[pos][:, 2] / 255 * 60
-
- # magenta to red, 300 to 360.
pos = np.where((colors[:, :, 0] == 255) & (colors[:, :, 1] == 0))
h[pos] = 360 - colors[pos][:, 2] / 255 * 60
-
- # red to yellow, 0 to 60.
pos = np.where((colors[:, :, 0] == 255) & (colors[:, :, 2] == 0))
h[pos] = colors[pos][:, 1] / 255 * 60
-
return cls.fmt_hsv_array(np.stack((h, s, v), axis=2))
-
@classmethod
- def hsv2rgb(cls, hsv):
- """
- Translate hsv color into rgb color.
-
- Args:
- hsv (tuple or list): hsv color.
-
- Returns:
- rgb color.
- """
+ def hsv2rgb(cls, hsv):
h, s, v = cls.fmt_hsv(hsv)
-
- # red to yellow.
if 0 <= h < 60:
g = round(h / 60 * 255)
color = np.array((255, g, 0))
-
- # yellow to green.
elif 60 <= h < 120:
r = round((1 - (h - 60) / 60) * 255)
color = np.array((r, 255, 0))
-
- # green to cyan.
elif 120 <= h < 180:
b = round((h - 120) / 60 * 255)
color = np.array((0, 255, b))
-
- # cyan to blue.
elif 180 <= h < 240:
g = round((1 - (h - 180) / 60) * 255)
color = np.array((0, g, 255))
-
- # blue to magenta.
elif 240 <= h < 300:
r = round((h - 240) / 60 * 255)
color = np.array((r, 0, 255))
-
- # magenta to red.
elif 300 <= h < 360:
b = round((1 - (h - 300) / 60) * 255)
color = np.array((255, 0, b))
-
else:
raise ValueError("unexpect h: {}.".format(h))
-
color = color + (color * -1 + 255) * (1 - s)
color = color * v
-
return cls.fmt_rgb(color)
-
@classmethod
- def hsv2rgb_array(cls, hsv_array):
- """
- Translate hsv array into rgb array.
-
- Args:
- hsv (3D array): hsv array.
-
- Returns:
- rgb array.
- """
+ def hsv2rgb_array(cls, hsv_array):
colors = cls.fmt_hsv_array(hsv_array)
-
r = np.zeros(colors.shape[:2], dtype=np.uint8)
g = np.zeros(colors.shape[:2], dtype=np.uint8)
b = np.zeros(colors.shape[:2], dtype=np.uint8)
-
- # red to yellow.
pos = np.where((colors[:, :, 0] >= 0) & (colors[:, :, 0] < 60))
r[pos] = 255
g[pos] = np.round(colors[pos][:, 0] / 60 * 255)
-
- # yellow to green.
pos = np.where((colors[:, :, 0] >= 60) & (colors[:, :, 0] < 120))
r[pos] = np.round((1 - (colors[pos][:, 0] - 60) / 60) * 255)
g[pos] = 255
-
- # green to cyan.
pos = np.where((colors[:, :, 0] >= 120) & (colors[:, :, 0] < 180))
g[pos] = 255
b[pos] = np.round((colors[pos][:, 0] - 120) / 60 * 255)
-
- # cyan to blue.
pos = np.where((colors[:, :, 0] >= 180) & (colors[:, :, 0] < 240))
g[pos] = np.round((1 - (colors[pos][:, 0] - 180) / 60) * 255)
b[pos] = 255
-
- # blue to magenta.
pos = np.where((colors[:, :, 0] >= 240) & (colors[:, :, 0] < 300))
r[pos] = np.round((colors[pos][:, 0] - 240) / 60 * 255)
b[pos] = 255
-
- # magenta to red.
pos = np.where((colors[:, :, 0] >= 300) & (colors[:, :, 0] < 360))
r[pos] = 255
b[pos] = np.round((1 - (colors[pos][:, 0] - 300) / 60) * 255)
-
r = r + (r * -1 + 255) * (1 - colors[:, :, 1])
g = g + (g * -1 + 255) * (1 - colors[:, :, 1])
b = b + (b * -1 + 255) * (1 - colors[:, :, 1])
-
r = r * colors[:, :, 2]
g = g * colors[:, :, 2]
b = b * colors[:, :, 2]
-
return cls.fmt_rgb_array(np.stack((r, g, b), axis=2))
-
@classmethod
- def rgb2hec(cls, rgb):
- """
- Translate rgb color into hex code (hec) color.
-
- Args:
- rgb (tuple or list): rgb color.
-
- Returns:
- hex code (hec) color.
- """
+ def rgb2hec(cls, rgb):
r, g, b = cls.fmt_rgb(rgb)
-
hec_r = hex(r)[2:].upper()
hec_g = hex(g)[2:].upper()
hec_b = hex(b)[2:].upper()
-
hec_r = "0" + hec_r if len(hec_r) < 2 else hec_r
hec_g = "0" + hec_g if len(hec_g) < 2 else hec_g
hec_b = "0" + hec_b if len(hec_b) < 2 else hec_b
-
return cls.fmt_hec(hec_r + hec_g + hec_b)
-
@classmethod
- def hec2rgb(cls, hec):
- """
- Translate hex code (hec) color into rgb color.
-
- Args:
- hec (str): hex code (hec) color.
-
- Returns:
- rgb color.
- """
+ def hec2rgb(cls, hec):
pr_hec_code = cls.fmt_hec(hec)
-
hec_r = pr_hec_code[0:2]
hec_g = pr_hec_code[2:4]
hec_b = pr_hec_code[4:6]
-
r = int("0x{}".format(hec_r), 16)
g = int("0x{}".format(hec_g), 16)
b = int("0x{}".format(hec_b), 16)
-
return cls.fmt_rgb((r, g, b))
-
@classmethod
- def hsv2hec(cls, hsv):
- """
- Translate hsv color into hex code (hec) color.
-
- Args:
- hsv (tuple or list): hsv color.
-
- Returns:
- hex code (hec) color.
- """
+ def hsv2hec(cls, hsv):
rgb = cls.hsv2rgb(hsv)
hec = cls.rgb2hec(rgb)
-
return hec
-
@classmethod
- def hec2hsv(cls, hec):
- """
- Translate hex code (hec) color into rgb color.
-
- Args:
- hec (str): hex code (hec) color.
-
- Returns:
- rgb color.
- """
+ def hec2hsv(cls, hec):
rgb = cls.hec2rgb(hec)
hsv = cls.rgb2hsv(rgb)
-
return hsv
-
@classmethod
- def rgb2lab(cls, rgb, white_ref=(95.047, 100.0, 108.883)):
- """
- Translate rgb color into lab color (ref: http://www.easyrgb.com/en/math.php).
-
- Args:
- rgb (tuple or list): rgb color.
- white_ref (tuple or list): xyz (Tristimulus) Reference values of a perfect reflecting diffuser. default: value of standard "D65, 2Ang".
-
- Returns:
- lab color.
- """
+ def rgb2lab(cls, rgb, white_ref=(95.047, 100.0, 108.883)):
normed_rgb = [((i + 0.055) / 1.055) ** 2.4 if i > 0.04045 else i / 12.92 for i in cls.fmt_rgb(rgb) / 255.0]
normed_rgb = np.array(normed_rgb) * 100.0
-
xyz = np.array([
[0.412453, 0.357580, 0.180423],
[0.212671, 0.715160, 0.072169],
[0.019334, 0.119193, 0.950227],
]).dot(normed_rgb) / white_ref
-
normed_xyz = [i ** (1 / 3) if i > 0.008856 else (7.787 * i) + (16 / 116) for i in xyz]
-
l = 116 * normed_xyz[1] - 16
a = 500 * (normed_xyz[0] - normed_xyz[1])
b = 200 * (normed_xyz[1] - normed_xyz[2])
-
return cls.fmt_lab((l, a, b))
-
@classmethod
- def lab2rgb(cls, lab, white_ref=(95.047, 100.0, 108.883)):
- """
- Translate lab color into rgb color (ref: http://www.easyrgb.com/en/math.php).
-
- Args:
- lab (tuple or list): lab color.
- white_ref (tuple or list): xyz (Tristimulus) Reference values of a perfect reflecting diffuser. default: value of standard "D65, 2Ang".
-
- Returns:
- rgb color.
- """
+ def lab2rgb(cls, lab, white_ref=(95.047, 100.0, 108.883)):
l, a, b = cls.fmt_lab(lab)
-
y = (l + 16) / 116
x = a / 500 + y
z = y - b / 200
-
normed_xyz = [i ** 3 if i > 0.008856 else (i - 16 / 116) / 7.787 for i in (x, y, z)]
xyz = np.array(normed_xyz) * white_ref / 100.0
-
normed_rgb = np.array([
[ 3.24048134, -1.53715152, -0.49853633],
[-0.96925495, 1.87599 , 0.04155593],
[ 0.05564664, -0.20404134, 1.05731107],
]).dot(xyz)
-
rgb = [1.055 * (i ** (1 / 2.4)) - 0.055 if i > 0.0031308 else 12.92 * i for i in normed_rgb]
rgb = np.array(rgb) * 255
-
return cls.fmt_rgb(rgb)
-
@classmethod
- def rgb2cmyk(cls, rgb):
- """
- Translate rgb color into cmyk color (ref: http://www.easyrgb.com/en/math.php).
-
- Args:
- rgb (tuple or list): rgb color.
-
- Returns:
- cmyk color.
- """
+ def rgb2cmyk(cls, rgb):
r, g, b = cls.fmt_rgb(rgb)
-
c = 1.0 - (r / 255.0)
m = 1.0 - (g / 255.0)
y = 1.0 - (b / 255.0)
-
k = min((c, m, y))
-
if k == 1.0:
c = m = y = 0.0
-
else:
c = (c - k) / (1 - k)
m = (m - k) / (1 - k)
y = (y - k) / (1 - k)
-
return cls.fmt_cmyk((c, m, y, k))
-
@classmethod
- def cmyk2rgb(cls, cmyk):
- """
- Translate cmyk color into rgb color (ref: http://www.easyrgb.com/en/math.php).
-
- Args:
- cmyk (tuple or list): cmyk color.
-
- Returns:
- rgb color.
- """
+ def cmyk2rgb(cls, cmyk):
c, m, y, k = cls.fmt_cmyk(cmyk)
-
c = (c * (1.0 - k) + k)
m = (m * (1.0 - k) + k)
y = (y * (1.0 - k) + k)
-
r = (1.0 - c) * 255.0
g = (1.0 - m) * 255.0
b = (1.0 - y) * 255.0
-
return cls.fmt_rgb((r, g, b))
-
@classmethod
- def sign(cls, hsv):
- """
- Sign the name of color by dividing colors into different blocks by h, s and v values.
-
- Diagram:
- s
- +---+---+---+---+
- | 5 | 6 | 7 | 9 |
- +---+---+---+---+
- | 4 | 4 | 8 | 8 |
- +---+---+---+---+
- | 4 | 3 | 3 | 8 |
- +---+---+---+---+
- | 2 | 2 | 2 | 2 |
- +---+---+---+---+ v
-
- 0 - deep black; 1 - snow white; 2 - heavy; 3 - dull; 4 - grey; 5 - pale, 6 - light; 7 - bright; 8 - dark; 9 - vivid.
-
- Args:
- hsv (tuple or list): hsv color.
-
- Returns:
- serial number of color name.
- """
+ def sign(cls, hsv):
h, s, v = cls.fmt_hsv(hsv)
-
if v < 0.08:
return (0, 0)
-
if v > 0.95 and s < 0.05:
return (1, 1)
-
prefix = 2
-
for start, end, idx in ((0, 20, 0), (20, 40, 6), (40, 70, 1), (70, 160, 2), (160, 190, 3), (190, 250, 4), (250, 310, 5), (310, 340, 7), (340, 360, 0)):
if start <= h % 360 < end:
prefix = idx + 2
break
-
if 0.0 <= v < 0.25:
return (2, prefix)
-
elif 0.25 <= v < 0.5:
if 0 <= s < 0.25:
return (4, prefix)
-
elif 0.25 <= s < 0.75:
return (3, prefix)
-
else:
return (8, prefix)
-
elif 0.5 <= v < 0.75:
if 0 <= s < 0.5:
return (4, prefix)
-
else:
return (8, prefix)
-
else:
if 0 <= s < 0.25:
return (5, prefix)
-
if 0.25 <= s < 0.5:
return (6, prefix)
-
if 0.5 <= s < 0.75:
return (7, prefix)
-
else:
return (9, prefix)
-
class TestColor(unittest.TestCase):
- """
- Test Color object.
- """
-
def test_translate(self):
pr_color = Color((0, 0, 0), tp="rgb")
-
for r in range(256):
for g in range(256):
print("testing rgb2hsv with r, g = {}, {}.".format(r, g))
-
for b in range(256):
color = Color((r, g, b), tp="rgb")
self.assertEqual(color.rgb, (r, g, b))
self.assertEqual(color.r, r)
self.assertEqual(color.g, g)
self.assertEqual(color.b, b)
-
hsv = Color.rgb2hsv(color.rgb)
self.assertEqual(color.hsv, tuple(hsv))
self.assertEqual(color.h, hsv[0])
self.assertEqual(color.s, hsv[1])
self.assertEqual(color.v, hsv[2])
-
hsv_array = Color.rgb2hsv_array(np.array([[color.rgb]]))
self.assertTrue(abs(hsv[0] - hsv_array[0, 0][0]) < 1E-4)
self.assertTrue(abs(hsv[1] - hsv_array[0, 0][1]) < 1E-4)
self.assertTrue(abs(hsv[2] - hsv_array[0, 0][2]) < 1E-4)
-
rgb = Color.hsv2rgb(hsv)
self.assertTrue(color.rgb == tuple(rgb))
-
rgb_array = Color.hsv2rgb_array(hsv_array)
self.assertEqual(tuple(rgb), tuple(rgb_array[0, 0]))
-
pr_color.r = r
pr_color.g = g
pr_color.b = b
self.assertEqual(pr_color, color)
-
pr_color.h = hsv[0]
pr_color.s = hsv[1]
pr_color.v = hsv[2]
self.assertEqual(pr_color, color)
-
for h in range(361):
for s in range(101):
print("testing hsv2rgb with h, s = {}, {}.".format(h, s))
-
for v in range(101):
hsv = np.array([h, s / 100, v / 100])
color = Color(hsv, tp="hsv")
-
rgb = Color.hsv2rgb(hsv)
ar_hsv = Color.rgb2hsv(rgb)
ar_rgb = Color.hsv2rgb(ar_hsv)
self.assertTrue((rgb == ar_rgb).all())
-
ar_color = Color(ar_rgb, tp="rgb")
self.assertEqual(color, ar_color)
-
-
if __name__ == "__main__":
unittest.main()
diff --git a/src/main/python/ricore/color_set.py b/src/main/python/ricore/color_set.py
index db4a19d..8b55add 100644
--- a/src/main/python/ricore/color_set.py
+++ b/src/main/python/ricore/color_set.py
@@ -18,40 +18,19 @@
class ColorSet(object):
- """
- ColorSet object. Storing five colors in in different harmony rules (analogous, monochromatic,triad, tetrad, pentad,
- complementary, shades and custom) and sequence 2, 1, 0, 3, 4.
- """
-
def __init__(self, h_range, s_range, v_range, overflow="cutoff", dep_wtp=1):
- """
- Init ColorSet object.
-
- Args:
- h_range (tuple or list): the initial range of h value. such as (0.0, 360.0).
- s_range (tuple or list): the initial range of s value. such as (0.8, 1.0).
- v_range (tuple or list): the initial range of v value. such as (0.8, 1.0).
- overflow (str): method to manipulate overflowed s and v values, in "cutoff", "return" and "repeat".
- """
-
- # synchronization methods: Unlimited, H Locked, S Locked, Equidistant, Equal, Gradual, Symmetrical.
self.synchronization = 0
self.dep_wtp = dep_wtp
-
self.set_hsv_ranges(h_range, s_range, v_range)
-
assert 0.0 <= self._h_range[0] <= 360.0
assert 0.0 <= self._h_range[1] <= 360.0
assert self._h_range[0] <= self._h_range[1]
-
assert 0.0 <= self._s_range[0] <= 1.0
assert 0.0 <= self._s_range[1] <= 1.0
assert self._s_range[0] <= self._s_range[1]
-
assert 0.0 <= self._v_range[0] <= 1.0
assert 0.0 <= self._v_range[1] <= 1.0
assert self._v_range[0] <= self._v_range[1]
-
self._color_set = [
Color((0, 0, 0), tp="rgb", overflow=overflow),
Color((0, 0, 0), tp="rgb", overflow=overflow),
@@ -59,94 +38,43 @@ def __init__(self, h_range, s_range, v_range, overflow="cutoff", dep_wtp=1):
Color((0, 0, 0), tp="rgb", overflow=overflow),
Color((0, 0, 0), tp="rgb", overflow=overflow),
]
-
self.initialize()
- # ---------- ---------- ---------- Setting and Getting Funcs ---------- ---------- ---------- #
-
def set_hsv_ranges(self, h_range, s_range, v_range):
- """
- Set the h, s, v ranges for creating color set.
- """
-
if isinstance(h_range, (tuple, list)) and isinstance(s_range, (tuple, list)) and isinstance(v_range, (tuple, list)):
self._h_range = tuple([float(i) for i in h_range[:2]])
self._s_range = tuple([float(i) for i in s_range[:2]])
self._v_range = tuple([float(i) for i in v_range[:2]])
-
else:
raise ValueError("expect h, s, v ranges in tuple or list type: {}, {}, {}.".format(h_range, s_range, v_range))
def set_color_system(self, dep_wtp):
- """
- Set the color space.
-
- Args:
- dep_wtp (bool or int): if is ryb system.
- """
-
self.dep_wtp = dep_wtp
def set_overflow(self, overflow):
- """
- Set the overflow method for each color in color set.
-
- Args:
- overflow (str): method to manipulate overflowed s and v values, in "cutoff", "return" and "repeat".
- """
-
for color in self._color_set:
color.set_overflow(overflow)
def get_overflow(self):
- """
- Get the overflow method of first color in color set.
- """
-
assert self._color_set[1].get_overflow() == self._color_set[0].get_overflow()
assert self._color_set[2].get_overflow() == self._color_set[0].get_overflow()
assert self._color_set[3].get_overflow() == self._color_set[0].get_overflow()
assert self._color_set[4].get_overflow() == self._color_set[0].get_overflow()
-
return self._color_set[0].get_overflow()
- # ---------- ---------- ---------- Inner Funcs ---------- ---------- ---------- #
-
def __str__(self):
- """
- Str format.
- """
-
return "ColorSet({}, {}, {}, {}, {})".format(*self._color_set)
def __repr__(self):
- """
- Repr format.
- """
-
return "ColorSet({}, {}, {}, {}, {})".format(*self._color_set)
def __getitem__(self, idx):
- """
- Get color item in color set.
- """
-
return self._color_set[idx]
def __len__(self):
- """
- Get color set length.
- """
-
return 5
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def backup(self):
- """
- Backup the color set as a tuple.
- """
-
color_set = (
Color(self._color_set[0], tp="color", overflow=self.get_overflow()),
Color(self._color_set[1], tp="color", overflow=self.get_overflow()),
@@ -154,14 +82,9 @@ def backup(self):
Color(self._color_set[3], tp="color", overflow=self.get_overflow()),
Color(self._color_set[4], tp="color", overflow=self.get_overflow()),
)
-
return color_set
def recover(self, color_set):
- """
- Recover the color set by a tuple.
- """
-
self._color_set = [
Color(color_set[0], tp="color", overflow=self.get_overflow()),
Color(color_set[1], tp="color", overflow=self.get_overflow()),
@@ -171,31 +94,17 @@ def recover(self, color_set):
]
def initialize(self):
- """
- Create color set randomly.
- """
-
for i in range(5):
h = self._h_range[0] + (self._h_range[1] - self._h_range[0]) * random.random()
s = self._s_range[0] + (self._s_range[1] - self._s_range[0]) * random.random()
v = self._v_range[0] + (self._v_range[1] - self._v_range[0]) * random.random()
-
if self.dep_wtp:
h = Color.sys_ryb2rgb(h)
-
self._color_set[i].hsv = (h, s, v)
def create(self, harmony_rule):
- """
- Create color set under a selected harmony rule.
-
- Args:
- harmony_rule (str): rule, in "analogous", "monochromatic", "triad", "tetrad", "pentad", "complementary", "shades" and "custom".
- """
-
if harmony_rule == "custom":
return
-
methods = {
"analogous": self._analogous_create,
"monochromatic": self._monochromatic_create,
@@ -205,27 +114,14 @@ def create(self, harmony_rule):
"complementary": self._complementary_create,
"shades": self._shades_create,
}
-
if harmony_rule in methods:
methods[harmony_rule]()
-
else:
raise ValueError("expect harmony rule in list 'analogous', 'monochromatic', etc.: {}.".format(harmony_rule))
def modify(self, harmony_rule, idx, color, do_sync=True):
- """
- Modify color set under a selected harmony rule.
-
- Args:
- harmony_rule (str): rule, in "analogous", "monochromatic", "triad", "tetrad", "pentad", "complementary", "shades" and "custom".
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- color (Color): replace the selected color with this color.
- do_sync (bool): if run synchronization.
- """
-
if do_sync and self.synchronization:
self._sync_modify(idx, color)
-
else:
methods = {
"analogous": self._analogous_modify,
@@ -237,55 +133,32 @@ def modify(self, harmony_rule, idx, color, do_sync=True):
"shades": self._shades_modify,
"custom": self._custom_modify,
}
-
if harmony_rule in methods:
methods[harmony_rule](idx, color)
-
else:
raise ValueError("unexpect harmony rule name for modify: {}.".format(harmony_rule))
- # ---------- ---------- ---------- Personal Funcs ---------- ---------- ---------- #
-
def _rotate(self, delta_h, delta_s, delta_v):
- """
- Rotate color set by delta values.
-
- Args:
- delta_h (int or float): shift value for h.
- delta_s (int or float): shift value for s.
- delta_v (int or float): shift value for v.
- """
-
for idx in range(5):
if self.dep_wtp:
self._color_set[idx].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[idx].h) + delta_h)
-
else:
self._color_set[idx].h = self._color_set[idx].h + delta_h
-
self._color_set[idx].s = self._color_set[idx].s + delta_s
self._color_set[idx].v = self._color_set[idx].v + delta_v
def _analogous_create(self):
- """
- Create color set in analogous rule.
- """
-
if self.dep_wtp:
angle = (Color.sys_rgb2ryb(self._color_set[3].h) - Color.sys_rgb2ryb(self._color_set[1].h)) / 2
-
else:
angle = (self._color_set[3].h - self._color_set[1].h) / 2
-
while angle > 30.0 or angle < -30.0:
angle = angle / 1.5
-
if self.dep_wtp:
self._color_set[1].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - angle)
self._color_set[2].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - angle * 2)
self._color_set[3].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + angle)
self._color_set[4].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + angle * 2)
-
else:
self._color_set[1].h = self._color_set[0].h - angle
self._color_set[2].h = self._color_set[0].h - angle * 2
@@ -293,128 +166,82 @@ def _analogous_create(self):
self._color_set[4].h = self._color_set[0].h + angle * 2
def _analogous_modify(self, idx, pr_color):
- """
- Modify color set in analogous rule.
-
- Args:
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- pr_color (Color): replace the selected color with this color.
- """
-
if idx == 0:
if self.dep_wtp:
delta_h = Color.sys_rgb2ryb(pr_color.h) - Color.sys_rgb2ryb(self._color_set[0].h)
-
else:
delta_h = pr_color.h - self._color_set[0].h
-
delta_s = pr_color.s - self._color_set[0].s
delta_v = pr_color.v - self._color_set[0].v
-
self._rotate(delta_h, delta_s, delta_v)
-
else:
if idx in (1, 2):
if self.dep_wtp:
angle = Color.sys_rgb2ryb(self._color_set[0].h) - Color.sys_rgb2ryb(pr_color.h)
-
else:
angle = self._color_set[0].h - pr_color.h
-
else:
if self.dep_wtp:
angle = Color.sys_rgb2ryb(pr_color.h) - Color.sys_rgb2ryb(self._color_set[0].h)
-
else:
angle = pr_color.h - self._color_set[0].h
-
- # place the turning point at relative 180 deg.
if idx in (2, 4):
angle = angle - 360 if angle > 180 else angle
angle = angle + 360 if angle < -180 else angle
angle /= 2
-
if self.dep_wtp:
self._color_set[1].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - angle)
self._color_set[2].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - angle * 2)
self._color_set[3].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + angle)
self._color_set[4].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + angle * 2)
-
else:
self._color_set[1].h = self._color_set[0].h - angle
self._color_set[2].h = self._color_set[0].h - angle * 2
self._color_set[3].h = self._color_set[0].h + angle
self._color_set[4].h = self._color_set[0].h + angle * 2
-
self._color_set[idx] = pr_color
def _monochromatic_create(self):
- """
- Create color set in monochromatic rule.
- """
-
self._color_set[1].h = self._color_set[0].h
self._color_set[2].h = self._color_set[0].h
self._color_set[3].h = self._color_set[0].h
self._color_set[4].h = self._color_set[0].h
-
us_random = self._color_set[0].s
ls_random = self._color_set[0].s
-
if us_random < 0.5:
us_random = us_random + 0.2 + 0.25 * random.random()
ls_random = ls_random + 0.15 * random.random()
-
else:
us_random = us_random - 0.2 - 0.25 * random.random()
ls_random = ls_random - 0.15 * random.random()
-
uv_random = self._color_set[0].v
lv_random = self._color_set[0].v
-
if uv_random < 0.5:
uv_random = uv_random + 0.2 + 0.25 * random.random()
lv_random = lv_random + 0.15 * random.random()
-
else:
uv_random = uv_random - 0.2 - 0.25 * random.random()
lv_random = lv_random - 0.15 * random.random()
-
self._color_set[1].s = us_random
self._color_set[2].s = us_random
self._color_set[3].s = ls_random
self._color_set[4].s = ls_random
-
self._color_set[1].v = uv_random
self._color_set[2].v = lv_random
self._color_set[3].v = uv_random
self._color_set[4].v = lv_random
def _monochromatic_modify(self, idx, pr_color):
- """
- Modify color set in single method for monochromatic rule.
-
- Args:
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- pr_color (Color): replace the selected color with this color.
- """
-
for i in range(5):
self._color_set[i].h = pr_color.h
-
self._color_set[idx] = pr_color
def _triad_create(self):
- """
- Create color set in triad rule.
- """
-
if self.dep_wtp:
self._color_set[1].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - 120.0)
self._color_set[2].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - 120.0)
self._color_set[3].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 120.0)
self._color_set[4].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 120.0)
-
else:
self._color_set[1].h = self._color_set[0].h - 120.0
self._color_set[2].h = self._color_set[0].h - 120.0
@@ -422,48 +249,29 @@ def _triad_create(self):
self._color_set[4].h = self._color_set[0].h + 120.0
def _multiple_modify(self, idx, pr_color):
- """
- Modify color set in multiple method for triad, pentad and complementary rules.
-
- Args:
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- pr_color (Color): replace the selected color with this color.
- """
-
if self.dep_wtp:
delta_h = Color.sys_rgb2ryb(pr_color.h) - Color.sys_rgb2ryb(self._color_set[idx].h)
-
else:
delta_h = pr_color.h - self._color_set[idx].h
-
if idx == 0:
delta_s = pr_color.s - self._color_set[idx].s
delta_v = pr_color.v - self._color_set[idx].v
-
self._rotate(delta_h, delta_s, delta_v)
-
else:
if self.dep_wtp:
for i in range(5):
self._color_set[i].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[i].h) + delta_h)
-
else:
for i in range(5):
self._color_set[i].h = self._color_set[i].h + delta_h
-
self._color_set[idx] = pr_color
def _tetrad_create(self):
- """
- Create color set in tetrad rule.
- """
-
if self.dep_wtp:
self._color_set[1].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - 90)
self._color_set[2].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - 180)
self._color_set[3].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 90)
self._color_set[4].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 180)
-
else:
self._color_set[1].h = self._color_set[0].h - 90
self._color_set[2].h = self._color_set[0].h - 180
@@ -471,49 +279,30 @@ def _tetrad_create(self):
self._color_set[4].h = self._color_set[0].h + 180
def _tetrad_modify(self, idx, pr_color):
- """
- Modify color set in tetrad rule.
-
- Args:
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- pr_color (Color): replace the selected color with this color.
- """
-
if self.dep_wtp:
delta_h = Color.sys_rgb2ryb(pr_color.h) - Color.sys_rgb2ryb(self._color_set[idx].h)
-
else:
delta_h = pr_color.h - self._color_set[idx].h
-
if idx == 0:
delta_s = pr_color.s - self._color_set[idx].s
delta_v = pr_color.v - self._color_set[idx].v
-
self._rotate(delta_h, delta_s, delta_v)
-
else:
if idx in (2, 4):
self._color_set[0].h += delta_h
self._color_set[2].h += delta_h
self._color_set[4].h += delta_h
-
else:
self._color_set[1].h += delta_h
self._color_set[3].h += delta_h
-
self._color_set[idx] = pr_color
def _pentad_create(self):
- """
- Create color set in pentad rule.
- """
-
if self.dep_wtp:
self._color_set[1].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - 72)
self._color_set[2].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) - 144)
self._color_set[3].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 72)
self._color_set[4].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 144)
-
else:
self._color_set[1].h = self._color_set[0].h - 72
self._color_set[2].h = self._color_set[0].h - 144
@@ -521,215 +310,143 @@ def _pentad_create(self):
self._color_set[4].h = self._color_set[0].h + 144
def _complementary_create(self):
- """
- Create color set in complementary rule.
- """
-
self._color_set[1].h = self._color_set[0].h
self._color_set[3].h = self._color_set[0].h
-
if self.dep_wtp:
self._color_set[2].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 180.0)
self._color_set[4].h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._color_set[0].h) + 180.0)
-
else:
self._color_set[2].h = self._color_set[0].h + 180.0
self._color_set[4].h = self._color_set[0].h + 180.0
-
us_random = self._color_set[0].s
ls_random = self._color_set[0].s
-
if us_random < 0.5:
us_random = us_random + 0.2 + 0.25 * random.random()
ls_random = ls_random + 0.15 * random.random()
-
else:
us_random = us_random - 0.2 - 0.25 * random.random()
ls_random = ls_random - 0.15 * random.random()
-
uv_random = self._color_set[0].v
lv_random = self._color_set[0].v
-
if uv_random < 0.5:
uv_random = uv_random + 0.2 + 0.25 * random.random()
lv_random = lv_random + 0.15 * random.random()
-
else:
uv_random = uv_random - 0.2 - 0.25 * random.random()
lv_random = lv_random - 0.15 * random.random()
-
self._color_set[1].s = us_random
self._color_set[2].s = us_random
self._color_set[3].s = ls_random
self._color_set[4].s = ls_random
-
self._color_set[1].v = uv_random
self._color_set[2].v = lv_random
self._color_set[3].v = uv_random
self._color_set[4].v = lv_random
def _shades_create(self):
- """
- Create color set in shades rule.
- """
-
self._color_set[1].hsv = self._color_set[0].hsv
self._color_set[2].hsv = self._color_set[0].hsv
self._color_set[3].hsv = self._color_set[0].hsv
self._color_set[4].hsv = self._color_set[0].hsv
-
self._color_set[1].v = 0.15
self._color_set[2].v = 0.40
self._color_set[3].v = 0.65
self._color_set[4].v = 0.90
def _shades_modify(self, idx, pr_color):
- """
- Modify color set in shades rule.
-
- Args:
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- pr_color (Color): replace the selected color with this color.
- """
-
for i in range(5):
self._color_set[i].h = pr_color.h
self._color_set[i].s = pr_color.s
-
self._color_set[idx] = pr_color
def _custom_modify(self, idx, pr_color):
- """
- Modify color set in custom rule.
-
- Args:
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- pr_color (Color): replace the selected color with this color.
- """
-
if idx in range(5):
self._color_set[idx].hsv = pr_color.hsv
-
else:
raise ValueError("expect idx in range 0 ~ 4: {}.".format(idx))
def _sync_modify(self, idx, pr_color):
- """
- Modify color set in special synchronization rule.
-
- Args:
- idx (int): index in range 0 ~ 4 which indicates the color in color set for modify.
- pr_color (Color): replace the selected color with this color.
- """
-
if self.dep_wtp:
delta_h = Color.sys_rgb2ryb(pr_color.h) - Color.sys_rgb2ryb(self._color_set[idx].h)
-
else:
delta_h = pr_color.h - self._color_set[idx].h
-
if self.synchronization == 1:
delta_h = 0
delta_s = pr_color.s - self._color_set[idx].s
delta_v = pr_color.v - self._color_set[idx].v
-
elif self.synchronization == 2:
delta_s = delta_v = 0
-
elif self.synchronization == 3:
delta_s = pr_color.s - self._color_set[idx].s
delta_v = pr_color.v - self._color_set[idx].v
-
elif self.synchronization == 4:
for i in range(5):
self._color_set[i].s = pr_color.s
self._color_set[i].v = pr_color.v
-
delta_s = 0
delta_v = 0
-
elif self.synchronization == 5:
if idx == 1:
self._color_set[1].s = pr_color.s
self._color_set[2].s = self._color_set[1].s * 2 - self._color_set[0].s
self._color_set[4].s = self._color_set[3].s * 2 - self._color_set[0].s
-
self._color_set[1].v = pr_color.v
self._color_set[2].v = self._color_set[1].v * 2 - self._color_set[0].v
self._color_set[4].v = self._color_set[3].v * 2 - self._color_set[0].v
-
elif idx == 3:
self._color_set[3].s = pr_color.s
self._color_set[2].s = self._color_set[1].s * 2 - self._color_set[0].s
self._color_set[4].s = self._color_set[3].s * 2 - self._color_set[0].s
-
self._color_set[3].v = pr_color.v
self._color_set[2].v = self._color_set[1].v * 2 - self._color_set[0].v
self._color_set[4].v = self._color_set[3].v * 2 - self._color_set[0].v
-
elif idx == 2:
self._color_set[2].s = pr_color.s
self._color_set[1].s = (self._color_set[2].s + self._color_set[0].s) / 2
self._color_set[3].s = (self._color_set[4].s + self._color_set[0].s) / 2
-
self._color_set[2].v = pr_color.v
self._color_set[1].v = (self._color_set[2].v + self._color_set[0].v) / 2
self._color_set[3].v = (self._color_set[4].v + self._color_set[0].v) / 2
-
elif idx == 4:
self._color_set[4].s = pr_color.s
self._color_set[1].s = (self._color_set[2].s + self._color_set[0].s) / 2
self._color_set[3].s = (self._color_set[4].s + self._color_set[0].s) / 2
-
self._color_set[4].v = pr_color.v
self._color_set[1].v = (self._color_set[2].v + self._color_set[0].v) / 2
self._color_set[3].v = (self._color_set[4].v + self._color_set[0].v) / 2
-
else:
self._color_set[0].s = pr_color.s
self._color_set[1].s = (self._color_set[2].s + self._color_set[0].s) / 2
self._color_set[3].s = (self._color_set[4].s + self._color_set[0].s) / 2
-
self._color_set[0].v = pr_color.v
self._color_set[1].v = (self._color_set[2].v + self._color_set[0].v) / 2
self._color_set[3].v = (self._color_set[4].v + self._color_set[0].v) / 2
-
delta_s = 0
delta_v = 0
-
elif self.synchronization == 6:
self._color_set[idx].s = pr_color.s
self._color_set[idx].v = pr_color.v
-
if idx in (1, 2):
self._color_set[3].s = self._color_set[1].s
self._color_set[4].s = self._color_set[2].s
-
self._color_set[3].v = self._color_set[1].v
self._color_set[4].v = self._color_set[2].v
-
elif idx in (3, 4):
self._color_set[1].s = self._color_set[3].s
self._color_set[2].s = self._color_set[4].s
-
self._color_set[1].v = self._color_set[3].v
self._color_set[2].v = self._color_set[4].v
-
else:
self._color_set[1].s = (self._color_set[1].s + self._color_set[3].s) / 2
self._color_set[2].s = (self._color_set[2].s + self._color_set[4].s) / 2
self._color_set[3].s = self._color_set[1].s
self._color_set[4].s = self._color_set[2].s
-
self._color_set[1].v = (self._color_set[1].v + self._color_set[3].v) / 2
self._color_set[2].v = (self._color_set[2].v + self._color_set[4].v) / 2
self._color_set[3].v = self._color_set[1].v
self._color_set[4].v = self._color_set[2].v
-
delta_s = 0
delta_v = 0
-
else:
raise ValueError("unexpect synchronization code for special rule: {}.".format(self.synchronization))
-
self._rotate(delta_h, delta_s, delta_v)
diff --git a/src/main/python/ricore/export.py b/src/main/python/ricore/export.py
index 347cf04..b60ef2e 100644
--- a/src/main/python/ricore/export.py
+++ b/src/main/python/ricore/export.py
@@ -23,135 +23,79 @@
def get_export_color_list(color_list, export_grid=False, max_len=65535):
- """
- Get the export_color_list and export_cname_list for formatting aco, gpl, xml, txt or others.
-
- Args:
- color_list (tuple or list): [(color_set, hm_rule, name, desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values), ...]
- export_grid (bool): True for exporting colors in grid list and False for exporting color set.
- max_len (int): max length of color list.
-
- Returns:
- export_color_list and export_cname_list.
- """
-
export_color_list = []
export_cname_list = []
-
if export_grid:
for idx in range(len(color_list)):
if color_list[idx][7][0]:
for i in range(len(color_list[idx][7][0])):
export_color_list.append(Color(color_list[idx][7][0][i], tp="hec"))
-
if len(color_list) == 1:
name = "{} {}: {}".format(fmt_name(color_list[idx][2]), i + 1, fmt_name(color_list[idx][7][1][i]))
-
else:
name = "{} {}-{}: {}".format(fmt_name(color_list[idx][2]), idx + 1, i + 1, fmt_name(color_list[idx][7][1][i]))
-
export_cname_list.append(name.replace("\"", "'"))
-
- # max length: 65535.
if len(export_color_list) >= max_len:
break
-
else:
color_grid = gen_color_grid(color_list[idx][0], color_list[idx][5], color_list[idx][6], grid_list=None, **color_list[idx][8]).tolist()
-
for i in range(len(color_grid)):
for j in range(len(color_grid[i])):
export_color_list.append(Color(color_grid[i][j], tp="rgb"))
-
if len(color_list) == 1:
name = "{} {}-{}".format(fmt_name(color_list[idx][2]), i + 1, j + 1)
-
else:
name = "{} {}-{}-{}".format(fmt_name(color_list[idx][2]), idx + 1, i + 1, j + 1)
-
export_cname_list.append(name.replace("\"", "'"))
-
- # max length: 65535.
if len(export_color_list) >= max_len:
break
-
- # max length: 65535.
if len(export_color_list) >= max_len:
break
-
- # max length: 65535.
if len(export_color_list) >= max_len:
break
-
else:
- # generate full colors. this code is reused.
for idx in range(len(color_list)):
for i in (2, 1, 0, 3, 4):
export_color_list.append(Color(color_list[idx][0][i]))
name = "{} {}-{}".format(fmt_name(color_list[idx][2]), idx + 1, i + 1)
export_cname_list.append(name)
-
export_color_list.append(Color("FFFFFF", tp="hec"))
name = fmt_name(color_list[idx][2])
export_cname_list.append(name)
-
for i in (2, 1, 0, 3, 4):
export_color_list.append(Color(color_list[idx][0][i]))
name = "{} {}-{}".format(fmt_name(color_list[idx][2]), idx + 1, i + 1)
export_cname_list.append(name)
-
for assit_idx in range(len(color_list[idx][6][i])):
assit_color = gen_assit_color(color_list[idx][0][i], *color_list[idx][6][i][assit_idx][2:6])
-
export_color_list.append(assit_color)
name = "{} {}-{}-{}".format(fmt_name(color_list[idx][2]), idx + 1, i + 1, assit_idx + 1)
export_cname_list.append(name)
-
export_color_list = export_color_list[:max_len]
export_cname_list = export_cname_list[:max_len]
-
return export_color_list, export_cname_list
def export_ase(color_list, ctp="rgb", asetp="process", export_grid=False, white_ref=(95.047, 100.0, 108.883)):
- """
- Export color set list in ase type (for Adobe exchange).
-
- Args:
- color_list (tuple or list): [(color_set, hm_rule, name, desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values), ...]
- ctp (str): 'rgb', 'hsv', 'cmyk', 'lab' or 'grey'.
- asetp (str): 'spot', 'global' or 'process'. ref: see https://github.com/nsfmc/swatch.
- export_grid (bool): True for exporting colors in grid list and False for exporting color set.
- white_ref (tuple or list): xyz (Tristimulus) Reference values of a perfect reflecting diffuser. default: value of standard "D65, 2Ang".
-
- Returns:
- Binary strings.
- """
-
export_color_list, export_cname_list = get_export_color_list(color_list, export_grid=export_grid)
data = []
-
for idx in range(len(export_color_list)):
if ctp == "cmyk":
c, m, y, k = Color.rgb2cmyk(export_color_list[idx].rgb)
data_values = (c, m, y, k)
data_mode = "CMYK"
-
elif ctp == "lab":
l, a, b = Color.rgb2lab(export_color_list[idx].rgb, white_ref=white_ref)
data_values = (l / 100.0, a, b)
data_mode = "LAB"
-
elif ctp == "gray":
r, g, b = export_color_list[idx].rgb
g = 0.2125 * r + 0.7154 * g + 0.0721 * b
data_values = (g / 255.0,)
data_mode = "Gray"
-
else:
r, g, b = export_color_list[idx].rgb
data_values = (r / 255.0, g / 255.0, b / 255.0)
data_mode = "RGB"
-
data.append({
"name": export_cname_list[idx],
"type": asetp[0].upper() + asetp[1:],
@@ -160,462 +104,252 @@ def export_ase(color_list, ctp="rgb", asetp="process", export_grid=False, white_
"values": data_values,
},
})
-
return swatch.dumps(data)
def import_ase(file_path, white_ref=(95.047, 100.0, 108.883)):
- """
- Import color list from ase file (for Adobe exchange).
-
- Args:
- file_path (str): swatch file.
- white_ref (tuple or list): xyz (Tristimulus) Reference values of a perfect reflecting diffuser. default: value of standard "D65, 2Ang".
-
- Returns:
- grid list (contains colors, names).
- """
-
data = swatch.parse(file_path)
grid_list = []
name_list = []
-
for line in data:
name_list.append(line["name"])
-
if line["data"]["mode"].lower() == "rgb":
color = Color.rgb2hec((line["data"]["values"][0] * 255, line["data"]["values"][1] * 255, line["data"]["values"][2] * 255))
-
elif line["data"]["mode"].lower() == "cmyk":
color = Color.rgb2hec(Color.cmyk2rgb((line["data"]["values"][0], line["data"]["values"][1], line["data"]["values"][2], line["data"]["values"][3])))
-
elif line["data"]["mode"].lower() == "lab":
color = Color.rgb2hec(Color.lab2rgb((line["data"]["values"][0] * 100.0, line["data"]["values"][1], line["data"]["values"][2]), white_ref=white_ref))
-
elif line["data"]["mode"].lower() == "gray":
color = Color.rgb2hec((255 * line["data"]["values"][0], 255 * line["data"]["values"][0], 255 * line["data"]["values"][0]))
-
else:
color = "FFFFFF"
-
grid_list.append(color)
-
return grid_list, name_list
def export_swatch(color_list, ctp="rgb", export_grid=False, white_ref=(95.047, 100.0, 108.883)):
- """
- Export color set list in swatch type (for Adobe exchange).
-
- Args:
- color_list (tuple or list): [(color_set, hm_rule, name, desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values), ...]
- ctp (str): 'rgb', 'hsv', 'cmyk', 'lab' or 'grey'.
- export_grid (bool): True for exporting colors in grid list and False for exporting color set.
- white_ref (tuple or list): xyz (Tristimulus) Reference values of a perfect reflecting diffuser. default: value of standard "D65, 2Ang".
-
- Returns:
- Binary strings.
- """
-
export_color_list, export_cname_list = get_export_color_list(color_list, export_grid=export_grid)
-
swatch_chars_v1 = struct.pack("!H", 1) + struct.pack("!H", len(export_color_list))
swatch_chars_v2 = struct.pack("!H", 2) + struct.pack("!H", len(export_color_list))
-
for idx in range(len(export_color_list)):
if ctp == "hsv":
h, s, v = export_color_list[idx].hsv
pr_chars = struct.pack("!H", 1) + struct.pack("!H", int(h * 182.04167)) + struct.pack("!H", int(s * 65535)) + struct.pack("!H", int(v * 65535)) + struct.pack("!H", 0)
-
elif ctp == "cmyk":
c, m, y, k = Color.rgb2cmyk(export_color_list[idx].rgb)
pr_chars = struct.pack("!H", 2) + struct.pack("!H", int((1.0 - c) * 65535)) + struct.pack("!H", int((1.0 - m) * 65535)) + struct.pack("!H", int((1.0 - y) * 65535)) + struct.pack("!H", int((1.0 - k) * 65535))
-
elif ctp == "lab":
l, a, b = Color.rgb2lab(export_color_list[idx].rgb, white_ref=white_ref)
pr_chars = struct.pack("!H", 7) + struct.pack("!H", int(l * 100)) + struct.pack("!h", int(a * 100)) + struct.pack("!h", int(b * 100)) + struct.pack("!H", 0)
-
elif ctp == "gray":
r, g, b = export_color_list[idx].rgb
g = 0.2125 * r + 0.7154 * g + 0.0721 * b
pr_chars = struct.pack("!H", 8) + struct.pack("!H", int((255 - g) * 39.2156862745098)) + struct.pack("!H", 0) + struct.pack("!H", 0) + struct.pack("!H", 0)
-
else:
r, g, b = export_color_list[idx].rgb
pr_chars = struct.pack("!H", 0) + struct.pack("!H", int(r * 257)) + struct.pack("!H", int(g * 257)) + struct.pack("!H", int(b * 257)) + struct.pack("!H", 0)
-
swatch_chars_v1 = swatch_chars_v1 + pr_chars
-
swatch_chars_v2 = swatch_chars_v2 + pr_chars
-
name = export_cname_list[idx]
swatch_chars_v2 = swatch_chars_v2 + struct.pack("!H", 0) + struct.pack("!H", len(name) + 1)
-
for n in name:
swatch_chars_v2 = swatch_chars_v2 + struct.pack("!H", ord(n))
-
swatch_chars_v2 = swatch_chars_v2 + struct.pack("!H", 0)
-
swatch_chars = swatch_chars_v1 + swatch_chars_v2
-
return swatch_chars
def import_swatch(file_path, white_ref=(95.047, 100.0, 108.883)):
- """
- Import color list from swatch file (for Adobe exchange).
-
- Args:
- file_path (str): swatch file.
- white_ref (tuple or list): xyz (Tristimulus) Reference values of a perfect reflecting diffuser. default: value of standard "D65, 2Ang".
-
- Returns:
- grid list (contains colors, names).
- """
-
with open(file_path, "rb") as df:
data = df.read()
-
if len(data) % 2 != 0 and len(data) < 4:
return None
-
init_ver = 1
init_pos = 4
init_len = struct.unpack('!H', data[2:4])[0]
-
if struct.unpack('!H', data[0:2])[0] == 2:
init_ver = 2
-
elif struct.unpack('!H', data[0:2])[0] == 1 and len(data) > init_len * 10 + 6 and struct.unpack('!H', data[init_len * 10 + 4: init_len * 10 + 6])[0] == 2:
init_ver = 2
init_pos = init_len * 10 + 8
init_len = struct.unpack("!H", data[init_len * 10 + 6: init_len * 10 + 8])[0]
-
last_pos = init_pos
-
grid_list = []
name_list = []
-
for idx in range(init_len):
color_type = struct.unpack('!H', data[last_pos: last_pos + 2])[0]
-
color_a = struct.unpack('!H', data[last_pos + 2: last_pos + 4 ])[0]
color_b = struct.unpack('!H', data[last_pos + 4: last_pos + 6 ])[0]
color_c = struct.unpack('!H', data[last_pos + 6: last_pos + 8 ])[0]
color_d = struct.unpack('!H', data[last_pos + 8: last_pos + 10])[0]
-
if color_type == 0:
color = Color.rgb2hec((color_a / 257, color_b / 257, color_c / 257))
-
elif color_type == 1:
color = Color.hsv2hec((color_a / 182.04167, color_b / 65535, color_c / 65535))
-
elif color_type == 2:
color = Color.rgb2hec(Color.cmyk2rgb((1.0 - color_a / 65535, 1.0 - color_b / 65535, 1.0 - color_c / 65535, 1.0 - color_d / 65535)))
-
elif color_type == 7:
color_b = struct.unpack('!h', data[last_pos + 4: last_pos + 6 ])[0]
color_c = struct.unpack('!h', data[last_pos + 6: last_pos + 8 ])[0]
-
color = Color.rgb2hec(Color.lab2rgb((color_a / 100, color_b / 100, color_c / 100), white_ref=white_ref))
-
elif color_type == 8:
color = Color.rgb2hec((255 - color_a / 39.2156862745098, 255 - color_a / 39.2156862745098, 255 - color_a / 39.2156862745098))
-
else:
color = "FFFFFF"
-
last_pos = last_pos + 10
-
if init_ver == 2:
if struct.unpack('!H', data[last_pos: last_pos + 2])[0] == 0:
char_len = struct.unpack('!H', data[last_pos + 2: last_pos + 4])[0] - 1
-
if struct.unpack('!H', data[last_pos + char_len * 2 + 4: last_pos + char_len * 2 + 6])[0] == 0:
name = ""
-
for name_idx in range(char_len):
name = name + chr(struct.unpack('!H', data[last_pos + name_idx * 2 + 4: last_pos + name_idx * 2 + 6])[0])
-
else:
name = ""
-
last_pos = last_pos + char_len * 2 + 6
-
else:
name = ""
-
else:
name = ""
-
grid_list.append(color)
name_list.append(name)
-
return grid_list, name_list
def export_gpl(color_list, export_grid=False):
- """
- Export color set list in gpl type (for GIMP exchange).
-
- Args:
- color_list (tuple or list): [(color_set, hm_rule, name, desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values), ...]
- export_grid (bool): True for exporting colors in grid list and False for exporting color set.
-
- Returns:
- Plain text strings.
- """
-
export_color_list, export_cname_list = get_export_color_list(color_list, export_grid=export_grid)
-
gpl_chars = "GIMP Palette\n"
-
for idx in range(len(export_color_list)):
r, g, b = export_color_list[idx].rgb
name = export_cname_list[idx]
gpl_chars += "{:<5}{:<5}{:<5}{}\n".format(r, g, b, name)
-
return gpl_chars
def import_gpl(file_path):
- """
- Import color list from gpl file (for GIMP exchange).
-
- Args:
- file_path (str): gpl file.
-
- Returns:
- grid list (contains colors, names).
- """
-
grid_list = []
name_list = []
-
with open(file_path, "r", encoding="utf-8") as df:
data = df.read()
-
for line in data.split("\n"):
items = line.split()
-
if len(items) >= 3:
color_text = ", ".join(items[:3])
color = Color.stri2color(color_text)
color = color.hec if color else "#FFFFFF"
-
if len(items) > 3:
name = " ".join(items[3:])
-
else:
name = ""
-
grid_list.append(color)
name_list.append(name)
-
return grid_list, name_list
def export_xml(color_list, export_grid=False):
- """
- Export color set list in xml type (for Pencil exchange).
-
- Args:
- color_list (tuple or list): [(color_set, hm_rule, name, desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values), ...]
- export_grid (bool): True for exporting colors in grid list and False for exporting color set.
-
- Returns:
- Plain text strings.
- """
-
export_color_list, export_cname_list = get_export_color_list(color_list, export_grid=export_grid)
-
xml_chars = "\n\n"
-
for idx in range(len(export_color_list)):
r, g, b = export_color_list[idx].rgb
name = export_cname_list[idx]
xml_chars += " \n".format(r, " " * (3 - len(str(r))), g, " " * (3 - len(str(g))), b, " " * (3 - len(str(b))), name)
-
xml_chars += " \n"
-
return xml_chars
def import_xml(file_path):
- """
- Import color list from xml flie (for Pencil exchange).
-
- Args:
- file_path (str): xml file.
-
- Returns:
- grid list (contains colors, names).
- """
-
grid_list = []
name_list = []
-
with open(file_path, "r", encoding="utf-8") as df:
data = df.read()
-
html = etree.HTML(data)
colour_xmls = html.xpath("//colour")
color_xmls = html.xpath("//color")
-
for color_xml in colour_xmls + color_xmls:
color_text = ""
color = None
-
r = color_xml.xpath("@red")
r = r if r else color_xml.xpath("@r")
g = color_xml.xpath("@green")
g = g if g else color_xml.xpath("@g")
b = color_xml.xpath("@blue")
b = b if b else color_xml.xpath("@b")
-
h = color_xml.xpath("@hue")
h = h if h else color_xml.xpath("@h")
s = color_xml.xpath("@saturation")
s = s if s else color_xml.xpath("@s")
v = color_xml.xpath("@value")
v = v if v else color_xml.xpath("@v")
-
rgb = color_xml.xpath("@rgb")
-
if r and g and b:
color_text = "{}, {}, {}".format(r[0], g[0], b[0])
-
elif h and s and v:
color_text = "{}, {}, {}".format(h[0], s[0], v[0])
-
elif rgb:
color_text = rgb[0]
-
if color_text:
color = Color.stri2color(color_text)
color = color.hec if color else "#FFFFFF"
-
if color:
name = color_xml.xpath("@name")
name = name[0] if name else ""
-
grid_list.append(color)
name_list.append(name)
-
return grid_list, name_list
def export_text(color_list):
- """
- Export color set list in plain text (for directly reading).
-
- Args:
- color_list (tuple or list): [(color_set, hm_rule, name, desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values), ...]
-
- Returns:
- Plain text strings.
- """
-
plain_text = ""
-
for idx in range(len(color_list)):
rule_str = color_list[idx][1]
rule_str = rule_str[0].upper() + rule_str[1:].lower()
-
if color_list[idx][4][0] < 0:
time_str = "Unknown"
-
else:
time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(color_list[idx][4][0]))
-
if color_list[idx][4][1] < 0:
time_str += "; Unknown"
-
else:
time_str += "; {}".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(color_list[idx][4][1])))
-
name = "{} {}".format(fmt_name(color_list[idx][2]), idx + 1)
plain_text += "# Name: {}\n".format(name)
plain_text += "# Rule: {}\n".format(rule_str)
plain_text += "# Time: {}\n".format(time_str)
plain_text += "{:<8}{:<8}{:<8}{:<8}{:<10}{:<10}{:<10}{:<8}\n".format("# Index", "R", "G", "B", "H", "S", "V", "Hex Code")
-
- # generate full colors. this code is reused.
for i in (2, 1, 0, 3, 4):
r, g, b = color_list[idx][0][i].rgb
h, s, v = color_list[idx][0][i].hsv
hex_code = "{}".format(color_list[idx][0][i].hec)
plain_text += " {:<6}{:<8}{:<8}{:<8}{:<10.3f}{:<10.3f}{:<10.3f}{:<8}\n".format(i, r, g, b, h, s, v, hex_code)
-
plain_text += "\n# Full Colors\n"
grid_list = []
-
for i in (2, 1, 0, 3, 4):
grid_list.append(color_list[idx][0][i].hec)
-
for assit_idx in range(len(color_list[idx][6][i])):
assit_color = gen_assit_color(color_list[idx][0][i], *color_list[idx][6][i][assit_idx][2:6])
-
grid_list.append(assit_color.hec)
-
plain_text += " " + " ".join(grid_list)
-
plain_text += "\n\n# Color Grid ...\n"
-
color_grid = gen_color_grid(color_list[idx][0], color_list[idx][5], color_list[idx][6], grid_list=None, **color_list[idx][8]).tolist()
-
for i in range(len(color_grid)):
grid_list = []
-
for j in range(len(color_grid[i])):
grid_list.append(Color(color_grid[i][j], tp="rgb").hec)
-
plain_text += " " + " ".join(grid_list) + "\n"
-
plain_text += "\n"
-
plain_text += "\n"
-
return plain_text
def import_text(file_path):
- """
- Import color list from plain text (for directly reading).
-
- Args:
- file_path (str): plain text.
-
- Returns:
- grid list (contains colors, names).
- """
-
grid_list = []
name_list = []
-
with open(file_path, "r", encoding="utf-8") as df:
data = df.read()
-
grid_list = Color.findall_hec_lst(data)
name_list = ["",] * len(grid_list)
-
return grid_list, name_list
def export_list(color_list):
- """
- Export color set list in list type (for Rickrack output).
-
- Args:
- color_list (tuple or list): [(color_set, hm_rule, name, desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values), ...]
-
- Returns:
- Json List.
- """
-
expt_list = []
-
for color in color_list:
color_dict = {"rule": color[1], "name": color[2], "desc": color[3], "time": list(color[4])}
-
for i in (2, 1, 0, 3, 4):
color_dict["color_{}".format(i)] = color[0][i].export()
-
color_dict["grid_locations"] = color[5]
color_dict["grid_assitlocs"] = color[6]
color_dict["grid_list"] = color[7]
color_dict["grid_values"] = color[8]
-
expt_list.append(color_dict)
-
return expt_list
diff --git a/src/main/python/ricore/grid.py b/src/main/python/ricore/grid.py
index 22893d9..719fb48 100644
--- a/src/main/python/ricore/grid.py
+++ b/src/main/python/ricore/grid.py
@@ -20,432 +20,262 @@
def gen_color_grid(color_set, grid_locations, grid_assitlocs, grid_list=None, col=9, ctp=("r", "g", "b"), sum_factor=1.0, dim_factor=1.0, assist_factor=0.4, rev_grid=False):
- """
- Generate color grid (board) from peroid colors and points (or fixed point list).
-
- Args:
- color_set (tuple or list): colors in color set.
- grid_locations (tuple or list): main of colors in color set.
- grid_assitlocs (tuple or list): assistant colors around color set.
- grid_list (tuple or list): fix the grid instead generate grid from color points, contains color list and name list.
- col (int): grid coulmn. suggest 0~50.
- ctp (str): color type, "r", "g", "b" or "h", "s", "v".
- sum_factor (int or float): sum factor, suggest 0~5. The larger the sum_factor is, the larger the circile is.
- dim_factor (int or float): dim factor, suggest 0~1. The larger the dim_factor is, the lighter the circile is.
- assist_factor (int or float): weight for assistant points, suggest 0~1. The larger the assist_factor is, the heavier the weight is.
- rev_grid (bool): if rgb grid generation reversed.
-
- Returns:
- color grid in rgb type.
- """
-
if grid_list and grid_list[0]:
color_grid_a = np.ones((col, col)) * 255
color_grid_b = np.ones((col, col)) * 255
color_grid_c = np.ones((col, col)) * 255
-
for fixed_idx in range(len(grid_list[0])):
if fixed_idx < col * col:
r, g, b = Color.hec2rgb(grid_list[0][fixed_idx])
-
color_grid_a[fixed_idx // col, fixed_idx % col] = r
color_grid_b[fixed_idx // col, fixed_idx % col] = g
color_grid_c[fixed_idx // col, fixed_idx % col] = b
-
final_grid = np.stack((color_grid_a, color_grid_b, color_grid_c), axis=2)
final_grid = Color.fmt_rgb_array(final_grid)
-
return final_grid
-
else:
assi_colors = [[], [], [], [], []]
assi_points = [[], [], [], [], []]
-
colors = []
points = []
-
- # two loops shouldn't be not merged because of the sequence.
- # main loop.
for idx in range(5):
pt_rxy = np.array(grid_locations[idx])
-
- # assistant points.
for assit_idx in range(len(grid_assitlocs[idx])):
assit_rpt = pt_rxy + np.array(grid_assitlocs[idx][assit_idx][0:2])
assi_points[idx].append(assit_rpt)
-
assit_color = gen_assit_color(color_set[idx], *grid_assitlocs[idx][assit_idx][2:6])
assi_colors[idx].append(assit_color)
-
- # periodical points: main and around points.
for shift_i in (-1, 0, 1):
for shift_j in (-1, 0, 1):
if "r" in ctp or "g" in ctp or "b" in ctp:
pt_color = color_set[idx].rgb
-
else:
pt_color = list(color_set[idx].hsv)
pt_color[0] = color_set[0].ref_h(pt_color[0])
-
colors.append(pt_color)
points.append(np.array(grid_locations[idx]) + np.array((shift_i, shift_j)))
-
- # assistant loop.
for idx in range(5):
for assidx in range(len(assi_colors[idx])):
if "r" in ctp or "g" in ctp or "b" in ctp:
pt_color = assi_colors[idx][assidx].rgb
-
else:
pt_color = list(assi_colors[idx][assidx].hsv)
pt_color[0] = color_set[0].ref_h(pt_color[0])
-
colors.append(pt_color)
points.append(np.array(assi_points[idx][assidx]))
-
colors = np.array(colors)
points = np.array(points)
-
distance_grid = []
-
for p in range(len(points)):
grid_x = (np.arange(col, dtype=float) + 0.5) / col
grid_y = (np.arange(col, dtype=float) + 0.5) / col
-
grid_x = (grid_x - points[p][0]) ** 2
grid_y = (grid_y - points[p][1]) ** 2
-
grid = np.array([grid_x,] * col, dtype=float).T + np.array([grid_y,] * col, dtype=float)
-
distance_grid.append(grid)
-
distance_grid = np.array(distance_grid, dtype=float)
distance_grid = distance_grid ** sum_factor
-
distance_grid[np.where(distance_grid < 0.001)] = 0.001
distance_grid = 1.0 / distance_grid
-
distance_grid[45:] = distance_grid[45:] * assist_factor
distance_grid = distance_grid / distance_grid.sum(axis=0)
distance_grid = distance_grid * dim_factor
distance_grid = distance_grid.swapaxes(0, 2)
-
if rev_grid:
if "r" in ctp or "g" in ctp or "b" in ctp:
color_grid_a = distance_grid.dot(255.0 - colors[:, 0]) if "r" in ctp else np.ones((col, col)) * (255.0 - color_set[0].r)
color_grid_b = distance_grid.dot(255.0 - colors[:, 1]) if "g" in ctp else np.ones((col, col)) * (255.0 - color_set[0].g)
color_grid_c = distance_grid.dot(255.0 - colors[:, 2]) if "b" in ctp else np.ones((col, col)) * (255.0 - color_set[0].b)
-
color_grid_a = 255.0 - color_grid_a
color_grid_b = 255.0 - color_grid_b
color_grid_c = 255.0 - color_grid_c
-
else:
color_grid_a = distance_grid.dot( colors[:, 0]) + color_set[0].h if "h" in ctp else np.ones((col, col)) * ( color_set[0].h)
color_grid_b = distance_grid.dot( colors[:, 1]) if "s" in ctp else np.ones((col, col)) * ( color_set[0].s)
color_grid_c = distance_grid.dot(1.0 - colors[:, 2]) if "v" in ctp else np.ones((col, col)) * (1.0 - color_set[0].v)
-
color_grid_c = 1.0 - color_grid_c
-
else:
if "r" in ctp or "g" in ctp or "b" in ctp:
color_grid_a = distance_grid.dot(colors[:, 0]) if "r" in ctp else np.ones((col, col)) * color_set[0].r
color_grid_b = distance_grid.dot(colors[:, 1]) if "g" in ctp else np.ones((col, col)) * color_set[0].g
color_grid_c = distance_grid.dot(colors[:, 2]) if "b" in ctp else np.ones((col, col)) * color_set[0].b
-
else:
color_grid_a = distance_grid.dot(colors[:, 0]) + color_set[0].h if "h" in ctp else np.ones((col, col)) * color_set[0].h
color_grid_b = distance_grid.dot(colors[:, 1]) if "s" in ctp else np.ones((col, col)) * color_set[0].s
color_grid_c = distance_grid.dot(colors[:, 2]) if "v" in ctp else np.ones((col, col)) * color_set[0].v
-
final_grid = np.stack((color_grid_a, color_grid_b, color_grid_c), axis=2)
-
if "r" in ctp or "g" in ctp or "b" in ctp:
final_grid = Color.fmt_rgb_array(final_grid)
-
else:
final_grid = Color.hsv2rgb_array(final_grid)
-
return final_grid
def norm_grid_locations(grid_locations, grid_assitlocs):
- """
- Verify and normalize value grid_locations and grid_assitlocs in args.
-
- Args:
- grid_locations (tuple or list): ref to self._args.sys_grid_locations. default value.
- grid_assitlocs (tuple or list): ref to self._args.sys_grid_assitlocs. default value.
-
- Returns:
- corrected grid_locations and grid_assitlocs.
- """
-
cr_grid_locations = []
cr_grid_assitlocs = [[], [], [], [], []]
-
clear_grid_loc = False
clear_assi_loc = False
-
if len(grid_locations) == 5:
for grid_i in range(5):
if len(grid_locations[grid_i]) == 2:
loc_x = grid_locations[grid_i][0]
loc_y = grid_locations[grid_i][1]
-
if isinstance(loc_x, (int, float)) and isinstance(loc_y, (int, float)):
loc_x = 0.0 if loc_x < 0.0 else loc_x
loc_y = 0.0 if loc_y < 0.0 else loc_y
loc_x = 1.0 if loc_x > 1.0 else loc_x
loc_y = 1.0 if loc_y > 1.0 else loc_y
-
cr_grid_locations.append((float(loc_x), float(loc_y)))
-
else:
clear_grid_loc = True
-
else:
clear_grid_loc = True
-
if clear_grid_loc:
break
-
else:
clear_grid_loc = True
-
if not clear_grid_loc and len(grid_assitlocs) == 5:
for grid_i in range(5):
for grid_j in range(len(grid_assitlocs[grid_i])):
if len(grid_assitlocs[grid_i][grid_j]) == 4:
loc_a, loc_b, loc_c, loc_d = grid_assitlocs[grid_i][grid_j]
-
if isinstance(loc_a, (int, float)) and isinstance(loc_b, (int, float)) and isinstance(loc_c, str) and loc_c in ("h", "s", "v") and isinstance(loc_d, (int, float)):
loc_a = -1.0 if loc_a < -1.0 else loc_a
loc_b = -1.0 if loc_b < -1.0 else loc_b
loc_a = 1.0 if loc_a > 1.0 else loc_a
loc_b = 1.0 if loc_b > 1.0 else loc_b
-
if loc_c == "h":
h, s, v = loc_d, 0, 0
-
elif loc_c == "s":
h, s, v = 0, loc_d, 0
-
else:
h, s, v = 0, 0, loc_d
-
loc_a, loc_b, loc_c, loc_d, loc_e, loc_f = float(loc_a), float(loc_b), float(h), float(s), float(v), True
-
else:
loc_a, loc_b, loc_c, loc_d, loc_e, loc_f = None, None, None, None, None, None
-
elif len(grid_assitlocs[grid_i][grid_j]) == 6:
loc_a, loc_b, loc_c, loc_d, loc_e, loc_f = grid_assitlocs[grid_i][grid_j]
-
else:
loc_a, loc_b, loc_c, loc_d, loc_e, loc_f = None, None, None, None, None, None
-
if isinstance(loc_a, (int, float)) and isinstance(loc_b, (int, float)) and isinstance(loc_c, (int, float)) and isinstance(loc_d, (int, float)) and isinstance(loc_e, (int, float)):
loc_a = -1.0 if loc_a < -1.0 else loc_a
loc_b = -1.0 if loc_b < -1.0 else loc_b
loc_a = 1.0 if loc_a > 1.0 else loc_a
loc_b = 1.0 if loc_b > 1.0 else loc_b
-
cr_grid_assitlocs[grid_i].append([float(loc_a), float(loc_b), float(loc_c), float(loc_d), float(loc_e), bool(loc_f)])
-
else:
clear_assi_loc = True
-
if clear_assi_loc:
break
-
else:
clear_assi_loc = True
-
if clear_grid_loc:
cr_grid_locations = [(0.5, 0.5), (0.85, 0.85), (0.15, 0.85), (0.85, 0.15), (0.15, 0.15)]
-
if clear_assi_loc:
cr_grid_assitlocs = [[], [], [], [], []]
-
return cr_grid_locations, cr_grid_assitlocs
def norm_grid_list(grid_list):
- """
- Verify and normalize value grid_list in args.
-
- Args:
- grid_list (tuple or list): ref to self._args.sys_grid_list. default value. contains color list and name list.
-
- Returns:
- corrected grid_list.
- """
-
cr_colr_list = []
cr_name_list = []
-
if isinstance(grid_list, (tuple, list)) and grid_list:
grid_tran = grid_list
name_tran = []
-
if isinstance(grid_list[0], (tuple, list)):
grid_tran = grid_list[0]
-
if isinstance(grid_list[1], (tuple, list)):
name_tran = grid_list[1]
-
for grid_item_idx in range(len(grid_tran)):
color = Color.stri2color(grid_tran[grid_item_idx])
-
if color:
cr_colr_list.append(color.hec)
-
if len(name_tran) > grid_item_idx:
name_stri = re.split(r"[\v\a\f\n\r\t]", str(name_tran[grid_item_idx]))
-
while "" in name_stri:
name_stri.remove("")
-
if name_stri:
name_stri = name_stri[0].lstrip().rstrip()
-
else:
name_stri = ""
-
cr_name_list.append(name_stri)
-
else:
cr_name_list.append("")
-
else:
cr_colr_list.append("FFFFFF")
cr_name_list.append("")
-
cr_grid_list = [cr_colr_list, cr_name_list]
-
return cr_grid_list
def norm_grid_values(grid_values):
- """
- Verify and normalize value grid_values in args.
-
- Args:
- grid_values (dict): ref to self._args.sys_grid_values. default value.
-
- Returns:
- corrected grid_values.
- """
-
cr_grid_values = {"col": 9, "ctp": ("r", "g", "b"), "sum_factor": 1.0, "dim_factor": 1.0, "assist_factor": 0.4, "rev_grid": False}
-
if isinstance(grid_values, dict):
if "col" in grid_values:
value = grid_values["col"]
-
if isinstance(value, (int, float)):
value = 1 if value < 1 else value
value = 51 if value > 51 else value
-
cr_grid_values["col"] = int(value)
-
if "ctp" in grid_values:
value = grid_values["ctp"]
-
if isinstance(value, (tuple, list)):
ctp_lst = []
-
if "r" in value or "g" in value or "b" in value:
for ctp in ("r", "g", "b"):
if ctp in value:
ctp_lst.append(ctp)
-
else:
for ctp in ("h", "s", "v"):
if ctp in value:
ctp_lst.append(ctp)
-
if not ctp_lst:
ctp_lst = ("r", "g", "b")
-
cr_grid_values["ctp"] = tuple(ctp_lst)
-
if "sum_factor" in grid_values:
value = grid_values["sum_factor"]
-
if isinstance(value, (int, float)):
value = 0.0 if value < 0.0 else value
value = 5.0 if value > 5.0 else value
-
cr_grid_values["sum_factor"] = float(value)
-
if "dim_factor" in grid_values:
value = grid_values["dim_factor"]
-
if isinstance(value, (int, float)):
value = 0.0 if value < 0.0 else value
value = 1.0 if value > 1.0 else value
-
cr_grid_values["dim_factor"] = float(value)
-
if "assist_factor" in grid_values:
value = grid_values["assist_factor"]
-
if isinstance(value, (int, float)):
value = 0.0 if value < 0.0 else value
value = 1.0 if value > 1.0 else value
-
cr_grid_values["assist_factor"] = float(value)
-
if "rev_grid" in grid_values:
value = grid_values["rev_grid"]
-
if isinstance(value, (int, float, bool)):
cr_grid_values["rev_grid"] = bool(value)
-
return cr_grid_values
def gen_assit_color(curr_color, assit_h, assit_s, assit_v, relativity):
- """
- Generate assit color relative to current color.
-
- Args:
- assit_h: delta h or absoluate h value.
- assit_s: delta s or absoluate s value.
- assit_v: delta v or absoluate v value.
- relativity: is relative or absoluate.
-
- Returns:
- assit color.
- """
-
if relativity:
assit_color = Color((
curr_color.h + assit_h,
curr_color.s + assit_s,
curr_color.v + assit_v,
), tp="hsv", overflow=curr_color.get_overflow())
-
else:
assit_color = Color((
assit_h,
assit_s,
assit_v,
), tp="hsv", overflow=curr_color.get_overflow())
-
return assit_color
def gen_assit_args(curr_color, assit_color, relativity):
- """
- Generate assit arguments relative to current color.
- """
-
if relativity:
assit_h = assit_color.h - curr_color.h
assit_s = assit_color.s - curr_color.s
assit_v = assit_color.v - curr_color.v
-
else:
assit_h = assit_color.h
assit_s = assit_color.s
assit_v = assit_color.v
-
return assit_h, assit_s, assit_v
diff --git a/src/main/python/ricore/history.py b/src/main/python/ricore/history.py
index 1b8d3c0..83de940 100644
--- a/src/main/python/ricore/history.py
+++ b/src/main/python/ricore/history.py
@@ -18,39 +18,22 @@
class History(object):
- """
- History object. Undo and redo operations.
- """
-
def __init__(self, args):
- """
- Init history.
- """
-
self._args = args
-
self._curr_idx = 0
self._history_line = []
-
self._moving = False
self._recording = False
def backup(self):
- """
- Create a history step.
- """
-
if self._moving:
return
-
if self._curr_idx != len(self._history_line) - 1:
self._curr_idx = self._curr_idx if self._curr_idx < len(self._history_line) else len(self._history_line) - 1
self._history_line = self._history_line[:self._curr_idx + 1]
-
if len(self._history_line) > self._args.max_history_steps:
self._curr_idx = self._curr_idx - (len(self._history_line) - self._args.max_history_steps)
self._history_line = self._history_line[len(self._history_line) - self._args.max_history_steps: ]
-
step_md5 = ""
step_md5 = step_md5 + hashlib.md5(str(self._args.hm_rule).encode("utf-8")).hexdigest()[:10]
step_md5 = step_md5 + hashlib.md5(str(self._args.sys_color_set).encode("utf-8")).hexdigest()[:10]
@@ -60,100 +43,57 @@ def backup(self):
step_md5 = step_md5 + hashlib.md5(str(self._args.sys_grid_values).encode("utf-8")).hexdigest()[:10]
step_md5 = step_md5 + hashlib.md5(str(self._args.sys_color_locs.count(None)).encode("utf-8")).hexdigest()[:10]
step_md5 = hashlib.md5(step_md5.encode("utf-8")).hexdigest()[:10]
-
- # display info.
# print("{} / {} -> {}".format(self._curr_idx, len(self._history_line), step_md5))
-
if len(self._history_line) > 0 and step_md5 == self._history_line[-1][1]:
return
-
self._recording = True
-
step = []
-
- # color set.
step.append(str(self._args.hm_rule))
step.append(self._args.sys_color_set.backup())
-
- # grid values.
step.append(copy.deepcopy(self._args.sys_grid_locations))
step.append(copy.deepcopy(self._args.sys_grid_assitlocs))
step.append(copy.deepcopy(self._args.sys_grid_list))
step.append(copy.deepcopy(self._args.sys_grid_values))
-
- # image values.
step.append(copy.deepcopy(self._args.sys_color_locs))
step.append(copy.deepcopy(self._args.sys_assit_color_locs))
-
self._curr_idx = self._curr_idx + 1
self._history_line.append((tuple(step), step_md5))
-
self._recording = False
def undo(self):
- """
- Move backward.
- """
-
if self._recording:
return
-
if self._curr_idx <= 0:
self._curr_idx = 0
-
return
-
self._moving = True
-
self._curr_idx = self._curr_idx - 1
step = self._history_line[self._curr_idx][0]
-
- # color set.
self._args.hm_rule = str(step[0])
self._args.sys_color_set.recover(step[1])
-
- # grid values.
self._args.sys_grid_locations = copy.deepcopy(step[2])
self._args.sys_grid_assitlocs = copy.deepcopy(step[3])
self._args.sys_grid_list = copy.deepcopy(step[4])
self._args.sys_grid_values = copy.deepcopy(step[5])
-
- # image values.
self._args.sys_color_locs = copy.deepcopy(step[6])
self._args.sys_assit_color_locs = copy.deepcopy(step[7])
-
self._moving = False
def redo(self):
- """
- Move foreward.
- """
-
if self._recording:
return
-
if self._curr_idx >= len(self._history_line) - 1:
self._curr_idx = len(self._history_line) - 1
-
return
-
self._moving = True
-
self._curr_idx = self._curr_idx + 1
step = self._history_line[self._curr_idx][0]
-
- # color set.
self._args.hm_rule = str(step[0])
self._args.sys_color_set.recover(step[1])
-
- # grid values.
self._args.sys_grid_locations = copy.deepcopy(step[2])
self._args.sys_grid_assitlocs = copy.deepcopy(step[3])
self._args.sys_grid_list = copy.deepcopy(step[4])
self._args.sys_grid_values = copy.deepcopy(step[5])
-
- # image values.
self._args.sys_color_locs = copy.deepcopy(step[6])
self._args.sys_assit_color_locs = copy.deepcopy(step[7])
-
self._moving = False
diff --git a/src/main/python/ricore/icon.py b/src/main/python/ricore/icon.py
index d291442..939fa1b 100644
--- a/src/main/python/ricore/icon.py
+++ b/src/main/python/ricore/icon.py
@@ -22,243 +22,139 @@
__SVG_FMT__ = """
-
+
{context}
-
+
"""
__SVG_WHEEL__ = """
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
"""
__SVG_IMAGE__ = """
-
-
-
-
-
-
+
+
+
+
"""
__SVG_BOARD__ = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
"""
__SVG_DEPOT__ = """
-
-
-
-
-
-
+
+
+
+
"""
__SVG_ABOUT__ = """
-
-
-
-
+
+
"""
__SVG_INFO__ = """
-
-
-
+
"""
__SVG_SETTINGS__ = """
-
-
-
-
+
+
"""
__SVG_SAVE__ = """
-
-
-
+
"""
__SVG_OPEN__ = """
-
-
-
+
"""
__SVG_QUIT__ = """
-
-
-
+
"""
__SVG_HOME__ = """
-
-
-
+
"""
__SVG_UPDATE__ = """
-
-
-
+
+"""
+
+__SVG_FORUM__ = """
+
"""
__SVG_UP__ = """
-
-
-
+
"""
__SVG_DOWN__ = """
-
-
-
+
"""
__SVG_LEFT__ = """
-
-
-
+
"""
__SVG_RIGHT__ = """
-
-
-
+
"""
__SVG_ZOOM_IN__ = """
-
-
-
+
"""
__SVG_ZOOM_OUT__ = """
-
-
-
+
"""
__SVG_RESET__ = """
-
-
-
+
+"""
+
+__SVG_LAYOUT_L__ = """
+
+"""
+
+__SVG_LAYOUT_R__ = """
+
"""
import os
from PyQt5.QtGui import QIcon
-def get_icon(name, forecolor, backcolor, temp_dir, default):
+def get_icon(name, forecolor, backcolor, higopacity, lowopacity, temp_dir, default):
name_dict = {
+ "sel_wheel": __SVG_WHEEL__,
+ "sel_image": __SVG_IMAGE__,
+ "sel_board": __SVG_BOARD__,
+ "sel_depot": __SVG_DEPOT__,
"wheel": __SVG_WHEEL__,
"image": __SVG_IMAGE__,
"board": __SVG_BOARD__,
@@ -271,6 +167,7 @@ def get_icon(name, forecolor, backcolor, temp_dir, default):
"quit": __SVG_QUIT__,
"home": __SVG_HOME__,
"update": __SVG_UPDATE__,
+ "forum": __SVG_FORUM__,
"up": __SVG_UP__,
"down": __SVG_DOWN__,
"left": __SVG_LEFT__,
@@ -278,18 +175,15 @@ def get_icon(name, forecolor, backcolor, temp_dir, default):
"reset": __SVG_RESET__,
"zoom_in": __SVG_ZOOM_IN__,
"zoom_out": __SVG_ZOOM_OUT__,
+ "layout_l": __SVG_LAYOUT_L__,
+ "layout_r": __SVG_LAYOUT_R__,
}
-
- size = "100"
-
- if name in ("up", "down", "left", "right", "reset", "zoom_in", "zoom_out", "info"):
- size = "24"
-
+ size = "24"
+ if name in ("sel_wheel", "sel_image", "sel_board", "sel_depot", "wheel", "image", "board", "depot", "about", "settings",):
+ size = "100"
if os.path.isdir(temp_dir) and name in name_dict:
with open(os.sep.join([temp_dir, "{}.svg".format(name)]), "w") as f:
- context = name_dict[name].format(forecolor=forecolor, backcolor=backcolor, stroke=6, opacity=0.3)
+ context = name_dict[name].format(forecolor=forecolor, backcolor=backcolor, stroke=6, higopacity=higopacity, lowopacity=lowopacity)
f.write(__SVG_FMT__.format(context=context, size=size)[1:])
-
return QIcon(os.sep.join([temp_dir, "{}.svg".format(name)]))
-
return default
diff --git a/src/main/python/ricore/image_act.py b/src/main/python/ricore/image_act.py
index 9c84aa3..ef5b3db 100644
--- a/src/main/python/ricore/image_act.py
+++ b/src/main/python/ricore/image_act.py
@@ -18,81 +18,50 @@
def extract_image(display_data, rand_num, color_type):
- """
- Extract a set of colors in different extract types.
-
- Args:
- process_scope (tuple or list): in format (start point, total length), e.g. (0, 100).
- values (tuple or list): (random number, color type).
- """
-
if rand_num > 0 and (display_data.shape[0] * display_data.shape[1]) > rand_num:
data_pos = ((np.random.rand(rand_num) * display_data.shape[0]).astype(int), (np.random.rand(rand_num) * display_data.shape[1]).astype(int))
data = display_data[data_pos]
-
else:
data = np.vstack(display_data)
-
data = data // 2 * 2
data = np.unique(data, axis=0)
-
if len(data) > 240:
data_pos = np.where(np.logical_not(((data[:, 0] < 25) & (data[:, 1] < 25) & (data[:, 2] < 25)) | ((data[:, 0] > 225) & (data[:, 1] > 225) & (data[:, 2] > 225))))
-
if len(data_pos[0]) > 240:
data = data[data_pos]
-
data = Color.rgb2hsv_array(np.array([data,]))[0]
-
s_range = (data[:, 1].min(), data[:, 1].max())
v_range = (data[:, 2].min(), data[:, 2].max())
-
for ext in (0.5, 0.45, 0.4, 0.35, 0.3, 0.25, 0.2, 0.15, 0.1, 0.05, 0.0):
if color_type == 0:
data_pos = np.where((data[:, 1] > s_range[0] + (s_range[1] - s_range[0]) * ext * 0.5) & (data[:, 2] > v_range[0] + (v_range[1] - v_range[0]) * (ext + 0.1) * 0.5))
-
elif color_type == 1:
data_pos = np.where((data[:, 1] < s_range[1] - (s_range[1] - s_range[0]) * ext * 0.5) & (data[:, 2] > v_range[0] + (v_range[1] - v_range[0]) * (ext + 0.1) * 0.5))
-
elif color_type == 2:
data_pos = np.where(data[:, 2] < v_range[1] - (v_range[1] - v_range[0]) * (ext + 0.1) * 0.5)
-
elif color_type == 3:
data_pos = np.where((data[:, 1] > s_range[0] + (s_range[1] - s_range[0]) * ext) & (data[:, 2] > v_range[0] + (v_range[1] - v_range[0]) * (ext + 0.1)))
-
elif color_type == 4:
data_pos = np.where((data[:, 1] < s_range[1] - (s_range[1] - s_range[0]) * ext) & (data[:, 2] > v_range[0] + (v_range[1] - v_range[0]) * (ext + 0.1)))
-
else:
data_pos = np.where(data[:, 2] < v_range[1] - (v_range[1] - v_range[0]) * (ext + 0.1))
-
if len(data_pos[0]) > 120:
data = data[data_pos]
-
break
-
extracts = []
-
h_range = (data[:, 0].min(), data[:, 0].max())
h_range = (h_range[0], h_range[1] - 1 / 12 * (h_range[1] - h_range[0]))
-
for idx in range(5):
mu = h_range[0] + (h_range[1] - h_range[0]) / 4 * idx
sigma = (h_range[1] - h_range[0]) / 5
-
for ext in (-0.5, -0.4, -0.3, -0.25, -0.2, -0.15, -0.1, -0.05, 0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 2.0):
data_pos = np.where((data[:, 0] > (mu - sigma - ext * sigma - 1E-3)) & (data[:, 0] < (mu + sigma + ext * sigma + 1E-3)))
-
if len(data_pos[0]) > 1:
break
-
sample = data[data_pos]
sample = sample[int(sample.shape[0] * 0.5)]
sample = Color.hsv2rgb(sample)
-
sample_pos = np.where((display_data[:, :, 0] > sample[0] - 3) & (display_data[:, :, 0] < sample[0] + 3) & (display_data[:, :, 1] > sample[1] - 3) & (display_data[:, :, 1] < sample[1] + 3) & (display_data[:, :, 2] > sample[2] - 3) & (display_data[:, :, 2] < sample[2] + 3))
-
pos = int(np.random.random() * len(sample_pos[0]))
extracts.append((sample_pos[1][pos] / (display_data.shape[1] - 1), sample_pos[0][pos] / (display_data.shape[0] - 1)))
-
return extracts
diff --git a/src/main/python/ricore/server_req.py b/src/main/python/ricore/server_req.py
index 4340786..632dff5 100644
--- a/src/main/python/ricore/server_req.py
+++ b/src/main/python/ricore/server_req.py
@@ -21,109 +21,75 @@
class Request(BaseRequestHandler):
- """
- Request object. Provide result by socket server.
- """
-
def handle(self):
- """
- Get method.
- """
-
if self.client_address[0] not in ("127.0.0.1", "localhost"):
return
-
req = self.request.recv(4)
req = req.decode("utf-8")
-
if req == "cidx":
text = self.request.recv(1024)
text = text.decode("utf-8")
text = text.split("; ")
-
if len(text) > 0 and text[0] and text[0] in [str(i) for i in range(5)]:
color_idx = int(text[0])
-
else:
color_idx = None
-
if len(text) > 1 and text[1]:
try:
color = tuple([float(i) for i in text[1].split(" ")])
-
except Exception as err:
color = ()
-
if len(color) == 3:
self.ps_cidx.emit((color_idx, color))
-
elif req == "star":
text = self.request.recv(1024)
text = text.decode("utf-8")
text = text.lstrip().rstrip()
-
if text:
self.args.sys_choice_stat.append(text)
self.ps_star.emit(True)
-
elif req == "stat":
self.request.sendall(str(int(bool(self.args.sys_choice_stat))).encode("utf-8"))
-
elif req == "iset":
path = self.request.recv(1024)
path = path.decode("utf-8")
path = path.lstrip().rstrip()
-
if os.path.isfile(path) and path[-4:] == ".dps":
self.ps_iset.emit(path)
-
elif req == "oset":
path = self.request.recv(1024)
path = path.decode("utf-8")
path = path.lstrip().rstrip()
-
if os.path.isdir(os.path.dirname(path)) and path[-4:] == ".dps":
self.ps_oset.emit(path)
-
elif req == "idpt":
path = self.request.recv(1024)
path = path.decode("utf-8")
path = path.lstrip().rstrip()
-
if os.path.isfile(path) and path[-4:] == ".dpc":
self.ps_idpt.emit(path)
-
elif req == "odpt":
path = self.request.recv(1024)
path = path.decode("utf-8")
path = path.lstrip().rstrip()
-
if os.path.isdir(os.path.dirname(path)) and path[-4:] == ".dpc":
self.ps_odpt.emit(path)
-
elif req == "data":
rule = self.args.hm_rule[0].upper() + self.args.hm_rule[1:]
-
main_color_list, main_cname_list = get_export_color_list([(self.args.sys_color_set, self.args.hm_rule, "RR", "", (time.time(), time.time()), self.args.sys_grid_locations, self.args.sys_grid_assitlocs, self.args.sys_grid_list, self.args.sys_grid_values),], export_grid=False)
grid_color_list, grid_cname_list = get_export_color_list([(self.args.sys_color_set, self.args.hm_rule, "RR", "", (time.time(), time.time()), self.args.sys_grid_locations, self.args.sys_grid_assitlocs, self.args.sys_grid_list, self.args.sys_grid_values),], export_grid=True)
-
text = ""
text += "{}; ".format(rule)
text += "{}; ".format(self.args.sys_activated_idx)
text += "{}; ".format(" ".join([i.hec for i in main_color_list]))
text += "{}; ".format(self.args.sys_grid_values["col"])
text += "{}; ".format(" ".join([i.hec for i in grid_color_list]))
-
if self.args.sys_grid_list[0]:
text += " ".join(['"{}"'.format(i) for i in grid_cname_list])
-
text = text.encode("utf-8")
text = "{:10d}".format(len(text)).encode("utf-8") + text
-
self.request.sendall(text)
-
elif req == "exit":
text = self.request.recv(1)
text = text.decode("utf-8")
-
self.ps_exit.emit(text in ("T", "1"))
diff --git a/src/main/python/ricore/transpt.py b/src/main/python/ricore/transpt.py
index 9739bdd..3c2bee8 100644
--- a/src/main/python/ricore/transpt.py
+++ b/src/main/python/ricore/transpt.py
@@ -17,305 +17,143 @@
def rotate_point(point, theta):
- """
- Rotate point in anti-clockwise direction. Rotating center is (0, 0), theta is in angle type and r_theta is in radian type.
-
- Args:
- point (tuple or list): point for rotating.
- theta (int or float): rotating angle (in angle type).
-
- Returns:
- rotated point.
- """
-
r_theta = theta * np.pi / 180
Rz = np.array([
[np.cos(r_theta), np.sin(r_theta) * -1],
[np.sin(r_theta), np.cos(r_theta) ],
])
-
pt = Rz.dot(np.array(point))
-
return pt
def rotate_point_center(center, point, theta):
- """
- Rotate point in anti-clockwise direction around given center.
-
- Args:
- center (tuple or list): rotating center.
- point (tuple or list): point for rotating.
- theta (int or float): rotating angle (in angle type).
-
- Returns:
- rotated point.
- """
-
delta_point = np.array(point) - np.array(center)
rotated_point = rotate_point(delta_point, theta)
-
pt = rotated_point + np.array(center)
-
return pt
def get_theta(point):
- """
- Get angle between point and x axis in anti-clockwise direction. Center is (0, 0).
-
- Args:
- point (tuple or list): rotated point.
-
- Returns:
- rotated theta.
- """
-
delta_x = point[0]
delta_y = point[1]
-
if delta_x == 0:
if delta_y > 0:
hue = 90
-
else:
hue = 270
-
else:
_hue = np.arctan(delta_y / delta_x) * 180 / np.pi
-
if delta_x > 0:
hue = _hue if _hue > 0 else 360 + _hue
-
else:
hue = _hue + 180
-
return hue
def get_theta_center(center, point):
- """
- Get angle between point and x axis in anti-clockwise direction around given center.
-
- Args:
- center (tuple or list): rotating center.
- point (tuple or list): rotated point.
-
- Returns:
- rotated theta.
- """
-
delta_point = np.array(point) - np.array(center)
-
hue = get_theta(delta_point)
-
return hue
def get_outer_box(center, radius):
- """
- Get outer box of circle with raduis.
-
- Args:
- center (tuple or list): circle center.
- radius (int or float): circle radius.
-
- Returns:
- outer box.
- """
-
box = np.array((center[0] - radius, center[1] - radius, 2 * radius, 2 * radius))
-
return box
def get_box_center(box):
- """
- Get the center of a circle box.
-
- Args:
- box (tuple or list): circle box.
-
- Returns:
- center.
- """
-
# radius , box[2] / 2
-
return np.array((box[0] + box[2] / 2, box[1] + box[3] / 2))
def get_link_tag(box):
- """
- Get link tag shape with two square and one line.
-
- Args:
- box (tuple or list): outer box.
- """
-
shift = box[2] / 8
shift_box = (box[0] + shift, box[1] + shift, box[2] - shift * 2, box[3] - shift * 2)
-
square_left = np.array((shift_box[0], shift_box[1] + (shift_box[3] - shift_box[2] / 2) / 2, shift_box[2] / 2, shift_box[2] / 2))
square_right = np.array((shift_box[0] + shift_box[2] / 2, shift_box[1] + (shift_box[3] - shift_box[2] / 2) / 2, shift_box[2] / 2, shift_box[2] / 2))
-
line_start = np.array((shift_box[0] + shift_box[2] / 4, shift_box[1] + shift_box[3] / 2))
line_end = np.array((shift_box[0] + shift_box[2] * 3 / 4, shift_box[1] + shift_box[3] / 2))
-
return square_left, square_right, shift, line_start, line_end
def snap_point(pt, wid):
- """
- Snap point on special locations, such as (1, 1) or (0.5, 0.5).
-
- Args:
- pt (tuple or list): point before snap.
- wid (float): box width (or half widh if snap (0.5, 0.5)).
-
- Returns:
- point after snap.
- """
-
x, y = pt
-
if (x % wid) < wid * 0.15:
x = (x // wid) * wid
-
elif (x % wid) > wid * 0.85:
x = (x // wid + 1) * wid
-
if (y % wid) < wid * 0.15:
y = (y // wid) * wid
-
elif (y % wid) > wid * 0.85:
y = (y // wid + 1) * wid
-
return [x, y]
def get_outer_circles(pt_array, activated_idx, pts_array, assit_pts_array, pt_radius, assit_pt_radius, info_pt_radius, last_result, major=True, minor=True):
- """
- Add info circles around pts and ref pts.
-
- Args:
- pt (tuple or list): current point.
- activated_idx (int): current activated index of main points.
- pts (tuple or list): main point locations.
- assit_pts (tuple or list): ref point locations.
- pt_radius (int or float): radius of a main point.
- assit_pt_radius (int or float): radius of a ref point.
- info_pt_radius (int or float): radius of a info point around a main point.
- major (bool): consider major points.
- minor (bool): consider minor points.
-
- Return:
- (sel_idx, sel_assit_idx, is_in_pt, is_in_assit_pt, ((circle_0, pattern_0), (circle_1, pattern_1), ...), sel_info_idx)
- """
-
- # pre-format.
# pt_array = pt # np.array(pt)
# pts_array = pts # [np.array(i) for i in pts]
# assit_pts_array = assit_pts # [[np.array(j) for j in i] for i in assit_pts]
info_pt_radius_int = int(info_pt_radius)
-
- # auto find points with min distance.
- # get distances between mouse pt and main pts (ref pts).
sel_idx = -1
sel_assit_idx = -1
all_pt_dist = []
-
idx_seq = list(range(5))
idx_seq = idx_seq[activated_idx + 1: ] + idx_seq[: activated_idx + 1]
-
pt_info_pt_radius_2 = (pt_radius + info_pt_radius_int * 2) ** 2
pt_radius_2 = pt_radius ** 2
assit_pt_info_pt_radius_2 = (assit_pt_radius + info_pt_radius_int * 2) ** 2
assit_pt_radius_2 = assit_pt_radius ** 2
info_pt_radius_int_2 = info_pt_radius_int ** 2
-
for idx in idx_seq:
pt_dist_2 = np.sum((pt_array - pts_array[idx]) ** 2)
-
if major:
all_pt_dist.append((pt_dist_2, (idx,)))
-
- # without "not last_result".
- # hide info pts when mouse over main points.
if pt_dist_2 < pt_info_pt_radius_2:
sel_idx = idx
-
if pt_dist_2 < pt_radius_2:
return None
-
assit_len = len(assit_pts_array[idx])
-
- # max assit len 30. recommand 25.
if assit_len > 25:
return None
-
for assit_idx in range(assit_len):
assit_pt_dist_2 = np.sum((pt_array - assit_pts_array[idx][assit_idx]) ** 2)
-
if minor:
all_pt_dist.append((assit_pt_dist_2, (idx, assit_idx)))
-
if assit_pt_dist_2 < assit_pt_info_pt_radius_2:
sel_idx = idx
sel_assit_idx = assit_idx
-
if not (minor and last_result) and assit_pt_dist_2 < assit_pt_radius_2:
return None
-
- # get info circle index with min distance.
is_in_pt = False
is_in_assit_pt = False
-
if sel_assit_idx > -1:
is_in_assit_pt = True
-
elif sel_idx > -1:
is_in_pt = True
-
else:
all_pt_dist.sort(key=lambda x: x[0])
sel_pt = all_pt_dist[0]
-
if sel_pt[0] > pt_radius_2 * 4:
return None
-
if len(sel_pt[1]) == 1:
sel_idx = sel_pt[1][0]
sel_assit_idx = -1
-
else:
sel_idx, sel_assit_idx = sel_pt[1]
-
- # without "is_in_pt".
- # always generate circle locations for main points.
if is_in_assit_pt and last_result and sel_idx == last_result[0] and sel_assit_idx == last_result[1] and is_in_pt == last_result[2] and is_in_assit_pt == last_result[3]:
circle_locations = last_result[4]
sel_info_idx = -1
-
for loc_idx in range(len(circle_locations)):
o_center = get_box_center(circle_locations[loc_idx][0])
-
if np.sum((pt_array - o_center) ** 2) < info_pt_radius_int_2:
sel_info_idx = loc_idx
-
else:
circle_locations = []
-
if sel_assit_idx == len(assit_pts_array[sel_idx]):
sel_assit_idx = -1
-
if sel_assit_idx > -1:
info_around_center = assit_pts_array[sel_idx][sel_assit_idx]
info_around_radius = assit_pt_radius + info_pt_radius_int
-
else:
info_around_center = pts_array[sel_idx]
info_around_radius = pt_radius + info_pt_radius_int
-
theta = get_theta_center(info_around_center, pt_array)
info_pt_center = rotate_point_center(info_around_center, (info_around_center[0] + info_around_radius, info_around_center[1]), theta).astype(int)
sel_info_idx = -1
-
if np.sum((pt_array - info_pt_center) ** 2) < info_pt_radius_int_2:
sel_info_idx = 0
-
circle_locations.append((
get_outer_box(info_pt_center, info_pt_radius_int),
info_pt_center + np.array((
@@ -326,7 +164,6 @@ def get_outer_circles(pt_array, activated_idx, pts_array, assit_pts_array, pt_ra
(0, 0.5),
)) * info_pt_radius_int,
))
-
if sel_assit_idx > -1:
theta = theta + 120
info_pt_center = rotate_point_center(info_around_center, (info_around_center[0] + info_around_radius, info_around_center[1]), theta).astype(int)
@@ -337,7 +174,6 @@ def get_outer_circles(pt_array, activated_idx, pts_array, assit_pts_array, pt_ra
( 0.5, 0),
)) * info_pt_radius_int,
))
-
theta = theta + 120
info_pt_center = rotate_point_center(info_around_center, (info_around_center[0] + info_around_radius, info_around_center[1]), theta).astype(int)
circle_locations.append((
@@ -357,5 +193,4 @@ def get_outer_circles(pt_array, activated_idx, pts_array, assit_pts_array, pt_ra
(-0.1216223, -0.2404163),
)) * info_pt_radius_int,
))
-
return (sel_idx, sel_assit_idx, is_in_pt, is_in_assit_pt, circle_locations, sel_info_idx)
diff --git a/src/main/python/wgets/board.py b/src/main/python/wgets/board.py
index 02ce0bf..6a44f81 100644
--- a/src/main/python/wgets/board.py
+++ b/src/main/python/wgets/board.py
@@ -31,178 +31,105 @@
class ColorBox(QDialog, Ui_BoxDialog):
- """
- ColorBox object based on QDialog. Init color box information.
- """
-
ps_value_changed = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init information.
- """
-
super().__init__(wget, Qt.WindowCloseButtonHint)
self.setupUi(self)
-
- # load args.
self._args = args
-
self._init_idx = -1
self._default_name = "Rickrack Color Box"
-
- # load translations.
self._func_tr_()
-
- # init qt args.
app_icon = QIcon()
app_icon.addPixmap(QPixmap(":/images/images/icon_128.png"), QIcon.Normal, QIcon.Off)
self.setWindowIcon(app_icon)
-
# self.setWindowModality(Qt.ApplicationModal)
-
color_grid_layout = QGridLayout(self.color_box)
color_grid_layout.setContentsMargins(1, 1, 1, 1)
-
self.box_sqr = BoxSqr(self, self._args, "FFFFFF")
color_grid_layout.addWidget(self.box_sqr)
self.box_sqr.ps_color_changed.connect(lambda x: self.hec_ledit.setText("#" + str(x)))
-
- # init buttons.
self.buttonBox.clear()
-
self._btn_1 = QPushButton()
self._btn_1.clicked.connect(self.application)
self.buttonBox.addButton(self._btn_1, QDialogButtonBox.AcceptRole)
-
self._btn_2 = QPushButton()
self._btn_2.clicked.connect(self.close)
self.buttonBox.addButton(self._btn_2, QDialogButtonBox.RejectRole)
-
self._btn_3 = QPushButton()
self._btn_3.clicked.connect(self.update_values)
self.buttonBox.addButton(self._btn_3, QDialogButtonBox.ApplyRole)
-
self._btn_4 = QPushButton()
self._btn_4.clicked.connect(self.reset_values)
self.buttonBox.addButton(self._btn_4, QDialogButtonBox.ResetRole)
-
self.hec_ledit.textChanged.connect(self.box_sqr.change_color)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def set_default_name(self, name):
- """
- Set the default name of color box.
- Args:
- name (str): name of color box. default: "Rickrack Color Box".
- """
-
self._default_name = str(name)
def set_context(self, idx):
- """
- Get the index, color and name of color box. Using update_context to update values.
- """
-
self._init_idx = idx
-
if 0 <= self._init_idx < len(self._args.sys_grid_list[0]):
self.index_spb.setMinimum(1)
self.index_spb.setMaximum(len(self._args.sys_grid_list[0]))
-
self.hec_ledit.setText("#" + self._args.sys_grid_list[0][self._init_idx])
self.box_sqr.change_color(self._args.sys_grid_list[0][self._init_idx])
-
name = self._args.sys_grid_list[1][self._init_idx]
-
if not name:
name = self._default_name
-
self.name_ledit.setText(str(name))
-
self.index_spb.setValue(self._init_idx + 1)
-
else:
self._init_idx = len(self._args.sys_grid_list[0])
-
self.index_spb.setMinimum(len(self._args.sys_grid_list[0]) + 1)
self.index_spb.setMaximum(len(self._args.sys_grid_list[0]) + 1)
-
self.hec_ledit.setText("#FFFFFF")
self.box_sqr.change_color("FFFFFF")
self.name_ledit.setText(self._uninit_descs[0])
-
self.index_spb.setValue(len(self._args.sys_grid_list[0]) + 1)
def application(self):
- """
- Modify the values.
- """
-
name = re.split(r"[\v\a\f\n\r\t]", str(self.name_ledit.text()))
-
while "" in name:
name.remove("")
-
if name:
name = name[0].lstrip().rstrip()
-
else:
name = ""
-
idx = self.index_spb.value() - 1
hec_color = self.box_sqr.color.hec
-
if idx == len(self._args.sys_grid_list[0]) and self._init_idx == len(self._args.sys_grid_list[0]):
self._args.sys_grid_list[0].append(hec_color)
self._args.sys_grid_list[1].append(name)
-
elif 0 <= idx < len(self._args.sys_grid_list[0]) and 0 <= self._init_idx < len(self._args.sys_grid_list[0]):
if idx == self._init_idx:
self._args.sys_grid_list[0][idx] = hec_color
self._args.sys_grid_list[1][idx] = name
-
else:
self._args.sys_grid_list[0].pop(self._init_idx)
self._args.sys_grid_list[1].pop(self._init_idx)
-
self._args.sys_grid_list[0].insert(idx, hec_color)
self._args.sys_grid_list[1].insert(idx, name)
-
self.ps_value_changed.emit(True)
def update_values(self):
- """
- For button apply.
- """
-
self.application()
self.set_context(self._init_idx)
def reset_values(self):
- """
- For button reset.
- """
-
self.set_context(self._init_idx)
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self.setWindowTitle(self._dialog_descs[0])
self._btn_1.setText(self._dialog_descs[1])
self._btn_2.setText(self._dialog_descs[2])
self._btn_3.setText(self._dialog_descs[3])
self._btn_4.setText(self._dialog_descs[4])
-
self.retranslateUi(self)
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._dialog_descs = (
_translate("Info", "Information"),
_translate("Info", "OK"),
@@ -210,94 +137,54 @@ def _func_tr_(self):
_translate("Info", "Apply"),
_translate("Info", "Reset"),
)
-
self._uninit_descs = (
_translate("Info", "Uninitialized Color Box"),
)
-
class BoxSqr(QWidget):
- """
- Square objet based on QWidget. Init a color square in box.
- """
-
ps_color_changed = pyqtSignal(str)
def __init__(self, wget, args, hec_color):
- """
- Init color square.
- """
-
super().__init__(wget)
-
- # load args.
self._args = args
-
self.color = Color(hec_color, tp="hec")
- # ---------- ---------- ---------- Paint Funcs ---------- ---------- ---------- #
-
def paintEvent(self, event):
rto = (1.0 - self._args.cubic_ratio) / 2
-
- self._box = [self.width() * rto, self.height() * rto, self.width() * self._args.cubic_ratio, self.height() * self._args.cubic_ratio]
-
+ self._box = (int(self.width() * rto) + self._args.positive_wid, self._args.positive_wid, int(self.width() * self._args.cubic_ratio - self._args.positive_wid * 2), self.height() - self._args.positive_wid * 2)
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setRenderHint(QPainter.TextAntialiasing, True)
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
-
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid * 1.5))
-
painter.setBrush(QColor(*self.color.rgb))
painter.drawRect(*self._box)
-
painter.end()
- # ---------- ---------- ---------- Mouse Event Funcs ---------- ---------- ---------- #
-
def mouseDoubleClickEvent(self, event):
if event.button() == Qt.LeftButton:
p_x = event.x()
p_y = event.y()
-
if self._box[0] < p_x < (self._box[0] + self._box[2]) and self._box[1] < p_y < (self._box[1] + self._box[3]):
dialog = QColorDialog.getColor(QColor(*self.color.rgb))
-
if dialog.isValid():
self.color = Color((dialog.red(), dialog.green(), dialog.blue()), tp="rgb")
-
self.ps_color_changed.emit(self.color.hec)
-
event.accept()
self.update()
-
else:
event.ignore()
-
else:
event.ignore()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def change_color(self, hec_color):
- """
- Find colors in info box.
- """
-
color = Color.stri2color(hec_color)
-
if color:
self.color = color
self.update()
-
class Board(QWidget):
- """
- Board object based on QWidget. Init a gradual board pannel in workarea.
- """
-
ps_index_changed = pyqtSignal(bool)
ps_value_changed = pyqtSignal(bool)
ps_color_changed = pyqtSignal(bool)
@@ -310,319 +197,206 @@ class Board(QWidget):
ps_transfer_image = pyqtSignal(PpmImageFile)
def __init__(self, wget, args):
- """
- Init color set depot.
- """
-
super().__init__(wget)
-
- # set name ids.
wget.setProperty("class", "WorkArea")
-
- # load args.
self._args = args
self._show_points = True
self._moving_maintp = False
self._moving_assitp = False
- self._last_moving = 0 # 0 for moving_maintp just now, 1 for moving_assitp just now.
+ self._last_moving = 0
self._color_grid = []
self._selecting_idx = -1
self._last_selecting_idx = -1
self._connected_keymaps = {}
-
- self._drag_file = False
- self._drop_file = None
- self._press_key = 0
-
- # load translations.
+ self.init_key()
self._func_tr_()
-
- # init qt args.
self.setFocusPolicy(Qt.StrongFocus)
self.setAcceptDrops(True)
-
self._tool_tip_label = QLabel(self)
self._last_tool_tip_label = QLabel(self)
self._color_box = ColorBox(self, self._args)
self._color_box.ps_value_changed.connect(self.update)
self._color_box.ps_value_changed.connect(lambda: self.ps_history_backup.emit(True))
-
- # generate point centers and radii.
- # self._center = ...
- # self._radius = ...
self._tag_centers = [(-100, -100), (-100, -100), (-100, -100), (-100, -100), (-100, -100)]
- # self._tag_radii = ...
self._assit_tag_centers = [[], [], [], [], []]
- # self._assit_tag_radii = ...
-
- # outer circles.
self._outer_circles = None
-
- # shortcut is updated by _setup_skey in main.py.
# self.update_skey()
-
self.create_menu()
self.update_text()
- # ---------- ---------- ---------- Paint Funcs ---------- ---------- ---------- #
-
def paintEvent(self, event):
- # norm assit point index.
if False: # self._args.sys_activated_assit_idx > len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]):
self._args.sys_activated_assit_idx = -1
self.ps_color_changed()
-
if self._args.sys_grid_list[0] and self._show_points:
self._show_points = False
-
self._cs_wid = int(min(self.width(), self.height()) * self._args.board_ratio)
self._cs_box = ((self.width() - self._cs_wid) / 2, (self.height() - self._cs_wid) / 2, self._cs_wid, self._cs_wid)
-
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setRenderHint(QPainter.TextAntialiasing, True)
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
-
- painter.setPen(QPen(QColor(*self._args.wheel_ed_color), self._args.wheel_ed_wid))
- painter.setBrush(Qt.white)
- painter.drawRect(*self._cs_box)
-
idx_seq = list(range(5))
idx_seq = idx_seq[self._args.sys_activated_idx + 1: ] + idx_seq[: self._args.sys_activated_idx + 1]
-
- # draw color grid.
self._color_grid = gen_color_grid(self._args.sys_color_set, self._args.sys_grid_locations, self._args.sys_grid_assitlocs, grid_list=self._args.sys_grid_list, **self._args.sys_grid_values)
-
grid_img = QImage(self._color_grid, self._color_grid.shape[1], self._color_grid.shape[0], self._color_grid.shape[1] * 3, QImage.Format_RGB888)
grid_img = grid_img.scaled(self._cs_box[2], self._cs_box[3], Qt.KeepAspectRatio)
-
painter.drawPixmap(*self._cs_box, QPixmap.fromImage(grid_img))
-
- # draw fixed grid.
+ painter.setPen(QPen(QColor(*self._args.wheel_ed_color), self._args.wheel_ed_wid))
+ painter.setBrush(Qt.NoBrush)
+ painter.drawRect(*self._cs_box)
if self._args.sys_grid_list[0]:
if 0 <= self._last_selecting_idx < self._args.sys_grid_values["col"] ** 2:
sel_wid = 1.0 / self._args.sys_grid_values["col"] * self._cs_wid
sel_box = ((self._last_selecting_idx % self._args.sys_grid_values["col"]) * sel_wid + self._cs_box[0], (self._last_selecting_idx // self._args.sys_grid_values["col"]) * sel_wid + self._cs_box[1], sel_wid, sel_wid)
-
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawRect(*sel_box)
-
self._last_tool_tip_label.setGeometry(*sel_box)
self._last_tool_tip_label.setToolTip(self.get_box_name(self._last_selecting_idx))
self._last_tool_tip_label.show()
-
else:
self._last_tool_tip_label.hide()
-
if 0 <= self._selecting_idx < self._args.sys_grid_values["col"] ** 2:
sel_wid = 1.0 / self._args.sys_grid_values["col"] * self._cs_wid
sel_box = ((self._selecting_idx % self._args.sys_grid_values["col"]) * sel_wid + self._cs_box[0], (self._selecting_idx // self._args.sys_grid_values["col"]) * sel_wid + self._cs_box[1], sel_wid, sel_wid)
-
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawRect(*sel_box)
-
if self._args.sys_link_colors[0]:
link_square_left, link_square_right, link_wid, link_line_start, link_line_end = get_link_tag(sel_box)
-
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawRoundedRect(*link_square_left, link_wid, link_wid)
painter.drawRoundedRect(*link_square_right, link_wid, link_wid)
painter.drawLine(QPoint(*link_line_start), QPoint(*link_line_end))
-
self._tool_tip_label.setGeometry(*sel_box)
self._tool_tip_label.setToolTip(self.get_box_name(self._selecting_idx))
self._tool_tip_label.show()
-
else:
self._tool_tip_label.hide()
-
- # draw main points and assistant points.
else:
for idx in idx_seq:
pt_xy = np.array((self._args.sys_grid_locations[idx][0] * self._cs_wid + self._cs_box[0], self._args.sys_grid_locations[idx][1] * self._cs_wid + self._cs_box[1]), dtype=int)
pt_rgb = self._args.sys_color_set[idx].rgb
-
self._tag_centers[idx] = pt_xy
self._assit_tag_centers[idx] = [None,] * len(self._args.sys_grid_assitlocs[idx])
-
- # assit sequence. this code is reused in four places.
assit_idx_seq = list(range(len(self._args.sys_grid_assitlocs[idx])))
if idx == self._args.sys_activated_idx and self._args.sys_activated_assit_idx >= 0:
assit_idx_seq = assit_idx_seq[self._args.sys_activated_assit_idx + 1: ] + assit_idx_seq[: self._args.sys_activated_assit_idx + 1]
-
- # assistant points.
for assit_idx in assit_idx_seq:
assit_pt = (pt_xy + np.array(self._args.sys_grid_assitlocs[idx][assit_idx][0:2]) * self._cs_wid).astype(int)
assit_box = get_outer_box(assit_pt, self._args.circle_dist)
assit_frame_color = (255, 255, 255)
-
self._assit_tag_centers[idx][assit_idx] = assit_pt
-
if self._show_points:
if idx == self._args.sys_activated_idx and assit_idx == self._args.sys_activated_assit_idx:
assit_frame_color = self._args.positive_color
-
else:
assit_frame_color = self._args.negative_color
-
painter.setPen(QPen(QColor(*assit_frame_color), self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
painter.drawLine(QPoint(*pt_xy), QPoint(*assit_pt))
-
painter.setPen(QPen(QColor(*assit_frame_color), self._args.negative_wid))
-
assit_color = gen_assit_color(self._args.sys_color_set[idx], *self._args.sys_grid_assitlocs[idx][assit_idx][2:6])
assit_color = assit_color.rgb
-
if self._show_points:
painter.setBrush(QColor(*assit_color))
-
else:
painter.setBrush(QBrush(Qt.NoBrush))
-
painter.drawEllipse(*assit_box)
-
- # relative (move-able) or ref (un-move-able) point tag. assit dot box.
if not self._args.sys_grid_assitlocs[idx][assit_idx][5]:
dot_box = get_outer_box(assit_pt, self._args.negative_wid * 2 / 3)
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QBrush(QColor(*assit_frame_color)))
painter.drawEllipse(*dot_box)
-
- # main points.
pt_box = get_outer_box(pt_xy, self._args.dep_circle_dist_wid)
-
if self._show_points:
if idx == self._args.sys_activated_idx:
painter.setPen(QPen(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2]), self._args.positive_wid))
painter.setBrush(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2], 128))
-
else:
painter.setPen(QPen(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2], 128), self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
painter.setBrush(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2], 64))
-
else:
painter.setPen(QPen(Qt.white, self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
painter.setBrush(QBrush(Qt.NoBrush))
-
painter.drawEllipse(*pt_box)
-
pt_box = get_outer_box(pt_xy, self._args.circle_dist)
-
if self._show_points:
if idx == self._args.sys_activated_idx:
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
-
else:
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid))
-
painter.setBrush(QColor(*pt_rgb))
-
else:
painter.setPen(QPen(Qt.black, self._args.negative_wid))
painter.setBrush(QBrush(Qt.NoBrush))
-
painter.drawEllipse(*pt_box)
-
- # outer circles.
if self._outer_circles:
frame_color = self._args.negative_color
-
if self._outer_circles[0] == self._args.sys_activated_idx and (self._outer_circles[1] == self._args.sys_activated_assit_idx or self._outer_circles[1] == -1):
frame_color = self._args.positive_color
-
- # circle 0.
if self._outer_circles[5] == 0:
painter.setPen(QPen(QColor(*frame_color, ), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][0]
painter.drawEllipse(*outer_circle[0])
-
for line in outer_circle[1:]:
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
if len(self._outer_circles[4]) > 2:
- # circle 1.
if self._outer_circles[5] == 1:
painter.setPen(QPen(QColor(*frame_color, ), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][1]
painter.drawEllipse(*outer_circle[0])
-
for line in outer_circle[1:]:
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
- # circle 2.
if self._outer_circles[5] == 2:
painter.setPen(QPen(QColor(*frame_color, ), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][2]
painter.drawEllipse(*outer_circle[0])
-
- # relative (move-able) or ref (un-move-able) point tag. assit dot box.
if self._outer_circles[1] < len(self._args.sys_grid_assitlocs[self._outer_circles[0]]) and self._args.sys_grid_assitlocs[self._outer_circles[0]][self._outer_circles[1]][5]:
line = outer_circle[1]
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
poly = QPolygon([QPoint(*i) for i in outer_circle[2]])
painter.drawPolygon(poly)
-
painter.end()
-
if self._args.sys_grid_list[0]:
self.ps_status_changed.emit((0, self._args.sys_grid_values["col"], self._args.sys_grid_values["col"], len(self._args.sys_grid_list[0]), self._selecting_idx))
-
elif self._show_points:
self.ps_status_changed.emit((1, len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx])))
-
else:
self.ps_status_changed.emit((2,))
- # ---------- ---------- ---------- Mouse Event Funcs ---------- ---------- ---------- #
-
def keyPressEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
if event.key() == Qt.Key_Shift:
self._press_key = 1
self.setCursor(QCursor(Qt.PointingHandCursor))
event.accept()
-
elif event.key() == Qt.Key_Control:
self._press_key = 2
self.setCursor(QCursor(Qt.PointingHandCursor))
event.accept()
-
elif event.key() == Qt.Key_Alt:
self._press_key = 4
-
if self._args.sys_grid_list[0]:
self.setCursor(QCursor(Qt.PointingHandCursor))
-
else:
self.setCursor(QCursor(Qt.ArrowCursor))
-
event.accept()
-
else:
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
@@ -632,7 +406,6 @@ def keyReleaseEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
event.ignore()
@@ -640,68 +413,47 @@ def keyReleaseEvent(self, event):
def mouseDoubleClickEvent(self, event):
if event.button() == Qt.LeftButton:
point = (event.x(), event.y())
-
if self._args.sys_grid_list[0]:
if point[0] < self._cs_box[0] or point[0] > self._cs_box[0] + self._cs_box[2] or point[1] < self._cs_box[1] or point[1] > self._cs_box[1] + self._cs_box[3]:
event.ignore()
-
else:
sel_wid = 1.0 / self._args.sys_grid_values["col"] * self._cs_wid
press_idx = int((point[1] - self._cs_box[1]) / sel_wid) * self._args.sys_grid_values["col"] + int((point[0] - self._cs_box[0]) / sel_wid)
-
if press_idx != self._selecting_idx:
self._last_selecting_idx = self._selecting_idx
self._selecting_idx = press_idx
-
self.update_select_idx()
-
self.insert_point()
-
event.accept()
-
# self.update()
# is completed by self.insert_point()
-
elif self._show_points and self._args.sys_activated_assit_idx >= 0:
pt_xy = np.array((self._args.sys_grid_locations[self._args.sys_activated_idx][0] * self._cs_wid + self._cs_box[0], self._args.sys_grid_locations[self._args.sys_activated_idx][1] * self._cs_wid + self._cs_box[1]), dtype=int)
assit_pt = (pt_xy + np.array(self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][0:2]) * self._cs_wid).astype(int)
-
if np.sum((point - assit_pt) ** 2) < self._args.dep_circle_dist_2:
self.ps_assit_pt_changed.emit(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5])
self.ps_color_changed.emit(True)
event.accept()
-
else:
event.ignore()
-
self.update()
-
else:
event.ignore()
-
else:
event.ignore()
def mousePressEvent(self, event):
point = np.array((event.x(), event.y()))
info_pt_pressed = False
-
if self._press_key == 0 and self._outer_circles and self._outer_circles[5] > -1 and event.button() == Qt.LeftButton:
info_pt_pressed = True
-
if self._press_key == 1 and event.button() == Qt.LeftButton:
- #
- # Sync to wheel.py.
- # May exist difference.
color_dict = {"version": self._args.info_version_en, "site": self._args.info_main_site, "type": "set"}
color_dict["palettes"] = export_list([(self._args.sys_color_set, self._args.hm_rule, "", "", (time.time(), time.time()), self._args.sys_grid_locations, self._args.sys_grid_assitlocs, self._args.sys_grid_list, self._args.sys_grid_values),])
color_path = os.sep.join((self._args.global_temp_dir.path(), "Rickrack_Set_{}.dps".format(abs(hash(str(color_dict))))))
-
with open(color_path, "w", encoding="utf-8") as f:
json.dump(color_dict, f, indent=4, ensure_ascii=False)
-
self._drag_file = True
-
drag = QDrag(self)
mimedata = QMimeData()
mimedata.setUrls([QUrl.fromLocalFile(color_path)])
@@ -710,43 +462,27 @@ def mousePressEvent(self, event):
drag.setPixmap(pixmap)
drag.setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2))
drag.exec_(Qt.CopyAction | Qt.MoveAction)
-
self._drag_file = False
self.setCursor(QCursor(Qt.ArrowCursor))
-
event.accept()
-
elif info_pt_pressed or (self._press_key == 2 and event.button() == Qt.LeftButton):
if (not self._args.sys_grid_list[0]) and self._show_points:
insert_assit_pt_by_info_tag = False
-
if info_pt_pressed:
sel_idx, sel_assit_idx, is_in_pt, is_in_assit_pt, circle_locations, sel_info_idx = self._outer_circles
-
self._args.sys_activated_idx = sel_idx
self._args.sys_activated_assit_idx = sel_assit_idx
-
self.ps_index_changed.emit(True)
-
- # add a ref color.
if is_in_pt or (is_in_assit_pt and sel_info_idx == 0):
insert_assit_pt_by_info_tag = True
-
- # del the ref color.
elif is_in_assit_pt and sel_info_idx == 1:
self._outer_circles = None
self.delete_point()
-
- # fix or unfix the ref color.
else:
self.ps_assit_pt_changed.emit(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5])
-
else:
insert_assit_pt_by_info_tag = True
-
- # max assit len 30.
assit_len = len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx])
-
if insert_assit_pt_by_info_tag and assit_len < 31:
loc = [(point[0] - self._cs_box[0]) / self._cs_wid - self._args.sys_grid_locations[self._args.sys_activated_idx][0], (point[1] - self._cs_box[1]) / self._cs_wid - self._args.sys_grid_locations[self._args.sys_activated_idx][1]]
loc = snap_point(loc, 0.5 / self._args.sys_grid_values["col"])
@@ -754,124 +490,88 @@ def mousePressEvent(self, event):
loc[0] = 1.0 if loc[0] > 1.0 else loc[0]
loc[1] = -1.0 if loc[1] < -1.0 else loc[1]
loc[1] = 1.0 if loc[1] > 1.0 else loc[1]
-
self._args.sys_activated_assit_idx = assit_len
self._args.sys_grid_assitlocs[self._args.sys_activated_idx].append([loc[0], loc[1], 15, 0.0, 0.0, True])
self._args.sys_assit_color_locs[self._args.sys_activated_idx].append(None)
-
self._moving_assitp = True
-
self.ps_value_changed.emit(True)
-
# not use self.insert_point()
-
event.accept()
self.update()
-
elif self._args.sys_grid_list[0] and self._cs_box[0] < point[0] < self._cs_box[0] + self._cs_box[2] and self._cs_box[1] < point[1] < self._cs_box[1] + self._cs_box[3]:
sel_wid = 1.0 / self._args.sys_grid_values["col"] * self._cs_wid
press_idx = int((point[1] - self._cs_box[1]) / sel_wid) * self._args.sys_grid_values["col"] + int((point[0] - self._cs_box[0]) / sel_wid)
-
if press_idx != self._selecting_idx:
self._last_selecting_idx = self._selecting_idx
self._selecting_idx = press_idx
-
self.update_select_idx()
-
event.accept()
self.update()
-
elif self._show_points:
already_accept_main = False
already_accept_assi = False
-
for idx in range(5):
if np.sum((point - np.array((self._cs_box[0], self._cs_box[1])) - np.array(self._args.sys_grid_locations[idx]) * self._cs_wid) ** 2) < self._args.dep_circle_dist_wid_2:
self._args.sys_activated_idx = idx
self._args.sys_activated_assit_idx = -1
-
self.ps_index_changed.emit(True)
already_accept_main = True
-
else:
for assit_idx in range(len(self._args.sys_grid_assitlocs[idx]))[::-1]:
if np.sum((point - np.array((self._cs_box[0], self._cs_box[1])) - (np.array(self._args.sys_grid_locations[idx]) + np.array(self._args.sys_grid_assitlocs[idx][assit_idx][0:2])) * self._cs_wid) ** 2) < self._args.dep_circle_dist_2:
self._args.sys_activated_idx = idx
self._args.sys_activated_assit_idx = assit_idx
-
self.ps_index_changed.emit(True)
already_accept_assi = True
-
break
-
if already_accept_main or already_accept_assi:
break
-
if event.button() == Qt.LeftButton:
- # main points.
if (self._args.press_move and not self._last_moving and not already_accept_assi and self._cs_box[0] < point[0] < self._cs_box[0] + self._cs_box[2] and self._cs_box[1] < point[1] < self._cs_box[1] + self._cs_box[3]) or already_accept_main:
self._moving_maintp = True
self._last_moving = 0
-
event.accept()
self.update()
-
- # assit points.
elif self._args.sys_grid_assitlocs[self._args.sys_activated_idx] and (self._args.press_move and self._last_moving and not already_accept_main and self._cs_box[0] < point[0] < self._cs_box[0] + self._cs_box[2] and self._cs_box[1] < point[1] < self._cs_box[1] + self._cs_box[3]) or already_accept_assi:
self._moving_assitp = True
self._last_moving = 1
-
event.accept()
self.update()
-
else:
event.ignore()
-
else:
event.ignore()
-
else:
event.ignore()
def mouseMoveEvent(self, event):
if not self._show_points:
return
-
point = np.array((event.x(), event.y()))
-
if self._moving_assitp:
self._outer_circles = None
-
loc = [(point[0] - self._cs_box[0]) / self._cs_wid - self._args.sys_grid_locations[self._args.sys_activated_idx][0], (point[1] - self._cs_box[1]) / self._cs_wid - self._args.sys_grid_locations[self._args.sys_activated_idx][1]]
loc = snap_point(loc, 0.5 / self._args.sys_grid_values["col"])
loc[0] = -1.0 if loc[0] < -1.0 else loc[0]
loc[0] = 1.0 if loc[0] > 1.0 else loc[0]
loc[1] = -1.0 if loc[1] < -1.0 else loc[1]
loc[1] = 1.0 if loc[1] > 1.0 else loc[1]
-
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][0] = loc[0]
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][1] = loc[1]
-
event.accept()
self.update()
-
elif self._moving_maintp:
self._outer_circles = None
-
loc = [(point[0] - self._cs_box[0]) / self._cs_wid, (point[1] - self._cs_box[1]) / self._cs_wid]
loc = snap_point(loc, 0.5 / self._args.sys_grid_values["col"])
loc[0] = 0.0 if loc[0] < 0.0 else loc[0]
loc[0] = 1.0 if loc[0] > 1.0 else loc[0]
loc[1] = 0.0 if loc[1] < 0.0 else loc[1]
loc[1] = 1.0 if loc[1] > 1.0 else loc[1]
-
self._args.sys_grid_locations[self._args.sys_activated_idx] = tuple(loc)
-
event.accept()
self.update()
-
else:
- # outer circles.
if self._args.show_info_pts[2] and self._press_key == 0 and (not self._drop_file) and (not self._args.sys_grid_list[0]): # and (self._cs_box[0] < point[0] < self._cs_box[0] + self._cs_box[2] and self._cs_box[1] < point[1] < self._cs_box[1] + self._cs_box[3]):
pts = self._tag_centers
major = self._args.show_info_pts[2] in (1, 3)
@@ -879,721 +579,436 @@ def mouseMoveEvent(self, event):
minor = self._args.show_info_pts[2] > 1
last_count = bool(self._outer_circles)
self._outer_circles = get_outer_circles(point, self._args.sys_activated_idx, pts, assit_pts, (self._args.dep_circle_dist_wid) * 1.2, self._args.circle_dist * 1.2, self._args.circle_dist, self._outer_circles, major=major, minor=minor)
-
if self._outer_circles or last_count:
self.update()
-
else:
self._outer_circles = None
-
event.ignore()
def mouseReleaseEvent(self, event):
self._moving_maintp = False
self._moving_assitp = False
-
if event.button() == Qt.LeftButton:
self.ps_history_backup.emit(True)
-
event.ignore()
def dragEnterEvent(self, event):
- """
- Sync to wheel.py. May exist difference.
- """
-
if self._outer_circles:
self._outer_circles = None
self.update()
-
- # drag file out from depot.
if self._drag_file:
event.ignore()
return
-
try:
set_file = event.mimeData().urls()[0].toLocalFile()
-
except Exception as err:
event.ignore()
return
-
if set_file.split(".")[-1].lower() in ("dps", "json", "txt", "aco", "ase", "gpl", "xml"):
self._drop_file = set_file
event.accept()
-
else:
event.ignore()
def dropEvent(self, event):
- """
- Sync to wheel.py. May exist difference.
- """
-
if self._outer_circles:
self._outer_circles = None
self.update()
-
if self._drop_file:
self.ps_dropped.emit((self._drop_file, False))
self._drop_file = None
-
event.accept()
-
else:
event.ignore()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
+ def init_key(self):
+ self._press_key = 0
+ self._drag_file = False
+ self._drop_file = None
def home(self):
- """
- Home points.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0]:
self._selecting_idx = 0
self._last_selecting_idx = 0
-
self.update()
-
else:
self.reset_locations()
-
# self.update()
- # is completed by self.reset_locations().
def move(self, shift_x, shift_y):
- """
- Move points.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0]:
next_idx = self._selecting_idx
-
if shift_x < 0.0:
next_idx = next_idx - 1
-
elif shift_x > 0.0:
next_idx = next_idx + 1
-
if shift_y < 0.0:
next_idx = next_idx - self._args.sys_grid_values["col"]
-
elif shift_y > 0.0:
next_idx = next_idx + self._args.sys_grid_values["col"]
-
if next_idx != self._selecting_idx:
self._last_selecting_idx = self._selecting_idx
self._selecting_idx = next_idx
-
self.update_select_idx()
-
else:
if self._last_moving:
loc = list(self._args.sys_grid_assitlocs[self._args.sys_activated_idx][0])
-
if shift_x < 0.0:
loc[0] = loc[0] - 0.5 / self._args.sys_grid_values["col"]
-
elif shift_x > 0.0:
loc[0] = loc[0] + 0.5 / self._args.sys_grid_values["col"]
-
if shift_y < 0.0:
loc[1] = loc[1] - 0.5 / self._args.sys_grid_values["col"]
-
elif shift_y > 0.0:
loc[1] = loc[1] + 0.5 / self._args.sys_grid_values["col"]
-
loc[0] = -1.0 if loc[0] < -1.0 else loc[0]
loc[0] = 1.0 if loc[0] > 1.0 else loc[0]
loc[1] = -1.0 if loc[1] < -1.0 else loc[1]
loc[1] = 1.0 if loc[1] > 1.0 else loc[1]
-
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][0][0] = loc[0]
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][0][1] = loc[1]
-
else:
loc = list(self._args.sys_grid_locations[self._args.sys_activated_idx])
-
if shift_x < 0.0:
loc[0] = loc[0] - 0.5 / self._args.sys_grid_values["col"]
-
elif shift_x > 0.0:
loc[0] = loc[0] + 0.5 / self._args.sys_grid_values["col"]
-
if shift_y < 0.0:
loc[1] = loc[1] - 0.5 / self._args.sys_grid_values["col"]
-
elif shift_y > 0.0:
loc[1] = loc[1] + 0.5 / self._args.sys_grid_values["col"]
-
loc[0] = loc[0] % 1.0
loc[1] = loc[1] % 1.0
-
self._args.sys_grid_locations[self._args.sys_activated_idx] = tuple(loc)
-
self.update()
def zoom(self, ratio):
- """
- Zoom points.
- """
-
if not self.isVisible():
return
-
if True: # self._args.rev_direct:
if ratio > 1 and self._args.sys_grid_values["col"] >= 2:
self._args.sys_grid_values["col"] = int(self._args.sys_grid_values["col"] - 1)
-
elif ratio < 1 and self._args.sys_grid_values["col"] <= 50:
self._args.sys_grid_values["col"] = int(self._args.sys_grid_values["col"] + 1)
-
else:
if ratio > 1 and self._args.sys_grid_values["col"] <= 50:
self._args.sys_grid_values["col"] = int(self._args.sys_grid_values["col"] + 1)
-
elif ratio < 1 and self._args.sys_grid_values["col"] >= 2:
self._args.sys_grid_values["col"] = int(self._args.sys_grid_values["col"] - 1)
-
self.ps_value_changed.emit(True)
self.ps_history_backup.emit(True)
-
self.update()
def update_select_idx(self):
- """
- Verify and update select_idx and last_select_idx.
- """
-
- # the verifing of grid_list length and others should be completed by upper level functions.
-
max_gidx = min(len(self._args.sys_grid_list[0]), self._args.sys_grid_values["col"] ** 2 - 1)
-
self._selecting_idx = 0 if self._selecting_idx < 0 else self._selecting_idx
self._selecting_idx = max_gidx if self._selecting_idx > max_gidx else self._selecting_idx
-
max_gidx = min(len(self._args.sys_grid_list[0]) - 1, self._args.sys_grid_values["col"] ** 2 - 1)
-
self._last_selecting_idx = 0 if self._last_selecting_idx < 0 else self._last_selecting_idx
self._last_selecting_idx = max_gidx if self._last_selecting_idx > max_gidx else self._last_selecting_idx
-
# set_context into info window, thus can change the info dynamically. (recovered)
- # similar to clone_cell in activate_idx in depot.py.
self._color_box.set_context(self._selecting_idx)
self.ps_history_backup.emit(True)
def show_or_hide_points(self):
- """
- Show or hide main and assistant points.
- """
-
if not self.isVisible():
return
-
if not self._args.sys_grid_list[0]:
self._show_points = not self._show_points
-
self.update()
def clear_or_gen_grid_list(self):
- """
- Dynamic board <-> Grid list according to the dynamic board.
- """
-
if not self.isVisible():
return
-
if self._color_box.isVisible():
return
-
- # unlink colors.
self._args.sys_link_colors[0] = False
self.ps_linked.emit(True)
-
- # clean or gen.
if self._args.sys_grid_list[0]:
self._show_points = True
self._args.sys_grid_list = [[], []]
-
else:
self._show_points = False
-
grid_list = [[], ["",] * self._args.sys_grid_values["col"] ** 2]
-
color_grid = self._color_grid.tolist()
-
for i in range(len(color_grid)):
for j in range(len(color_grid[i])):
grid_list[0].append(Color.rgb2hec(color_grid[i][j]))
-
self._args.sys_grid_list = grid_list
-
self._selecting_idx = -1
self._last_selecting_idx = -1
self.ps_history_backup.emit(True)
-
self.update()
def clear_or_gen_assit_color_list(self):
- """
- Dynamic board <-> Assit color list.
- """
-
if not self.isVisible():
return
-
if self._color_box.isVisible():
return
-
- # unlink colors.
self._args.sys_link_colors[0] = False
self.ps_linked.emit(True)
-
- # clean or gen.
if self._args.sys_grid_list[0]:
self._show_points = True
self._args.sys_grid_list = [[], []]
-
else:
self._show_points = False
-
grid_list = [[], []]
-
- # generate full colors. this code is reused.
- for idx in (2, 1, 0, 3, 4):
- grid_list[0].append(self._args.sys_color_set[idx].hec)
- grid_list[1].append(self._color_descs[0] + " {}".format(idx))
-
- grid_list[0].append("FFFFFF")
- grid_list[1].append("")
-
+ assit_grid_list = [[], []]
for idx in (2, 1, 0, 3, 4):
grid_list[0].append(self._args.sys_color_set[idx].hec)
- grid_list[1].append(self._color_descs[0] + " {}".format(idx))
-
+ assit_grid_list[0].append(self._args.sys_color_set[idx].hec)
+ color_sign = Color.sign(self._args.sys_color_set[idx].hsv)
+ color_sign = self._color_descs[color_sign[0] + 2] + self._color_descs[color_sign[1] + 12]
+ grid_list[1].append(self._color_descs[0].format(idx, color_sign))
+ assit_grid_list[1].append(self._color_descs[0].format(idx, color_sign))
for assit_idx in range(len(self._args.sys_grid_assitlocs[idx])):
assit_color = gen_assit_color(self._args.sys_color_set[idx], *self._args.sys_grid_assitlocs[idx][assit_idx][2:6])
-
- grid_list[0].append(assit_color.hec)
- grid_list[1].append(self._color_descs[1] + " {}-{}".format(idx, assit_idx))
-
- self._args.sys_grid_list = grid_list
-
+ assit_grid_list[0].append(assit_color.hec)
+ color_sign = Color.sign(assit_color.hsv)
+ color_sign = self._color_descs[color_sign[0] + 2] + self._color_descs[color_sign[1] + 12]
+ assit_grid_list[1].append(self._color_descs[1].format("{}-{}".format(idx, assit_idx), color_sign))
+ self._args.sys_grid_list = [grid_list[0] + ["FFFFFF", ] + assit_grid_list[0], grid_list[1] + ["", ] + assit_grid_list[1]]
self._selecting_idx = -1
self._last_selecting_idx = -1
self.ps_history_backup.emit(True)
-
self.update()
def get_box_name(self, idx):
- """
- Get the name of color box at idx in fixed view.
- """
-
if idx < 0 or idx > min(len(self._args.sys_grid_list[0]) - 1, self._args.sys_grid_values["col"] ** 2 - 1):
return ""
-
name = self._args.sys_grid_list[1][idx]
-
if not name:
name = self._tip_descs[0]
-
return name
def act_append_color_box(self):
- """
- Append a color box at end.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0]:
self._args.sys_grid_list[0].append(self._args.sys_color_set[self._args.sys_activated_idx].hec)
self._args.sys_grid_list[1].append("")
-
self.update_select_idx()
def act_append_beside_color_box(self):
- """
- Append a color box beside.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0] and self._selecting_idx < len(self._args.sys_grid_list[0]):
self._args.sys_grid_list[0] = self._args.sys_grid_list[0][:self._selecting_idx] + [self._args.sys_color_set[self._args.sys_activated_idx].hec,] + self._args.sys_grid_list[0][self._selecting_idx:]
self._args.sys_grid_list[1] = self._args.sys_grid_list[1][:self._selecting_idx] + ["",] + self._args.sys_grid_list[1][self._selecting_idx:]
-
self.update_select_idx()
def act_rev_insert_color_box(self):
- """
- Insert the result color into a color box.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0] and self._selecting_idx < len(self._args.sys_grid_list[0]):
self._args.sys_grid_list[0][self._selecting_idx] = self._args.sys_color_set[self._args.sys_activated_idx].hec
-
self.update_select_idx()
def act_insert_color_box(self):
- """
- Insert the color in a color box into the result.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0] and self._selecting_idx < len(self._args.sys_grid_list[0]):
color = Color(self._args.sys_grid_list[0][self._selecting_idx], tp="hec", overflow=self._args.sys_color_set.get_overflow())
self._args.sys_color_set.modify(self._args.hm_rule, self._args.sys_activated_idx, color)
-
self.ps_color_changed.emit(True)
-
self.update_select_idx()
def link_point(self, link):
- """
- Link point with result.
-
- Args:
- link (bool): whether linked.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0] and self._selecting_idx < len(self._args.sys_grid_list[0]):
self._args.sys_link_colors[0] = bool(link)
self.ps_linked.emit(True)
def insert_point(self, insert_pt_beside=False):
- """
- Insert a point into assistant list (dynamic view) or grid list (fixed view) without updating color type and value.
-
- Args:
- insert_pt_beside (bool): whether append a color beside the selected color box.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0]:
if self._selecting_idx < self._args.sys_grid_values["col"] ** 2:
if self._selecting_idx >= len(self._args.sys_grid_list[0]):
self.act_append_color_box()
-
else:
if self._press_key in (2, 4):
self.act_rev_insert_color_box()
-
elif self._press_key == 1 or insert_pt_beside:
self.act_append_beside_color_box()
-
else:
self.act_insert_color_box()
-
- # link and unlink.
if self._press_key == 2:
self.link_point(not self._args.sys_link_colors[0])
-
elif self._args.sys_link_colors[0]:
self.link_point(False)
-
else:
- # max assit len 30.
assit_len = len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx])
-
if assit_len < 31:
- # similar to func "insert_assit_point" in wheel.py.
- #
loc_a, loc_b = 0.1, 0.1
-
self._args.sys_activated_assit_idx = assit_len
self._args.sys_grid_assitlocs[self._args.sys_activated_idx].append([loc_a, loc_b, (15 * np.random.random() + 15) * np.random.choice([1,-1]), 0.3 * np.random.random() - 0.15, 0.0, True])
self._args.sys_assit_color_locs[self._args.sys_activated_idx].append(None)
-
self.ps_color_changed.emit(True)
-
self.update()
def switch_point(self):
- """
- Switch selected point (self._selecting_idx) with last selected point.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0] and 0 <= self._selecting_idx < len(self._args.sys_grid_list[0]) and 0 <= self._last_selecting_idx < len(self._args.sys_grid_list[0]) and self._selecting_idx != self._last_selecting_idx:
self._args.sys_grid_list[0][self._selecting_idx], self._args.sys_grid_list[0][self._last_selecting_idx] = self._args.sys_grid_list[0][self._last_selecting_idx], self._args.sys_grid_list[0][self._selecting_idx]
self._args.sys_grid_list[1][self._selecting_idx], self._args.sys_grid_list[1][self._last_selecting_idx] = self._args.sys_grid_list[1][self._last_selecting_idx], self._args.sys_grid_list[1][self._selecting_idx]
-
self.update_select_idx()
self.update()
def delete_point(self, direct_delete=False):
- """
- Delete current point from assistant list (dynamic view) or grid list (fixed view) without updating color type and value.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0]:
if len(self._args.sys_grid_list[0]) == 1 and self._args.sys_grid_list[0][0] == "FFFFFF":
return
-
if 0 <= self._selecting_idx < min(self._args.sys_grid_values["col"] ** 2, len(self._args.sys_grid_list[0])):
if self._args.sys_grid_list[0][self._selecting_idx] == "FFFFFF" or direct_delete:
self._args.sys_grid_list[0].pop(self._selecting_idx)
self._args.sys_grid_list[1].pop(self._selecting_idx)
-
else:
self._args.sys_grid_list[0][self._selecting_idx] = "FFFFFF"
self._args.sys_grid_list[1][self._selecting_idx] = ""
-
self.update_select_idx()
-
else:
if len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]) > self._args.sys_activated_assit_idx >= 0:
if self._args.sys_activated_assit_idx == 0:
self._args.sys_grid_assitlocs[self._args.sys_activated_idx] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][1:]
self._args.sys_assit_color_locs[self._args.sys_activated_idx] = self._args.sys_assit_color_locs[self._args.sys_activated_idx][1:]
-
else:
self._args.sys_grid_assitlocs[self._args.sys_activated_idx] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][:self._args.sys_activated_assit_idx] + self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx + 1:]
self._args.sys_assit_color_locs[self._args.sys_activated_idx] = self._args.sys_assit_color_locs[self._args.sys_activated_idx][:self._args.sys_activated_assit_idx] + self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx + 1:]
-
self._args.sys_activated_assit_idx = -1
-
self.ps_color_changed.emit(True)
-
self.update()
def confirm_delete_point(self):
- """
- Act delete_point with confirmation.
- """
-
if not self.isVisible():
return
-
if self._args.sys_grid_list[0]:
self.prompt(self._operation_warns[3], lambda: self.delete_point(direct_delete=True))
-
else:
self.prompt(self._operation_warns[4], self.delete_point)
def detail_point(self):
- """
- Show info of color box at current idx.
- """
-
if not self.isVisible():
return
-
if self._selecting_idx < 0 or self._selecting_idx > len(self._args.sys_grid_list[0]) - 1:
return
-
# self.update_select_idx()
-
# self._color_box.set_context is completed by self.update_select_idx above. (recovered)
# self._color_box.set_context(self._selecting_idx)
-
if self._args.sys_grid_list[0]:
self._color_box.show()
def hide_detail(self):
- """
- Hide the info window.
- Esc refer to close self._color_box if it is visible (return True) in main window.
- """
-
if self._color_box.isVisible():
self._color_box.hide()
-
return True
-
else:
return False
def update_index(self):
- """
- The color type and value of current point will be changed when color set index is changed. For self._wget_cube_table.ps_value_changed in main.py.
- Opposite function to update_assitp (deleted because of fake_current_assitp).
- Link colors with cube table here.
- """
-
- # similar code segment in method self.insert_point with self._press_key == 2.
if self._args.sys_link_colors[0] and self._args.sys_grid_list[0] and self._selecting_idx < len(self._args.sys_grid_list[0]):
self._args.sys_grid_list[0][self._selecting_idx] = self._args.sys_color_set[self._args.sys_activated_idx].hec
-
self.update_select_idx()
-
self.ps_value_changed.emit(True)
-
self.update()
def reset_locations(self):
- """
- Reset point loctions to default values.
- """
-
if self._color_box.isVisible():
return
-
if self._args.sys_grid_list[0]:
self._show_points = True
self._args.sys_grid_list = [[], []]
-
self._args.sys_grid_locations, _ = norm_grid_locations([], [])
self._args.sys_activated_assit_idx = -1
-
self._args.sys_assit_color_locs = [[None for j in self._args.sys_grid_assitlocs[i]] for i in range(5)]
-
- # reset center.
for idx in range(5):
assit_len = len(self._args.sys_grid_assitlocs[idx])
-
for assit_idx in range(assit_len):
self._args.sys_grid_assitlocs[idx][assit_idx][0:2] = rotate_point((0.2, 0), assit_idx / assit_len * 360)
-
self._args.sys_grid_values = norm_grid_values({})
-
self._selecting_idx = -1
self._last_selecting_idx = -1
-
self.ps_value_changed.emit(True)
self.ps_history_backup.emit(True)
self.update()
def freeze_image(self, value=None):
- """
- Freeze current image.
- """
-
if not self.isVisible():
return
-
grid_img = QImage(self._color_grid, self._color_grid.shape[1], self._color_grid.shape[0], self._color_grid.shape[1] * 3, QImage.Format_RGB888)
grid_img = grid_img.scaled(self._cs_box[2], self._cs_box[3], Qt.KeepAspectRatio)
grid_img = ImageQt.fromqimage(grid_img)
-
self.ps_transfer_image.emit(grid_img)
def save_image(self, value=None):
- """
- Exec save image.
- """
-
if not self.isVisible():
return
-
grid_img = QImage(self._color_grid, self._color_grid.shape[1], self._color_grid.shape[0], self._color_grid.shape[1] * 3, QImage.Format_RGB888)
grid_img = grid_img.scaled(self._cs_box[2], self._cs_box[3], Qt.KeepAspectRatio)
-
name = "{}".format(time.strftime("Rickrack_Image_%Y_%m_%d.png", time.localtime()))
-
cb_filter = "{} (*.png *.bmp *.jpg *.jpeg *.tif *.tiff *.webp);; {} (*.png);; {} (*.bmp);; {} (*.jpg *.jpeg);; {} (*.tif *.tiff);; {} (*.webp)".format(*self._extend_descs)
cb_file = QFileDialog.getSaveFileName(None, self._open_descs[2], os.sep.join((self._args.usr_image, name)), filter=cb_filter)
-
if cb_file[0]:
self._args.usr_image = os.path.dirname(os.path.abspath(cb_file[0]))
-
else:
- # closed without open a file.
return
-
grid_img.save(cb_file[0])
def clipboard_in(self):
- """
- Load set from clipboard. Sync to wheel.py. May exist difference.
- """
-
if not self.isVisible():
return
-
clipboard = QApplication.clipboard().mimeData()
-
if clipboard.hasUrls():
try:
set_file = clipboard.urls()[0].toLocalFile()
-
except Exception as err:
return
-
if set_file.split(".")[-1].lower() in ("dps", "json", "txt", "aco", "ase", "gpl", "xml") and os.path.isfile(set_file):
self.ps_dropped.emit((set_file, False))
self.ps_history_backup.emit(True)
-
else:
try:
color_dict = json.loads(clipboard.text(), encoding="utf-8")
-
except Exception as err:
return
-
if isinstance(color_dict, dict) and "type" in color_dict and "palettes" in color_dict:
if color_dict["type"] == "set":
self.ps_dropped.emit((color_dict, True))
self.ps_history_backup.emit(True)
def clipboard_img(self):
- """
- Set the board image as the clipboard data by Ctrl + c.
- """
-
if not (self.isVisible() and isinstance(self._color_grid, np.ndarray)):
return
-
grid_img = QImage(self._color_grid, self._color_grid.shape[1], self._color_grid.shape[0], self._color_grid.shape[1] * 3, QImage.Format_RGB888)
grid_img = grid_img.scaled(self._cs_box[2], self._cs_box[3], Qt.KeepAspectRatio)
-
mimedata = QMimeData()
mimedata.setImageData(QPixmap.fromImage(grid_img))
-
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
def clipboard_cur(self, ctp):
- """
- Set the rgb, hsv or hec (hex code) of current color box as the clipboard data by shortcut Ctrl + r, h or x.
- """
-
def _func_():
if self._args.sys_grid_list[0] and 0 <= self._selecting_idx < len(self._args.sys_grid_list[0]):
color = Color(self._args.sys_grid_list[0][self._selecting_idx], tp="hec").getti(ctp)
-
else:
color = self._args.sys_color_set[self._args.sys_activated_idx].getti(ctp)
-
if ctp == "hec":
color = self._args.hec_prefix[0] + str(color) + self._args.hec_prefix[1]
-
else:
color = self._args.rgb_prefix[1].join([self._args.r_prefix[0] + str(color[coi]) + self._args.r_prefix[1] for coi in range(3)])
color = self._args.rgb_prefix[0] + color + self._args.rgb_prefix[2]
-
mimedata = QMimeData()
mimedata.setText(color)
-
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
-
return _func_
def prompt(self, text, accept_action):
@@ -1601,160 +1016,90 @@ def prompt(self, text, accept_action):
box.setWindowTitle(self._operation_warns[0])
box.setText(text)
box.setIcon(QMessageBox.Warning)
-
box.addButton(self._operation_warns[1], QMessageBox.AcceptRole)
box.addButton(self._operation_warns[2], QMessageBox.RejectRole)
-
if box.exec_() == 0:
accept_action()
- # ---------- ---------- ---------- Menu ---------- ---------- ---------- #
-
def create_menu(self):
- """
- Create a right clicked menu.
-
- """
-
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.show_menu)
-
self._menu = QMenu(self)
-
- # _translate("Board", "Undo"), # 0
- # _translate("Board", "Redo"), # 1
self._action_undo = QAction(self)
self._action_undo.triggered.connect(lambda: self.ps_undo.emit(True))
self._menu.addAction(self._action_undo)
-
self._action_redo = QAction(self)
self._action_redo.triggered.connect(lambda: self.ps_undo.emit(False))
self._menu.addAction(self._action_redo)
-
- # _translate("Board", "Reset"), # 2
self._action_reset = QAction(self)
self._action_reset.triggered.connect(self.reset_locations)
self._menu.addAction(self._action_reset)
-
- # _translate("Board", "Paste"), # 7
self._action_paste = QAction(self)
self._action_paste.triggered.connect(self.clipboard_in)
self._menu.addAction(self._action_paste)
-
- # _translate("Board", "Copy RGB"), # 3
- # _translate("Board", "Copy HSV"), # 4
- # _translate("Board", "Copy Hex Code"), # 5
self._action_copy_rgb = QAction(self)
self._action_copy_rgb.triggered.connect(self.clipboard_cur("rgb"))
self._menu.addAction(self._action_copy_rgb)
-
self._action_copy_hsv = QAction(self)
self._action_copy_hsv.triggered.connect(self.clipboard_cur("hsv"))
self._menu.addAction(self._action_copy_hsv)
-
self._action_copy_hec = QAction(self)
self._action_copy_hec.triggered.connect(self.clipboard_cur("hec"))
self._menu.addAction(self._action_copy_hec)
-
- # _translate("Board", "Copy as Image"), # 6
self._action_copy_img = QAction(self)
self._action_copy_img.triggered.connect(self.clipboard_img)
self._menu.addAction(self._action_copy_img)
-
- # _translate("Board", "Freeze Image"), # 28
- # _translate("Board", "Save Image"), # 29
self._action_freeze_img = QAction(self)
self._action_freeze_img.triggered.connect(self.freeze_image)
self._menu.addAction(self._action_freeze_img)
-
self._action_save_img = QAction(self)
self._action_save_img.triggered.connect(self.save_image)
self._menu.addAction(self._action_save_img)
-
- # _translate("Board", "Zoom In"), # 8
- # _translate("Board", "Zoom Out"), # 9
self._action_zoom_in = QAction(self)
self._action_zoom_in.triggered.connect(lambda: self.zoom(self._args.zoom_step))
self._menu.addAction(self._action_zoom_in)
-
self._action_zoom_out = QAction(self)
self._action_zoom_out.triggered.connect(lambda: self.zoom(1 / self._args.zoom_step))
self._menu.addAction(self._action_zoom_out)
-
- # _translate("Board", "Insert Ref Point (Ctrl+MV)"), # 10
- # _translate("Board", "Replace Color (DK)"), # 14
self._action_insert = QAction(self)
self._action_insert.triggered.connect(self.insert_point)
self._menu.addAction(self._action_insert)
-
- # _translate("Board", "Fix Ref Point (DK)"), # 12
- # _translate("Board", "Un-Fix Ref Point (DK)"), # 13
self._action_fix_pt = QAction(self)
self._action_fix_pt.triggered.connect(lambda: self.ps_assit_pt_changed.emit(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5]) if self._args.sys_activated_assit_idx >= 0 else None)
self._menu.addAction(self._action_fix_pt)
-
- # _translate("Board", "Rev-Replace Color (Alt+DK)"), # 15
self._action_rev_insert = QAction(self)
self._action_rev_insert.triggered.connect(self.act_rev_insert_color_box)
self._menu.addAction(self._action_rev_insert)
-
- # _translate("Board", "Delete Ref Point"), # 11
- # _translate("Board", "Delete Color Box"), # 18
self._action_delete = QAction(self)
self._action_delete.triggered.connect(self.delete_point)
self._menu.addAction(self._action_delete)
-
- # _translate("Board", "Insert Color Box (Shift+DK)"), # 16
self._action_insert_beside = QAction(self)
self._action_insert_beside.triggered.connect(self.act_append_beside_color_box)
self._menu.addAction(self._action_insert_beside)
-
- # _translate("Board", "Append Color Box"), # 17
self._action_insert_append = QAction(self)
self._action_insert_append.triggered.connect(self.act_append_color_box)
self._menu.addAction(self._action_insert_append)
-
- # _translate("Board", "Switch Color Boxes"), # 19
self._action_switch = QAction(self)
self._action_switch.triggered.connect(self.switch_point)
self._menu.addAction(self._action_switch)
-
- # _translate("Board", "Show Points"), # 26
- # _translate("Board", "Hide Points"), # 27
self._action_hide_pt = QAction(self)
self._action_hide_pt.triggered.connect(self.show_or_hide_points)
self._menu.addAction(self._action_hide_pt)
-
- # _translate("Board", "Link with Result (Ctrl+DK)"), # 21
- # _translate("Board", "Un-Link with Result (Ctrl+DK)"), # 22
self._action_link = QAction(self)
self._action_link.triggered.connect(lambda: self.link_point(not self._args.sys_link_colors[0]))
self._menu.addAction(self._action_link)
-
- # _translate("Board", "Make Gradient Board"), # 23
- # _translate("Board", "Make Fixed Board"), # 24
- # _translate("Board", "Make Ref Board"), # 25
self._action_fixed_board = QAction(self)
self._action_fixed_board.triggered.connect(self.clear_or_gen_grid_list)
self._menu.addAction(self._action_fixed_board)
-
self._action_ref_board = QAction(self)
self._action_ref_board.triggered.connect(self.clear_or_gen_assit_color_list)
self._menu.addAction(self._action_ref_board)
-
- # _translate("Board", "Show Detail"), # 20
self._action_detail = QAction(self)
self._action_detail.triggered.connect(self.detail_point)
self._menu.addAction(self._action_detail)
def show_menu(self):
- """
- Show the right clicked menu.
- """
-
self.update_action_text()
-
- # special actions for delete later.
self._action_copy_rgb.setVisible(True)
self._action_copy_hsv.setVisible(True)
self._action_copy_hec.setVisible(True)
@@ -1763,8 +1108,6 @@ def show_menu(self):
self._action_detail.setVisible(True)
self._action_link.setVisible(True)
self._action_fix_pt.setVisible(True)
-
- # normal actions delete.
if self._args.sys_grid_list[0]:
self._action_rev_insert.setVisible(True)
self._action_insert_beside.setVisible(True)
@@ -1774,7 +1117,6 @@ def show_menu(self):
self._action_link.setVisible(True)
self._action_ref_board.setVisible(False)
self._action_hide_pt.setVisible(False)
-
else:
self._action_rev_insert.setVisible(False)
self._action_insert_beside.setVisible(False)
@@ -1784,22 +1126,16 @@ def show_menu(self):
self._action_link.setVisible(False)
self._action_ref_board.setVisible(True)
self._action_hide_pt.setVisible(True)
-
if self._args.sys_grid_list[0] or self._show_points:
self._action_insert.setVisible(True)
self._action_delete.setVisible(True)
-
else:
self._action_insert.setVisible(False)
self._action_delete.setVisible(False)
-
if not self._args.sys_grid_list[0] and self._show_points:
self._action_fix_pt.setVisible(True)
-
else:
self._action_fix_pt.setVisible(False)
-
- # special actions delete here.
if self._args.sys_grid_list[0] and self._selecting_idx >= len(self._args.sys_grid_list[0]):
self._action_copy_rgb.setVisible(False)
self._action_copy_hsv.setVisible(False)
@@ -1808,273 +1144,169 @@ def show_menu(self):
self._action_switch.setVisible(False)
self._action_detail.setVisible(False)
self._action_link.setVisible(False)
-
if self._args.sys_activated_assit_idx < 0:
self._action_fix_pt.setVisible(False)
-
self._menu.exec_(QCursor.pos())
- # ---------- ---------- ---------- Shortcut ---------- ---------- ---------- #
-
def update_skey(self):
- """
- Set board shortcuts.
- """
-
for skey in self._args.shortcut_keymaps[39]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.delete_point)
-
for skey in self._args.shortcut_keymaps[40]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.confirm_delete_point)
-
for skey in self._args.shortcut_keymaps[38]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.insert_point)
-
for skey in self._args.shortcut_keymaps[41]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.detail_point)
-
for skey in self._args.shortcut_keymaps[42]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.switch_point)
-
for skey in self._args.shortcut_keymaps[43]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.show_or_hide_points)
-
for skey in self._args.shortcut_keymaps[44]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clear_or_gen_grid_list)
-
for skey in self._args.shortcut_keymaps[51]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clear_or_gen_assit_color_list)
-
for skey in self._args.shortcut_keymaps[20]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_cur("rgb"))
-
for skey in self._args.shortcut_keymaps[21]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_cur("hsv"))
-
for skey in self._args.shortcut_keymaps[22]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_cur("hec"))
-
for skey in self._args.shortcut_keymaps[45]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_img)
-
for skey in self._args.shortcut_keymaps[46]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_in)
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_action_text(self):
- # _translate("Board", "Undo"), # 0
- # _translate("Board", "Redo"), # 1
self._action_undo.setText(self._action_descs[0])
self._action_redo.setText(self._action_descs[1])
-
- # _translate("Board", "Reset"), # 2
self._action_reset.setText(self._action_descs[2])
-
- # _translate("Board", "Copy RGB"), # 3
- # _translate("Board", "Copy HSV"), # 4
- # _translate("Board", "Copy Hex Code"), # 5
self._action_copy_rgb.setText(self._action_descs[3])
self._action_copy_hsv.setText(self._action_descs[4])
self._action_copy_hec.setText(self._action_descs[5])
-
- # _translate("Board", "Copy as Image"), # 6
self._action_copy_img.setText(self._action_descs[6])
-
- # _translate("Board", "Paste"), # 7
self._action_paste.setText(self._action_descs[7])
-
- # _translate("Board", "Zoom In"), # 8
- # _translate("Board", "Zoom Out"), # 9
self._action_zoom_in.setText(self._action_descs[8])
self._action_zoom_out.setText(self._action_descs[9])
-
- # _translate("Board", "Insert Ref Point (Ctrl+MV)"), # 10
- # _translate("Board", "Replace Color (DK)"), # 14
if self._args.sys_grid_list[0]:
self._action_insert.setText(self._action_descs[14])
-
else:
self._action_insert.setText(self._action_descs[10])
-
- # _translate("Board", "Delete Ref Point"), # 11
- # _translate("Board", "Delete Color Box"), # 18
if self._args.sys_grid_list[0]:
self._action_delete.setText(self._action_descs[18])
-
else:
self._action_delete.setText(self._action_descs[11])
-
- # _translate("Board", "Fix Ref Point (DK)"), # 12
- # _translate("Board", "Un-Fix Ref Point (DK)"), # 13
if self._args.sys_activated_assit_idx >= 0 and self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5]:
self._action_fix_pt.setText(self._action_descs[12])
-
else:
self._action_fix_pt.setText(self._action_descs[13])
-
- # _translate("Board", "Rev-Replace Color (Alt+DK)"), # 15
self._action_rev_insert.setText(self._action_descs[15])
-
- # _translate("Board", "Insert Color Box (Shift+DK)"), # 16
self._action_insert_beside.setText(self._action_descs[16])
-
- # _translate("Board", "Append Color Box"), # 17
self._action_insert_append.setText(self._action_descs[17])
-
- # _translate("Board", "Switch Color Boxes"), # 19
self._action_switch.setText(self._action_descs[19])
-
- # _translate("Board", "Show Detail"), # 20
self._action_detail.setText(self._action_descs[20])
-
- # _translate("Board", "Link with Result (Ctrl+DK)"), # 21
- # _translate("Board", "Un-Link with Result (Ctrl+DK)"), # 22
if self._args.sys_link_colors[0]:
self._action_link.setText(self._action_descs[22])
-
else:
self._action_link.setText(self._action_descs[21])
-
- # _translate("Board", "Make Gradient Board"), # 23
- # _translate("Board", "Make Fixed Board"), # 24
- # _translate("Board", "Make Ref Board"), # 25
if self._args.sys_grid_list[0]:
self._action_fixed_board.setText(self._action_descs[23])
self._action_ref_board.setText(self._action_descs[23])
-
else:
self._action_fixed_board.setText(self._action_descs[24])
self._action_ref_board.setText(self._action_descs[25])
-
- # _translate("Board", "Show Points"), # 26
- # _translate("Board", "Hide Points"), # 27
if self._show_points:
self._action_hide_pt.setText(self._action_descs[27])
-
else:
self._action_hide_pt.setText(self._action_descs[26])
-
- # _translate("Board", "Freeze Image"), # 28
- # _translate("Board", "Save Image"), # 29
self._action_freeze_img.setText(self._action_descs[28])
self._action_save_img.setText(self._action_descs[29])
def update_text(self):
self.update_action_text()
-
self._color_box.set_default_name(self._tip_descs[0])
-
self._color_box._func_tr_()
self._color_box.update_text()
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._action_descs = (
_translate("Wheel", "Undo"), # 0
_translate("Wheel", "Redo"), # 1
@@ -2107,16 +1339,33 @@ def _func_tr_(self):
_translate("Image", "Freeze Image"), # 28
_translate("Image", "Save Image"), # 29
)
-
self._tip_descs = (
_translate("Info", "Rickrack Color Box"),
)
-
self._color_descs = (
- _translate("Info", "Main Color"),
- _translate("Info", "Reference Color"),
+ _translate("Info", "Main Color {}: {}"),
+ _translate("Info", "Reference Color {}: {}"),
+ _translate("Rickrack", "Deep "),
+ _translate("Rickrack", "Snow "),
+ _translate("Rickrack", "Heavy "),
+ _translate("Rickrack", "Dull "),
+ _translate("Rickrack", "Grey "),
+ _translate("Rickrack", "Pale "),
+ _translate("Rickrack", "Light "),
+ _translate("Rickrack", "Bright "),
+ _translate("Rickrack", "Dark "),
+ _translate("Rickrack", "Vivid "),
+ _translate("Rickrack", "Black"),
+ _translate("Rickrack", "White"),
+ _translate("Rickrack", "Red"),
+ _translate("Rickrack", "Yellow"),
+ _translate("Rickrack", "Green"),
+ _translate("Rickrack", "Cyan"),
+ _translate("Rickrack", "Blue"),
+ _translate("Rickrack", "Magenta"),
+ _translate("Rickrack", "Orange"),
+ _translate("Rickrack", "Pink"),
)
-
self._operation_warns = (
_translate("Info", "Warning"),
_translate("Info", "OK"),
@@ -2124,14 +1373,12 @@ def _func_tr_(self):
_translate("Info", "The selected color box will be removed from board."),
_translate("Info", "The selected assistant point will be removed from board."),
)
-
self._open_descs = (
_translate("Image", "Double click here to open an image."),
_translate("Image", "Open"),
_translate("Image", "Save"),
_translate("Image", "Cover"),
)
-
self._extend_descs = (
_translate("Image", "All Acceptable Images"),
_translate("Image", "PNG Image"),
diff --git a/src/main/python/wgets/channel.py b/src/main/python/wgets/channel.py
index 21772c4..0b6e572 100644
--- a/src/main/python/wgets/channel.py
+++ b/src/main/python/wgets/channel.py
@@ -18,164 +18,109 @@
class Channel(QWidget):
- """
- Channel object based on QWidget. Init a channel in channel.
- """
-
ps_channel_changed = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init channel.
- """
-
super().__init__(wget)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
self._backups = ()
-
- # load translations.
self._func_tr_()
-
- # init qt args.
channel_grid_layout = QGridLayout(self)
channel_grid_layout.setContentsMargins(0, 0, 0, 0)
channel_grid_layout.setHorizontalSpacing(0)
channel_grid_layout.setVerticalSpacing(0)
-
scroll_area = QScrollArea(self)
scroll_area.setFrameShape(QFrame.Box)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setWidgetResizable(True)
channel_grid_layout.addWidget(scroll_area)
-
scroll_contents = QWidget()
scroll_grid_layout = QGridLayout(scroll_contents)
scroll_grid_layout.setContentsMargins(3, 9, 3, 3)
scroll_grid_layout.setHorizontalSpacing(3)
scroll_grid_layout.setVerticalSpacing(12)
scroll_area.setWidget(scroll_contents)
-
self._category_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._category_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(16)
scroll_grid_layout.addWidget(self._category_gbox, 0, 1, 1, 1)
-
self._category_btns = []
for i in range(8):
btn = QRadioButton(self._category_gbox)
gbox_grid_layout.addWidget(btn, i, 0, 1, 1)
-
btn.clicked.connect(self.modify_category(i))
self._category_btns.append(btn)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 8, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 8, 1, 1, 1)
-
self._channel_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._channel_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(16)
scroll_grid_layout.addWidget(self._channel_gbox, 1, 1, 1, 1)
-
self._channel_btns = []
for i in range(7):
btn = QRadioButton(self._channel_gbox)
gbox_grid_layout.addWidget(btn, i, 0, 1, 1)
-
btn.clicked.connect(self.modify_channel(i))
self._channel_btns.append(btn)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 7, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 7, 1, 1, 1)
-
self.reset()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def sizeHint(self):
- return QSize(210, 90)
+ return QSize(250, 90)
def reset(self):
self._category_btns[self._args.sys_category].setChecked(True)
self._channel_btns[self._args.sys_channel].setChecked(True)
-
self.update_text()
def modify_category(self, idx):
- """
- Modify stored category set by btn.
- """
-
def _func_(value):
self._backups = (self._args.sys_category, self._args.sys_channel)
-
self._args.sys_category = idx
self.ps_channel_changed.emit(True)
-
self.update_text()
-
return _func_
def modify_channel(self, idx):
- """
- Modify stored channel set by btn.
- """
-
def _func_(value):
self._backups = (self._args.sys_category, self._args.sys_channel)
-
self._args.sys_channel = idx
self.ps_channel_changed.emit(True)
-
return _func_
def recover(self):
- """
- Recover sys_category and sys_channel from backups.
- """
-
self._args.sys_category, self._args.sys_channel = self._backups
self.reset()
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self._category_gbox.setTitle(self._gbox_descs[0])
self._channel_gbox.setTitle(self._gbox_descs[1])
-
for i in range(8):
self._category_btns[i].setText(self._category_descs[i])
-
if self._args.sys_category in range(4):
for i in range(7):
self._channel_btns[i].setText(self._channel_descs[i])
-
else:
for i in range(7):
self._channel_btns[i].setText(self._channel_descs[i + 7])
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._gbox_descs = (
_translate("Channel", "Category"),
_translate("Channel", "Channel"),
)
-
self._category_descs = (
_translate("Channel", "Norm RGB"),
_translate("Channel", "Vtcl RGB"),
@@ -186,7 +131,6 @@ def _func_tr_(self):
_translate("Channel", "Horz HSV"),
_translate("Channel", "Finl HSV"),
)
-
self._channel_descs = (
_translate("Channel", "Full RGB"),
_translate("Channel", "Chnnel R"),
diff --git a/src/main/python/wgets/choice.py b/src/main/python/wgets/choice.py
index 2471262..4955666 100644
--- a/src/main/python/wgets/choice.py
+++ b/src/main/python/wgets/choice.py
@@ -22,111 +22,64 @@
class Choice(QDialog):
def __init__(self, wget, args):
- """
- Init settings.
- """
-
super().__init__(wget, Qt.WindowCloseButtonHint)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
- # load translations.
self._func_tr_()
-
- # init qt args.
app_icon = QIcon()
app_icon.addPixmap(QPixmap(":/images/images/icon_128.png"), QIcon.Normal, QIcon.Off)
self.setWindowIcon(app_icon)
-
self.setObjectName("Choice")
self.resize(300, 200)
-
choice_grid_layout = QGridLayout(self)
-
self.choice_label = QLabel(self)
choice_grid_layout.addWidget(self.choice_label, 0, 0, 1, 1)
self.choice_label.setWordWrap(True)
-
self.choice_btn = QPushButton(self)
choice_grid_layout.addWidget(self.choice_btn, 1, 0, 1, 1)
self.choice_btn.clicked.connect(self.apply_choice)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def apply_choice(self):
- """
- Apply current choice of color.
- """
-
self._args.sys_choice_stat = []
self.hide()
def showup(self):
- """
- Initialize and show.
- """
-
self.update_text()
self.show()
- # ---------- ---------- ---------- Event Funcs ---------- ---------- ---------- #
-
def closeEvent(self, event):
- """
- Actions before close dialog.
- """
-
self.apply_choice()
event.accept()
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self.setWindowTitle(self._choice_descs[0])
-
if self._args.sys_choice_stat:
if len(self._args.sys_choice_stat) > 1:
pre_text = self._choice_descs[1].join(self._args.sys_choice_stat[:-1])
end_text = self._args.sys_choice_stat[-1]
-
if self._args.lang[:2].lower() in ("zh", "ja", "ko"):
if check_file_name(pre_text[-1]):
pre_text = pre_text + " "
-
if check_file_name(end_text[0]):
end_text = " " + end_text
-
if check_file_name(end_text[-1]):
end_text = end_text + " "
-
text = pre_text + self._choice_descs[2] + end_text
-
else:
text = self._args.sys_choice_stat[0]
-
if self._args.lang[:2].lower() in ("zh", "ja", "ko"):
if check_file_name(text[-1]):
text = text + " "
-
text += self._choice_descs[3]
-
else:
text = ""
-
self.choice_label.setText(text)
self.choice_btn.setText(self._choice_descs[4])
-
self.choice_label.setAlignment(Qt.AlignCenter)
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._choice_descs = (
_translate("Choice", "Choice"),
_translate("Info", ", "),
diff --git a/src/main/python/wgets/cube.py b/src/main/python/wgets/cube.py
index 450a767..f73b598 100644
--- a/src/main/python/wgets/cube.py
+++ b/src/main/python/wgets/cube.py
@@ -23,130 +23,88 @@
class Square(QWidget):
- """
- Square objet based on QWidget. Init a color square in cube.
- """
-
ps_color_changed = pyqtSignal(bool)
ps_index_changed = pyqtSignal(bool)
def __init__(self, wget, args, idx):
- """
- Init color square.
- """
-
super().__init__(wget)
-
- # load args.
self._args = args
self._idx = idx
- # ---------- ---------- ---------- Paint Funcs ---------- ---------- ---------- #
-
def paintEvent(self, event):
- # norm assit point index.
if False: # self._args.sys_activated_assit_idx > len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]):
self._args.sys_activated_assit_idx = -1
-
rto = (1.0 - self._args.cubic_ratio) / 2
-
- self._box = (self.width() * rto, self.height() * rto, self.width() * self._args.cubic_ratio, self.height() * self._args.cubic_ratio)
-
+ self._box = (int(self.width() * rto) + self._args.positive_wid, self._args.positive_wid, int(self.width() * self._args.cubic_ratio - self._args.positive_wid * 2), self.height() - self._args.positive_wid * 2)
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setRenderHint(QPainter.TextAntialiasing, True)
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
-
- # main color.
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QColor(*self._args.sys_color_set[self._idx].rgb))
painter.drawRect(*self._box)
-
- # assit colors and frames.
assit_len = len(self._args.sys_grid_assitlocs[self._idx])
assit_w = self._box[2] / (assit_len + 1)
- assit_h = self._box[3] / 4
-
+ assit_h = self._box[3] * 0.382
+ start_w = self._box[0] + assit_w
+ start_h = self._box[3] - assit_h
self._assit_boxes = []
-
self._assit_idx_seq = list(range(len(self._args.sys_grid_assitlocs[self._idx])))
if self._args.sys_activated_assit_idx >= 0:
self._assit_idx_seq = self._assit_idx_seq[self._args.sys_activated_assit_idx + 1: ] + self._assit_idx_seq[: self._args.sys_activated_assit_idx + 1]
-
for assit_idx in self._assit_idx_seq:
- assit_box = (self._box[0] + assit_w * (assit_idx + 1), self._box[1] + assit_h * 3, assit_w, assit_h)
+ assit_box = (start_w + assit_w * assit_idx, start_h, assit_w, assit_h)
assit_color = gen_assit_color(self._args.sys_color_set[self._idx], *self._args.sys_grid_assitlocs[self._idx][assit_idx][2:6])
assit_frame_color = self._args.positive_color if self._idx == self._args.sys_activated_idx and assit_idx == self._args.sys_activated_assit_idx else self._args.negative_color
-
self._assit_boxes.append(assit_box)
-
- painter.setPen(QPen(QColor(*assit_frame_color), self._args.negative_wid))
+ painter.setPen(Qt.NoPen)
painter.setBrush(QColor(*assit_color.rgb))
painter.drawRect(*assit_box)
-
- # relative (move-able) or ref (un-move-able) point tag.
+ if self._idx == self._args.sys_activated_idx and assit_idx == self._args.sys_activated_assit_idx:
+ painter.setPen(QPen(QColor(*assit_frame_color), self._args.positive_wid))
+ painter.setBrush(Qt.NoBrush)
+ painter.drawRect(*assit_box)
if not self._args.sys_grid_assitlocs[self._idx][assit_idx][5]:
dot_box = get_outer_box((assit_box[0] + assit_box[2] / 5, assit_box[1] + assit_box[3] / 5), self._args.negative_wid)
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QBrush(QColor(*assit_frame_color)))
painter.drawEllipse(*dot_box)
-
- # main frame.
if self._idx == self._args.sys_activated_idx:
- painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid * 1.5))
-
+ painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
else:
- painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid * 1.5))
-
+ painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid))
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawRect(*self._box)
-
- # link tag.
if self._idx == self._args.sys_activated_idx and (self._args.sys_link_colors[0] or self._args.sys_link_colors[1]):
link_box = (self._box[0], self._box[1], self._box[2] / 3.0, self._box[3] / 3.0)
link_square_left, link_square_right, link_wid, link_line_start, link_line_end = get_link_tag(link_box)
-
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawRoundedRect(*link_square_left, link_wid, link_wid)
painter.drawRoundedRect(*link_square_right, link_wid, link_wid)
painter.drawLine(QPoint(*link_line_start), QPoint(*link_line_end))
-
painter.end()
- # ---------- ---------- ---------- Mouse Event Funcs ---------- ---------- ---------- #
-
def mousePressEvent(self, event):
if event.button() in (Qt.LeftButton, Qt.RightButton):
p_x = event.x()
p_y = event.y()
-
if self._box[0] < p_x < (self._box[0] + self._box[2]) and self._box[1] < p_y < (self._box[1] + self._box[3]):
self._args.sys_activated_assit_idx = -1
-
- # click on assit colors.
for seq_idx in range(len(self._assit_idx_seq)):
assit_box = self._assit_boxes[seq_idx]
-
if assit_box[0] < p_x < (assit_box[0] + assit_box[2]) and assit_box[1] < p_y < (assit_box[1] + assit_box[3]):
self._args.sys_activated_idx = self._idx
self._args.sys_activated_assit_idx = self._assit_idx_seq[seq_idx]
-
break
-
- # click on the main color.
if self._args.sys_activated_assit_idx < 0:
self._args.sys_activated_idx = self._idx
self._args.sys_activated_assit_idx = -1
-
self.ps_index_changed.emit(True)
-
event.accept()
self.update()
-
else:
event.ignore()
-
else:
event.ignore()
@@ -154,122 +112,73 @@ def mouseDoubleClickEvent(self, event):
if event.button() == Qt.LeftButton:
p_x = event.x()
p_y = event.y()
-
if self._box[0] < p_x < (self._box[0] + self._box[2]) and self._box[1] < p_y < (self._box[1] + self._box[3]):
if self._idx == self._args.sys_activated_idx and self._args.sys_activated_assit_idx >= 0:
curr_color = gen_assit_color(self._args.sys_color_set[self._idx], *self._args.sys_grid_assitlocs[self._idx][self._args.sys_activated_assit_idx][2:6])
-
else:
curr_color = self._args.sys_color_set[self._idx]
-
dialog = QColorDialog.getColor(QColor(*curr_color.rgb))
-
if dialog.isValid():
color = Color((dialog.red(), dialog.green(), dialog.blue()), tp="rgb", overflow=self._args.sys_color_set.get_overflow())
-
if self._idx == self._args.sys_activated_idx and self._args.sys_activated_assit_idx >= 0:
self._args.sys_grid_assitlocs[self._idx][self._args.sys_activated_assit_idx][2:5] = gen_assit_args(self._args.sys_color_set[self._idx], color, self._args.sys_grid_assitlocs[self._idx][self._args.sys_activated_assit_idx][5])
-
else:
self._args.sys_color_set.modify(self._args.hm_rule, self._idx, color)
-
self.ps_color_changed.emit(True)
-
event.accept()
self.update()
-
else:
event.ignore()
-
else:
event.ignore()
-
class Cube(QWidget, Ui_ScrollCube):
- """
- Cube object based on QWidget. Init a color cube in table.
- """
-
def __init__(self, wget, args, idx):
- """
- Init color cube.
- """
-
super().__init__(wget)
self.setupUi(self)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
self._idx = idx
-
- # init qt args.
cube_grid_layout = QGridLayout(self.cube_color)
cube_grid_layout.setContentsMargins(0, 0, 0, 0)
cube_grid_layout.setHorizontalSpacing(0)
cube_grid_layout.setVerticalSpacing(0)
-
self.square = Square(self.cube_color, self._args, self._idx)
cube_grid_layout.addWidget(self.square)
-
for tp in ("r", "g", "b"):
getattr(self, "hs_rgb_{}".format(tp)).wheelEvent = lambda event: event.ignore()
-
for tp in ("h", "s", "v"):
getattr(self, "hs_hsv_{}".format(tp)).wheelEvent = lambda event: event.ignore()
- # ---------- ---------- ---------- Paint Funcs ---------- ---------- ---------- #
-
def paintEvent(self, event):
- wid = self.cube_color.width()
- self.cube_color.setMinimumHeight(wid * 0.72)
- self.cube_color.setMaximumHeight(wid * 0.72)
-
+ wid = self.cube_color.width() * self._args.cubic_ratio
+ self.cube_color.setMinimumHeight(wid * 0.618)
+ self.cube_color.setMaximumHeight(wid * 0.618)
class CubeTable(QWidget):
- """
- CubeTable object based on QWidget. Init color cube table in result.
- """
-
ps_color_changed = pyqtSignal(bool)
ps_history_backup = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init color cube table.
- """
-
super().__init__(wget)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
self._updated_colors = False
-
- # init qt args.
self.setMinimumSize(120, 10)
-
cube_grid_layout = QGridLayout(self)
cube_grid_layout.setContentsMargins(0, 0, 0, 0)
cube_grid_layout.setHorizontalSpacing(0)
cube_grid_layout.setVerticalSpacing(0)
-
scroll_area = QScrollArea(self)
scroll_area.setFrameShape(QFrame.Box)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setWidgetResizable(True)
cube_grid_layout.addWidget(scroll_area)
-
scroll_contents = QWidget()
scroll_horizontal_layout = QHBoxLayout(scroll_contents)
scroll_horizontal_layout.setContentsMargins(0, 0, 0, 0)
scroll_area.setWidget(scroll_contents)
-
self._cubes = (
Cube(scroll_contents, args, 0),
Cube(scroll_contents, args, 1),
@@ -277,248 +186,149 @@ def __init__(self, wget, args):
Cube(scroll_contents, args, 3),
Cube(scroll_contents, args, 4),
)
-
self.update_color()
-
for idx in (2, 1, 0, 3, 4):
scroll_horizontal_layout.addWidget(self._cubes[idx])
self._cubes[idx].square.ps_color_changed.connect(lambda x: self.update_color())
self._cubes[idx].square.ps_color_changed.connect(lambda x: self.ps_history_backup.emit(True))
self._cubes[idx].square.ps_index_changed.connect(lambda x: self.update_color())
-
for ctp in ("r", "g", "b"):
- # horizontal slider.
obj = getattr(self._cubes[idx], "hs_rgb_{}".format(ctp))
obj.valueChanged.connect(self.modify_color(idx, "direct", ctp))
-
- # spin box.
obj = getattr(self._cubes[idx], "sp_rgb_{}".format(ctp))
obj.valueChanged.connect(self.modify_color(idx, "frdire", ctp))
-
for ctp in ("h", "s", "v"):
- # horizontal slider.
obj = getattr(self._cubes[idx], "hs_hsv_{}".format(ctp))
obj.valueChanged.connect(self.modify_color(idx, "indire", ctp))
-
- # double spin box.
obj = getattr(self._cubes[idx], "dp_hsv_{}".format(ctp))
obj.valueChanged.connect(self.modify_color(idx, "frdire", ctp))
-
self._cubes[idx].le_hec.textChanged.connect(self.modify_color(idx, "frdire", "hec"))
-
self.modify_box_visibility()
def sizeHint(self):
- return QSize(600, 150)
-
- # ---------- ---------- ---------- Mouse Event Funcs ---------- ---------- ---------- #
+ return QSize(600, 200)
def resizeEvent(self, event):
wid = self.geometry().width()
-
if wid < 650 and self._cubes[0].sp_rgb_r.isVisible():
for idx in (2, 1, 0, 3, 4):
for ctp in ("r", "g", "b"):
obj = getattr(self._cubes[idx], "sp_rgb_{}".format(ctp))
obj.setVisible(False)
-
for ctp in ("h", "s", "v"):
obj = getattr(self._cubes[idx], "dp_hsv_{}".format(ctp))
obj.setVisible(False)
-
if wid > 650 and not self._cubes[0].sp_rgb_r.isVisible():
for idx in (2, 1, 0, 3, 4):
for ctp in ("r", "g", "b"):
obj = getattr(self._cubes[idx], "sp_rgb_{}".format(ctp))
obj.setVisible(True)
-
for ctp in ("h", "s", "v"):
obj = getattr(self._cubes[idx], "dp_hsv_{}".format(ctp))
obj.setVisible(True)
-
event.ignore()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def modify_color(self, idx, kword, ctp):
- """
- Modify stored color set by slide and box name and value.
- """
-
def _func_(value):
if self._updated_colors:
return
-
if ctp == "hec":
value = Color.stri2color(value)
-
if not value:
return
-
self._updated_colors = True
-
color = Color(self._args.sys_color_set[idx], tp="color", overflow=self._args.sys_color_set.get_overflow())
if ctp == "hec":
color.setti(value, tp="color")
-
else:
if kword == "direct" or kword == "frdire":
color.setti(value, ctp)
-
else:
color.setti(value / 1E3, ctp)
-
self._args.sys_color_set.modify(self._args.hm_rule, idx, color)
-
if kword == "frdire":
self.update_color(skip_dp=(idx, ctp))
-
else:
self.update_color()
-
self._updated_colors = False
-
return _func_
def update_color(self, skip_dp=None):
- """
- Update all colors.
- """
-
self._updated_colors = True
-
for lc_idx in range(5):
if lc_idx == self._args.sys_activated_idx and self._args.sys_activated_assit_idx >= 0:
curr_color = gen_assit_color(self._args.sys_color_set[lc_idx], *self._args.sys_grid_assitlocs[lc_idx][self._args.sys_activated_assit_idx][2:6])
-
else:
curr_color = self._args.sys_color_set[lc_idx]
-
curr_hec = curr_color.getti("hec")
curr_h, curr_s, curr_v = curr_color.getti("hsv")
-
- # skip same color. no need to update.
if curr_hec == self._cubes[lc_idx].le_hec.text() and curr_s > 0.01 and 0.99 > curr_v > 0.01:
continue
-
if not (skip_dp and skip_dp[0] == lc_idx and skip_dp[1] == "hec"):
self._cubes[lc_idx].le_hec.setText(curr_hec)
-
for lc_ctp in ("r", "g", "b"):
obj = getattr(self._cubes[lc_idx], "hs_rgb_{}".format(lc_ctp))
obj.setValue(curr_color.getti(lc_ctp))
-
if not (skip_dp and skip_dp[0] == lc_idx and skip_dp[1] == lc_ctp):
obj = getattr(self._cubes[lc_idx], "sp_rgb_{}".format(lc_ctp))
obj.setValue(curr_color.getti(lc_ctp))
-
for lc_ctp in ("h", "s", "v"):
obj = getattr(self._cubes[lc_idx], "hs_hsv_{}".format(lc_ctp))
obj.setValue(vars()["curr_{}".format(lc_ctp)] * 1E3)
-
if not (skip_dp and skip_dp[0] == lc_idx and skip_dp[1] == lc_ctp):
obj = getattr(self._cubes[lc_idx], "dp_hsv_{}".format(lc_ctp))
obj.setValue(vars()["curr_{}".format(lc_ctp)])
-
self.update_index()
-
self._updated_colors = False
def update_index(self):
- """
- Update color activated index. Undertake func update_color.
- """
-
for lc_idx in range(5):
self._cubes[lc_idx].update()
-
self.ps_color_changed.emit(True)
def modify_rule(self):
- """
- Modify stored color set by rule selection.
- """
-
- """
- self._args.sys_grid_assitlocs = [[], [], [], [], []]
- self._args.sys_assit_color_locs = [[], [], [], [], []]
- self._args.sys_activated_assit_idx = -1
- """
-
self._args.sys_color_set.create(self._args.hm_rule)
-
self.update_color()
-
self.ps_history_backup.emit(True)
def create_set(self, direct=False):
- """
- Create stored color set by create button.
- """
-
if not direct and True in [bool(i) for i in self._args.sys_grid_assitlocs]:
self._args.sys_grid_assitlocs = [[], [], [], [], []]
self._args.sys_assit_color_locs = [[], [], [], [], []]
self._args.sys_activated_assit_idx = -1
-
else:
self._args.sys_color_set.initialize()
self._args.sys_color_set.create(self._args.hm_rule)
-
self.update_color()
-
self.ps_history_backup.emit(True)
def modify_box_visibility(self):
- """
- Modify the visibility of hsv or rgb cbox.
- """
-
for i in range(5):
self._cubes[i].gbox_hsv.setVisible(self._args.show_hsv)
self._cubes[i].gbox_rgb.setVisible(self._args.show_rgb)
def update_all(self):
- """
- Update five cubes and cube table.
- """
-
for lc_idx in range(5):
self._cubes[lc_idx].update()
-
self.update()
def clipboard_act(self, ctp):
- """
- Set the rgb, hsv or hec (hex code) of activated tag color as the clipboard data by shortcut r, h or c.
- """
-
def _func_():
color = self._args.sys_color_set[self._args.sys_activated_idx].getti(ctp)
-
if ctp == "hec":
color = self._args.hec_prefix[0] + str(color) + self._args.hec_prefix[1]
-
else:
color = self._args.rgb_prefix[1].join([self._args.r_prefix[0] + str(color[coi]) + self._args.r_prefix[1] for coi in range(3)])
color = self._args.rgb_prefix[0] + color + self._args.rgb_prefix[2]
-
mimedata = QMimeData()
mimedata.setText(color)
-
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
-
return _func_
def active_by_num(self, idx):
- """
- Set activated idx by shortcut 1, 2, 3, 4 and 5.
- """
-
def _func_():
self._args.sys_activated_idx = idx
self._args.sys_activated_assit_idx = -1
self.update_index()
-
return _func_
diff --git a/src/main/python/wgets/depot.py b/src/main/python/wgets/depot.py
index 5c301f7..a49101e 100644
--- a/src/main/python/wgets/depot.py
+++ b/src/main/python/wgets/depot.py
@@ -31,214 +31,136 @@
class Info(QDialog, Ui_InfoDialog):
- """
- Info object based on QDialog. Init color set information.
- """
-
def __init__(self, wget, args):
- """
- Init information.
- """
-
super().__init__(wget, Qt.WindowCloseButtonHint)
self.setupUi(self)
-
- # load args.
self._args = args
-
- # load translations.
self._func_tr_()
-
- # init qt args.
app_icon = QIcon()
app_icon.addPixmap(QPixmap(":/images/images/icon_128.png"), QIcon.Normal, QIcon.Off)
self.setWindowIcon(app_icon)
-
self._clone = None
self._unit_cell = UnitCell(self.colors, self._args)
-
color_grid_layout = QGridLayout(self.colors)
color_grid_layout.setContentsMargins(1, 1, 1, 1)
color_grid_layout.addWidget(self._unit_cell)
-
- # init buttons.
self.buttonBox.clear()
-
self._btn_1 = QPushButton()
self._btn_1.clicked.connect(self.application)
self.buttonBox.addButton(self._btn_1, QDialogButtonBox.AcceptRole)
-
self._btn_2 = QPushButton()
self._btn_2.clicked.connect(self.close)
self.buttonBox.addButton(self._btn_2, QDialogButtonBox.RejectRole)
-
self._btn_3 = QPushButton()
self._btn_3.clicked.connect(self.update_values)
self.buttonBox.addButton(self._btn_3, QDialogButtonBox.ApplyRole)
-
self._btn_4 = QPushButton()
self._btn_4.clicked.connect(self.reset_values)
self.buttonBox.addButton(self._btn_4, QDialogButtonBox.ResetRole)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def clone_cell(self, unit_cell):
if isinstance(unit_cell, UnitCell) and len(unit_cell.color_set) == 5 and None not in self._unit_cell.color_set:
self._clone = unit_cell
-
self._unit_cell.color_set = unit_cell.color_set
-
if unit_cell.grid_list[0]:
self._unit_cell.grid_list = [["FFFFFF",], ["",]]
-
else:
self._unit_cell.grid_list = [[], []]
-
self._unit_cell.update()
-
if unit_cell.name:
self.name_ledit.setText(unit_cell.name)
-
else:
self.name_ledit.setText(self._cell_descs[0])
-
if unit_cell.desc:
self.desc_tedit.setText(unit_cell.desc)
-
else:
color_signs = []
-
for i in (2, 1, 0, 3, 4):
sign = Color.sign(self._unit_cell.color_set[i].hsv)
color_signs.append(self._color_descs[sign[0]] + self._color_descs[sign[1] + 10])
-
desc_context = self._cell_descs[2].format(*color_signs) + "\n"
-
if unit_cell.grid_list[0]:
if len(unit_cell.grid_list[0]) > 5:
list_out_signs = [Color.sign(Color.hec2hsv(coitem)) for coitem in unit_cell.grid_list[0][:5]]
list_out_colors = [self._color_descs[snitem[0]] + self._color_descs[snitem[1] + 10] for snitem in list_out_signs]
-
for i in range(5):
if len(unit_cell.grid_list[1]) > i and unit_cell.grid_list[1][i]:
list_out_colors[i] = unit_cell.grid_list[1][i]
-
list_out_text = self._cell_descs[4].join(list_out_colors) + self._cell_descs[6]
-
elif len(unit_cell.grid_list[0]) > 1:
list_out_signs = [Color.sign(Color.hec2hsv(coitem)) for coitem in unit_cell.grid_list[0]]
list_out_colors = [self._color_descs[snitem[0]] + self._color_descs[snitem[1] + 10] for snitem in list_out_signs]
-
for i in range(len(unit_cell.grid_list[0])):
if len(unit_cell.grid_list[1]) > i and unit_cell.grid_list[1][i]:
list_out_colors[i] = unit_cell.grid_list[1][i]
-
list_out_text = self._cell_descs[4].join(list_out_colors[:-1]) + self._cell_descs[5] + list_out_colors[-1]
-
elif len(unit_cell.grid_list[0]) == 1:
one_sign = Color.sign(Color.hec2hsv(unit_cell.grid_list[0][0]))
list_out_text = self._color_descs[one_sign[0]] + self._color_descs[one_sign[1] + 10]
-
else:
list_out_text = ""
-
desc_context = desc_context + self._cell_descs[3].format(list_out_text) + "\n"
-
else:
desc_context = desc_context + self._cell_descs[7]
-
self.desc_tedit.setText(desc_context)
-
self.hm_rule_label.setText(self._rule_descs[self._args.global_hm_rules.index(unit_cell.hm_rule)])
-
if unit_cell.cr_time[0] < 0:
time_str = self._cell_descs[1]
-
else:
time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(unit_cell.cr_time[0]))
-
if unit_cell.cr_time[1] < 0:
time_str += "\n{}".format(self._cell_descs[1])
-
else:
time_str += "\n{}".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(unit_cell.cr_time[1])))
-
self.cr_time_label.setText(time_str)
-
else:
self._clone = None
-
self._unit_cell.color_set = []
self._unit_cell.update()
-
self.name_ledit.setText(self._cell_descs[8])
self.desc_tedit.setText(self._cell_descs[9])
self.cr_time_label.setText(self._cell_descs[1] + "\n" + self._cell_descs[1])
self.hm_rule_label.setText(self._rule_descs[self._args.global_hm_rules.index(self._args.hm_rule)])
def application(self):
- """
- Modify the values.
- """
-
if self._clone:
name = re.split(r"[\v\a\f\n\r\t]", str(self.name_ledit.text()))
desc = re.split(r"[\v\a\f]", str(self.desc_tedit.toPlainText()))
-
while "" in name:
name.remove("")
-
if name:
name = name[0].lstrip().rstrip()
-
else:
name = ""
-
while "" in desc:
desc.remove("")
-
if desc:
desc = desc[0].lstrip().rstrip()
-
else:
desc = ""
-
if name != self._clone.name or desc != self._clone.desc:
self._clone.name = name
self._clone.desc = desc
self._clone.cr_time = (self._clone.cr_time[0], time.time())
def update_values(self):
- """
- For button apply.
- """
-
self.application()
self.clone_cell(self._clone)
def reset_values(self):
- """
- For button reset.
- """
-
self.clone_cell(self._clone)
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self.setWindowTitle(self._dialog_descs[0])
self._btn_1.setText(self._dialog_descs[1])
self._btn_2.setText(self._dialog_descs[2])
self._btn_3.setText(self._dialog_descs[3])
self._btn_4.setText(self._dialog_descs[4])
-
self.retranslateUi(self)
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._dialog_descs = (
_translate("Info", "Information"),
_translate("Info", "OK"),
@@ -246,7 +168,6 @@ def _func_tr_(self):
_translate("Info", "Apply"),
_translate("Info", "Reset"),
)
-
self._cell_descs = (
_translate("Info", "Rickrack Color Set"),
_translate("Info", "Unknown"),
@@ -259,7 +180,6 @@ def _func_tr_(self):
_translate("Info", "Uninitialized Color Set"),
_translate("Info", "Double Click The Blank Set to Initialize."),
)
-
self._rule_descs = (
_translate("Rule", "Analogous"),
_translate("Rule", "Monochromatic"),
@@ -270,7 +190,6 @@ def _func_tr_(self):
_translate("Rule", "Shades"),
_translate("Rule", "Custom"),
)
-
self._color_descs = (
_translate("Rickrack", "Deep "),
_translate("Rickrack", "Snow "),
@@ -294,84 +213,53 @@ def _func_tr_(self):
_translate("Rickrack", "Pink"),
)
-
class UnitCell(QWidget):
- """
- UnitCell objet based on QWidget. Init an unit cell in depot.
- """
-
def __init__(self, wget, args, hsv_set=[], hm_rule="", name="", desc="", cr_time=(0, 0), grid_locations=[], grid_assitlocs=[], grid_list=[], grid_values={}):
- """
- Init empty unit cell.
- """
-
super().__init__(wget)
-
- # load args.
self._args = args
-
self.activated = False
-
name_stri = re.split(r"[\v\a\f\n\r\t]", str(name))
desc_stri = re.split(r"[\v\a\f]", str(desc))
-
while "" in name_stri:
name_stri.remove("")
-
if name_stri:
name_stri = name_stri[0].lstrip().rstrip()
-
else:
name_stri = ""
-
while "" in desc_stri:
desc_stri.remove("")
-
if desc_stri:
desc_stri = desc_stri[0].lstrip().rstrip()
-
else:
desc_stri = ""
-
self.name = name_stri
self.desc = desc_stri
-
self.cr_time = fmt_im_time(cr_time)
-
self.update_colors(hsv_set, hm_rule, grid_locations, grid_assitlocs, grid_list, grid_values, update_time=False)
def update_colors(self, hsv_set, hm_rule, grid_locations, grid_assitlocs, grid_list, grid_values, update_time=True):
self.color_set = []
-
for hsv in hsv_set:
if hsv == None:
self.color_set.append(None)
-
else:
self.color_set.append(FakeColor(Color.hsv2rgb(hsv), hsv, Color.hsv2hec(hsv)))
-
self.color_set = tuple(self.color_set)
self.hm_rule = str(hm_rule)
-
if hsv_set:
self.grid_locations, self.grid_assitlocs = norm_grid_locations(grid_locations, grid_assitlocs)
self.grid_list = norm_grid_list(grid_list) # ["000000", "FF0000", "00FF00", "0000FF", "FFFF00", "00FFFF"]
self.grid_values = norm_grid_values(grid_values)
-
else:
self.grid_locations = []
self.grid_assitlocs = []
self.grid_list = [[], []]
self.grid_values = {}
-
if update_time:
self.cr_time = fmt_im_time((self.cr_time[0], time.time()))
- # ---------- ---------- ---------- Paint Funcs ---------- ---------- ---------- #
-
def paintEvent(self, event):
cs_wid = int(min(self.width(), self.height()) * self._args.coset_ratio / 2)
-
cs_boxes = (
(self.width() / 2 - cs_wid, self.height() / 2 - cs_wid, cs_wid, cs_wid),
(self.width() / 2, self.height() / 2 - cs_wid, cs_wid, cs_wid),
@@ -379,69 +267,49 @@ def paintEvent(self, event):
(self.width() / 2, self.height() / 2, cs_wid, cs_wid),
(self.width() / 2 - cs_wid / 2, self.height() / 2 - cs_wid / 2, cs_wid, cs_wid),
)
-
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setRenderHint(QPainter.TextAntialiasing, True)
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
-
if self.activated:
curr_box = (self._args.negative_wid, self._args.negative_wid, self.width() - self._args.negative_wid * 2, self.height() - self._args.negative_wid * 2)
-
- painter.setPen(QPen(QColor(*self._args.positive_color), self._args.negative_wid))
- painter.setBrush(QColor(*self._args.wheel_ed_color))
+ alpha = 255 if self._args.style_id < 5 else 120
+ painter.setPen(QPen(QColor(*self._args.wheel_ed_color), self._args.wheel_ed_wid))
+ painter.setBrush(QColor(*self._args.negative_color, alpha))
painter.drawRoundedRect(*curr_box, self.width() / 9, self.height() / 9)
-
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.negative_wid))
-
else:
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid))
-
for idx in range(5):
if len(self.color_set) == 5:
painter.setBrush(QColor(*self.color_set[4 - idx].rgb))
-
else:
painter.setBrush(QBrush(Qt.NoBrush))
-
painter.drawRoundedRect(*cs_boxes[idx], cs_wid / 9, cs_wid / 9)
-
if self.grid_list[0]:
painter.drawEllipse(*cs_boxes[idx])
-
if self.activated and self._args.sys_link_colors[1] and len(self.color_set) == 5:
link_square_left, link_square_right, link_wid, link_line_start, link_line_end = get_link_tag(cs_boxes[4])
-
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawRoundedRect(*link_square_left, link_wid, link_wid)
painter.drawRoundedRect(*link_square_right, link_wid, link_wid)
painter.drawLine(QPoint(*link_line_start), QPoint(*link_line_end))
-
painter.end()
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
if self.name:
self.setToolTip(self.name)
-
else:
self.setToolTip(self._cell_descs[0])
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._cell_descs = (
_translate("Info", "Rickrack Color Set"),
)
-
class Depot(QWidget):
- """
- Depot object based on QWidget. Init a color set depot in workarea.
- """
-
ps_update = pyqtSignal(bool)
ps_export = pyqtSignal(int)
ps_status_changed = pyqtSignal(tuple)
@@ -453,38 +321,22 @@ class Depot(QWidget):
ps_open_image_url = pyqtSignal(tuple)
def __init__(self, wget, args):
- """
- Init color set depot.
- """
-
super().__init__(wget)
-
- # set name ids.
wget.setProperty("class", "WorkArea")
-
- # load args.
self._args = args
- self._drop_file = None
self._left_click = False
- self._drag_file = False
self._double_click = False
self._start_hig = None
self._start_pt = None
self._current_idx = None
self._fetched_cell = None
- self._press_key = 0
self._connected_keymaps = {}
-
- # load translations.
+ self.init_key()
self._func_tr_()
-
- # init qt args.
self.setFocusPolicy(Qt.StrongFocus)
self.setAcceptDrops(True)
-
grid_layout = QGridLayout(self)
grid_layout.setContentsMargins(0, 0, 0, 0)
-
self._scroll_area = QScrollArea(self)
self._scroll_area.setProperty("class", "WorkArea")
self._scroll_area.setFrameShape(QFrame.Box)
@@ -492,86 +344,59 @@ def __init__(self, wget, args):
self._scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self._scroll_area.setWidgetResizable(True)
grid_layout.addWidget(self._scroll_area)
-
self._scroll_bar = self._scroll_area.verticalScrollBar()
-
self._scroll_contents = QWidget()
self._scroll_contents.setProperty("class", "WorkArea")
self._scroll_grid_layout = QGridLayout(self._scroll_contents)
self._scroll_grid_layout.setContentsMargins(0, 0, 0, 0)
self._scroll_area.setWidget(self._scroll_contents)
-
self.initialize()
-
self._info = Info(self, self._args)
-
self.create_menu()
self.update_text()
-
- # shortcut is updated by _setup_skey in main.py.
# self.update_skey()
-
- # stab_column is changed with the changing of interface size. this code is reused.
self._stab_column_wid = None
-
self._pl_wid = 0
self._tot_rows = 0
- # ---------- ---------- ---------- Paint Funcs ---------- ---------- ---------- #
-
def paintEvent(self, event):
self._pl_wid = int((self.width() - (self._scroll_bar.width() * 1.25)) / self._args.stab_column)
self._tot_rows = len(self._args.stab_ucells) // self._args.stab_column if len(self._args.stab_ucells) % self._args.stab_column == 0 else len(self._args.stab_ucells) // self._args.stab_column + 1
-
if not self._stab_column_wid:
self._stab_column_wid = int(self._pl_wid)
-
height = self._pl_wid * self._tot_rows
height = height if height > self._scroll_area.height() else self._scroll_area.height()
-
self._scroll_contents.setMinimumSize(self._pl_wid * self._args.stab_column, height)
self._scroll_contents.setMaximumSize(self._pl_wid * self._args.stab_column, height)
-
for i in range(self._tot_rows):
for j in range(self._args.stab_column):
idx = self._args.stab_column * i + j
-
if idx < len(self._args.stab_ucells) and isinstance(self._args.stab_ucells[idx], UnitCell):
self._args.stab_ucells[idx].setGeometry(self._pl_wid * j, self._pl_wid * i, self._pl_wid, self._pl_wid)
-
status_idx = self._current_idx
-
if status_idx == None:
status_idx = 0
-
else:
status_idx = status_idx + 1
-
self.ps_status_changed.emit((self._tot_rows, self._args.stab_column, len(self._args.stab_ucells) - 1, status_idx))
- # ---------- ---------- ---------- Mouse Event Funcs ---------- ---------- ---------- #
-
def keyPressEvent(self, event):
if event.key() == Qt.Key_Shift:
self._press_key = 1
self.setCursor(QCursor(Qt.PointingHandCursor))
event.accept()
-
elif event.key() == Qt.Key_Control:
self._press_key = 2
self.setCursor(QCursor(Qt.PointingHandCursor))
event.accept()
-
elif event.key() == Qt.Key_Space:
self._press_key = 3
self.setCursor(QCursor(Qt.ClosedHandCursor))
event.accept()
-
elif event.key() == Qt.Key_Alt:
self._press_key = 4
self.setCursor(QCursor(Qt.PointingHandCursor))
event.accept()
-
else:
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
@@ -584,26 +409,19 @@ def keyReleaseEvent(self, event):
def mousePressEvent(self, event):
point = np.array((event.x() - self._scroll_contents.x(), event.y() - self._scroll_contents.y()))
-
col = point[0] // self._pl_wid
row = point[1] // self._pl_wid
-
if self._press_key == 2 and event.button() == Qt.LeftButton:
color_list = []
-
for unit_cell in self._args.stab_ucells[:-1]:
if isinstance(unit_cell, UnitCell):
color_list.append((unit_cell.color_set, unit_cell.hm_rule, unit_cell.name, unit_cell.desc, unit_cell.cr_time, unit_cell.grid_locations, unit_cell.grid_assitlocs, unit_cell.grid_list, unit_cell.grid_values))
-
color_dict = {"version": self._args.info_version_en, "site": self._args.info_main_site, "type": "depot"}
color_dict["palettes"] = export_list(color_list)
color_path = os.sep.join((self._args.global_temp_dir.path(), "Rickrack_Depot_{}.dpc".format(abs(hash(str(color_dict))))))
-
with open(color_path, "w", encoding="utf-8") as f:
json.dump(color_dict, f, indent=4, ensure_ascii=False)
-
self._drag_file = True
-
drag = QDrag(self)
mimedata = QMimeData()
mimedata.setUrls([QUrl.fromLocalFile(color_path)])
@@ -612,63 +430,44 @@ def mousePressEvent(self, event):
drag.setPixmap(pixmap)
drag.setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2))
drag.exec_(Qt.CopyAction | Qt.MoveAction)
-
self._drag_file = False
-
- # color link will be invalided by code below.
# self._press_key = 0
# self.setCursor(QCursor(Qt.ArrowCursor))
-
elif col <= self._args.stab_column:
idx = self._args.stab_column * row + col
-
if event.button() == Qt.MidButton or (self._press_key == 3 and event.button() == Qt.LeftButton):
if event.button() == Qt.MidButton:
self.setCursor(QCursor(Qt.ClosedHandCursor))
-
self._start_hig = self._scroll_bar.value() + event.y()
-
elif idx < len(self._args.stab_ucells):
self.activate_idx(idx)
-
if self._fetched_cell:
self._args.stab_ucells[self._current_idx] = self._fetched_cell
self._fetched_cell = None
-
self._left_click = False
self._start_pt = None
-
elif event.button() == Qt.LeftButton and idx < len(self._args.stab_ucells) - 1:
self._left_click = True
self._start_pt = np.array((event.x(), event.y()))
-
self._fetched_cell = self._args.stab_ucells[self._current_idx]
self._args.stab_ucells[self._current_idx] = None
-
self._fetched_cell.raise_()
-
else:
self.activate_idx(None)
-
else:
self.activate_idx(None)
-
event.accept()
def mouseMoveEvent(self, event):
if self._double_click:
event.accept()
-
elif self._press_key == 1 and self._left_click:
color_dict = {"version": self._args.info_version_en, "site": self._args.info_main_site, "type": "set"}
color_dict["palettes"] = export_list([(self._fetched_cell.color_set, self._fetched_cell.hm_rule, self._fetched_cell.name, self._fetched_cell.desc, self._fetched_cell.cr_time, self._fetched_cell.grid_locations, self._fetched_cell.grid_assitlocs, self._fetched_cell.grid_list, self._fetched_cell.grid_values),])
color_path = os.sep.join((self._args.global_temp_dir.path(), "Rickrack_Set_{}.dps".format(abs(hash(str(color_dict))))))
-
with open(color_path, "w", encoding="utf-8") as f:
json.dump(color_dict, f, indent=4, ensure_ascii=False)
-
self._drag_file = True
-
drag = QDrag(self)
mimedata = QMimeData()
mimedata.setUrls([QUrl.fromLocalFile(color_path)])
@@ -677,28 +476,20 @@ def mouseMoveEvent(self, event):
drag.setPixmap(pixmap)
drag.setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2))
drag.exec_(Qt.CopyAction | Qt.MoveAction)
-
self._args.stab_ucells[self._current_idx] = self._fetched_cell
self._fetched_cell = None
-
self._left_click = False
self._start_pt = None
-
self._drag_file = False
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
-
self.update()
event.accept()
-
elif self._left_click:
point = (event.x(), event.y())
pl_wid_5 = self._pl_wid / 5
-
if isinstance(self._start_pt, np.ndarray) and np.sum((self._start_pt - point) ** 2) < pl_wid_5 ** 2:
- # fixed icon in small region.
event.ignore()
-
else:
x, y = point
x = x if x > pl_wid_5 else pl_wid_5
@@ -707,32 +498,22 @@ def mouseMoveEvent(self, event):
y = y if y < self.height() - pl_wid_5 else self.height() - pl_wid_5
x = int(x) - self._scroll_contents.x()
y = int(y) - self._scroll_contents.y()
-
self._start_pt = None
-
col = x // self._pl_wid
row = y // self._pl_wid
-
if col <= self._args.stab_column:
idx = self._args.stab_column * row + col
-
if idx < len(self._args.stab_ucells) - 1:
self._args.stab_ucells.pop(self._current_idx)
self._current_idx = idx
-
self._args.stab_ucells.insert(idx, None)
-
self._fetched_cell.setGeometry(x - self._pl_wid / 2, y - self._pl_wid / 2, self._pl_wid, self._pl_wid)
-
self.update()
event.accept()
-
elif self._start_hig != None:
self._scroll_bar.setValue(self._start_hig - event.y())
-
self.update()
event.accept()
-
else:
event.ignore()
@@ -740,18 +521,14 @@ def mouseReleaseEvent(self, event):
if self._start_hig:
self.setCursor(QCursor(Qt.ArrowCursor))
self._start_hig = None
-
if self._left_click:
if isinstance(self._fetched_cell, UnitCell):
self._args.stab_ucells[self._current_idx] = self._fetched_cell
-
self._fetched_cell = None
self._left_click = False
self._start_pt = None
-
self.update()
event.accept()
-
else:
event.ignore()
@@ -759,51 +536,37 @@ def mouseDoubleClickEvent(self, event):
if event.button() == Qt.LeftButton:
self._double_click = True
point = (event.x() - self._scroll_contents.x(), event.y() - self._scroll_contents.y())
-
col = point[0] // self._pl_wid
row = point[1] // self._pl_wid
-
if col <= self._args.stab_column:
idx = self._args.stab_column * row + col
-
if idx < len(self._args.stab_ucells):
self.activate_idx(idx)
-
if idx == len(self._args.stab_ucells) - 1:
self.attach_set()
-
else:
self.import_set()
-
else:
self.activate_idx(None)
-
else:
self.activate_idx(None)
-
self._double_click = False
event.accept()
-
else:
event.ignore()
def dragEnterEvent(self, event):
- # drag file out from depot.
if self._drag_file:
event.ignore()
return
-
try:
depot_file = event.mimeData().urls()[0].toLocalFile()
-
except Exception as err:
event.ignore()
return
-
if depot_file.split(".")[-1].lower() in ("dpc", "dps", "json", "txt", "aco", "ase", "gpl", "xml"):
self._drop_file = depot_file
event.accept()
-
else:
event.ignore()
@@ -811,603 +574,362 @@ def dropEvent(self, event):
if self._drop_file:
if self._drop_file.split(".")[-1].lower() in ("dpc", "json"):
self.ps_dropped.emit((self._drop_file, False))
-
else:
self.ps_appended.emit((self._drop_file, False))
-
self._drop_file = None
-
event.accept()
-
else:
event.ignore()
def resizeEvent(self, event):
if self._stab_column_wid:
wid = self.width()
-
stab_column = int(wid / self._stab_column_wid)
stab_column = 1 if stab_column < 1 else stab_column
-
if stab_column != self._args.stab_column:
self._args.modify_settings("stab_column", stab_column)
-
self.update()
-
event.ignore()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
+ def init_key(self):
+ self._press_key = 0
+ self._drag_file = False
+ self._drop_file = None
def initialize(self):
- """
- Initialize Depot from self._args.stab_ucells list.
- """
-
unit_cells = []
-
for cset in self._args.stab_ucells:
unit_cell = UnitCell(self._scroll_contents, self._args, *cset)
unit_cells.append(unit_cell)
-
self._scroll_grid_layout.addWidget(unit_cell)
-
empty_cell = UnitCell(self._scroll_contents, self._args)
unit_cells.append(empty_cell)
-
self._scroll_grid_layout.addWidget(empty_cell)
-
self._args.stab_ucells = unit_cells
self._current_idx = None
-
self.ps_history_backup.emit(True)
-
for unit_cell in self._args.stab_ucells:
if isinstance(unit_cell, UnitCell):
unit_cell._func_tr_()
unit_cell.update_text()
def activate_idx(self, idx):
- """
- Activate unit cell at idx and set current idx to idx.
- """
-
- # current idx is None if all unit cells are not selected.
- # current idx is a serial number in range len(self._args.stab_ucells) if any unit cell is selected.
- # firstly deactivate old unit cell at current idx.
if self._current_idx != None and isinstance(self._args.stab_ucells[self._current_idx], UnitCell):
self._args.stab_ucells[self._current_idx].activated = False
self._args.stab_ucells[self._current_idx].update()
-
- # then change current idx to given idx.
self._current_idx = idx
-
if self._current_idx != None:
self._current_idx = self._current_idx if self._current_idx > 0 else 0
self._current_idx = self._current_idx if self._current_idx < len(self._args.stab_ucells) -1 else len(self._args.stab_ucells) - 1
-
- # finally activate new unit cell at current idx.
if self._current_idx != None and isinstance(self._args.stab_ucells[self._current_idx], UnitCell):
self._args.stab_ucells[self._current_idx].activated = True
self._args.stab_ucells[self._current_idx].update()
-
upp_pos = self._scroll_contents.y() + self._args.stab_ucells[self._current_idx].y()
low_pos = self._scroll_contents.y() + self._args.stab_ucells[self._current_idx].y() + self._args.stab_ucells[self._current_idx].height()
-
if upp_pos <= 0:
self._scroll_bar.setValue(self._args.stab_ucells[self._current_idx].y())
-
elif low_pos >= self._scroll_area.height():
- # similar to the expression in func page_end.
- # please modify synchronously if necessary.
self._scroll_bar.setValue(self._args.stab_ucells[self._current_idx].y() + self._pl_wid - self._scroll_area.height())
-
status_idx = self._current_idx
-
if status_idx == None:
status_idx = 0
-
else:
status_idx = status_idx + 1
-
self.ps_status_changed.emit((self._tot_rows, self._args.stab_column, len(self._args.stab_ucells) - 1, status_idx))
-
# clone_cell into info window, thus can change the info dynamically. (recovered)
- # similar to set_context in update_select_idx in board.py.
if self._current_idx == None:
self._info.hide()
-
else:
self._info.clone_cell(self._args.stab_ucells[self._current_idx])
def move(self, shift_x, shift_y):
- """
- Select unit cell around current idx unit cell (leftward, rightward, uppward and downward).
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
if self._current_idx == None:
self.activate_idx(0)
-
elif shift_x < 0:
self.activate_idx(self._current_idx - 1)
-
elif shift_x > 0:
self.activate_idx(self._current_idx + 1)
-
elif shift_y < 0:
self.activate_idx(self._current_idx - self._args.stab_column)
-
elif shift_y > 0:
self.activate_idx(self._current_idx + self._args.stab_column)
def zoom(self, ratio):
- """
- Increase or decrease columns for display.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
stab_column = self._args.stab_column
-
if True: # self._args.rev_direct:
if ratio > 1:
stab_column = stab_column - 1
-
elif ratio < 1:
stab_column = stab_column + 1
-
else:
if ratio > 1:
stab_column = stab_column + 1
-
elif ratio < 1:
stab_column = stab_column - 1
-
self._args.modify_settings("stab_column", stab_column)
-
- # stab_column is changed with the changing of interface size. this code is reused.
self._stab_column_wid = None
-
self.update()
-
'''
- def home(self):
- """
- Locate current unit cell.
- """
+ def home(self):
if not self.isVisible():
return
-
if self._current_idx == None:
self._scroll_bar.setValue(0)
self.update()
-
else:
self.activate_idx(self._current_idx)
'''
def home(self):
- """
- Home scroll page.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
if self._scroll_bar.value() < self._pl_wid:
self.activate_idx(0)
-
else:
self._scroll_bar.setValue(0)
-
self.update()
def page_up(self):
- """
- Up scroll page.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
self._scroll_bar.setValue(self._scroll_bar.value() - self._scroll_area.height())
self.update()
def page_down(self):
- """
- Down scroll page.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
self._scroll_bar.setValue(self._scroll_bar.value() + self._scroll_area.height())
self.update()
def page_end(self):
- """
- End scroll page.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
- # similar to the expression in func activate_idx.
- # please modify synchronously if necessary.
if self._scroll_bar.value() > self._args.stab_ucells[len(self._args.stab_ucells) - 1].y() - self._scroll_area.height():
self.activate_idx(len(self._args.stab_ucells) - 1)
-
else:
self._scroll_bar.setValue(self._scroll_contents.height())
-
self.update()
def insert_set(self):
- """
- Insert current color set (combine attach_set and import_set funcs).
- """
-
if self._current_idx == len(self._args.stab_ucells) - 1:
self.attach_set()
-
else:
self.import_set()
def delete_set(self):
- """
- Delete current color set from depot.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
if self._current_idx == None or self._current_idx > len(self._args.stab_ucells) - 2:
return
-
if isinstance(self._args.stab_ucells[self._current_idx], UnitCell):
self._args.stab_ucells[self._current_idx].close()
self._args.stab_ucells.pop(self._current_idx)
-
self._args.stab_ucells[self._current_idx].activated = True
self.activate_idx(self._current_idx)
self.update()
def confirm_delete_set(self):
- """
- Act delete_set with confirmation.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
self.prompt(self._operation_warns[3], self.delete_set)
def link_set(self, link):
- """
- Link set with result.
-
- Args:
- link (bool): whether linked.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
if self._current_idx == None or self._current_idx > len(self._args.stab_ucells) - 2:
return
-
self._args.sys_link_colors[1] = bool(link)
self.ps_linked.emit(True)
def import_set(self, rev_import=False):
- """
- Import current color set into color wheel.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
if self._current_idx == None or self._current_idx > len(self._args.stab_ucells) - 2:
return
-
if isinstance(self._args.stab_ucells[self._current_idx], UnitCell):
self.activate_idx(self._current_idx)
-
if self._press_key in (2, 4) or rev_import:
self._args.stab_ucells[self._current_idx].update_colors([i.hsv for i in self._args.sys_color_set], self._args.hm_rule, self._args.sys_grid_locations, self._args.sys_grid_assitlocs, self._args.sys_grid_list, self._args.sys_grid_values)
-
if self._info.isVisible():
self._info.update_values()
-
elif self._press_key == 1:
self.attach_set(location_idx=self._current_idx)
-
else:
self._args.sys_color_set.recover(self._args.stab_ucells[self._current_idx].color_set)
self._args.hm_rule = str(self._args.stab_ucells[self._current_idx].hm_rule)
self._args.sys_grid_locations, self._args.sys_grid_assitlocs = norm_grid_locations(self._args.stab_ucells[self._current_idx].grid_locations, self._args.stab_ucells[self._current_idx].grid_assitlocs)
self._args.sys_grid_list = norm_grid_list(self._args.stab_ucells[self._current_idx].grid_list)
self._args.sys_grid_values = dict(self._args.stab_ucells[self._current_idx].grid_values)
-
self._args.sys_activated_assit_idx = -1
-
self._args.sys_assit_color_locs = [[None for j in self._args.sys_grid_assitlocs[i]] for i in range(5)]
-
self.ps_update.emit(True)
self.ps_history_backup.emit(True)
-
image_url, full_loc = check_image_desc(self._args.stab_ucells[self._current_idx].desc)
-
if image_url:
self.ps_open_image_url.emit((image_url, full_loc))
-
- # link and unlink.
if self._press_key == 2:
self.link_set(not self._args.sys_link_colors[1])
-
elif self._args.sys_link_colors[1]:
self.link_set(False)
def export_set(self):
- """
- Export current color set from depot.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
if self._current_idx == None or self._current_idx > len(self._args.stab_ucells) - 2:
return
-
if isinstance(self._args.stab_ucells[self._current_idx], UnitCell):
self.activate_idx(self._current_idx)
self.ps_export.emit(self._current_idx)
def detail_set(self):
- """
- Show info of color set (unit cell) at current idx.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
if self._current_idx == None or self._current_idx > len(self._args.stab_ucells) - 2:
return
-
if isinstance(self._args.stab_ucells[self._current_idx], UnitCell):
self.activate_idx(self._current_idx)
-
# self._info.clone_cell is completed by self.activate_idx above. (recovered)
# self._info.clone_cell(self._args.stab_ucells[self._current_idx])
self._info.show()
def attach_set(self, color_list=None, location_idx=-1):
- """
- Attach current color set from wheel or color list from file into depot.
- """
-
if not self.isVisible():
return
-
if isinstance(self._fetched_cell, UnitCell) or self._left_click:
return
-
- # Arg color_list with None or False represent add color set from wheel instead of discard.
if color_list:
hsv_set = tuple(color_list[0][i].hsv for i in range(5))
unit_cell = UnitCell(self._scroll_contents, self._args, hsv_set, color_list[1], color_list[2], color_list[3], color_list[4], color_list[5], color_list[6], color_list[7], color_list[8])
-
else:
hsv_set = tuple(self._args.sys_color_set[i].hsv for i in range(5))
unit_cell = UnitCell(self._scroll_contents, self._args, hsv_set, self._args.hm_rule, "", "", (time.time(), time.time()), self._args.sys_grid_locations, self._args.sys_grid_assitlocs, self._args.sys_grid_list, self._args.sys_grid_values)
-
self._scroll_grid_layout.addWidget(unit_cell)
-
- # normalize location_idx.
loc_idx = -1
if isinstance(location_idx, (int, np.int_)):
loc_idx = int(location_idx)
loc_idx = -1 if loc_idx < 0 else loc_idx
loc_idx = -1 if loc_idx > len(self._args.stab_ucells) - 2 else loc_idx
-
location_cell = self._args.stab_ucells[loc_idx]
location_cell.activated = False
-
unit_cell._func_tr_()
unit_cell.update_text()
unit_cell.activated = False
-
- # set geometry to prevent go to head when activate_idx() below.
unit_cell.setGeometry(location_cell.geometry())
-
total_len = len(self._args.stab_ucells)
self._args.stab_ucells = self._args.stab_ucells[:loc_idx] + [unit_cell,] + self._args.stab_ucells[loc_idx:]
-
self.update()
-
- #
- # add judge activate_list to prevent press_act error.
- # activate current index to update info.
self.activate_idx((total_len + loc_idx) % total_len)
def detail_state(self):
- """
- Esc refer to close self._info if it is visible in main window.
- """
-
return self._info.isVisible()
def hide_detail(self):
- """
- Hide the info window.
- Esc refer to close self._info if it is visible (return True) in main window.
- """
-
if self._info.isVisible():
self._info.hide()
-
return True
-
else:
return False
def clean_up(self):
- """
- Delete all unit cells except empty cell.
- """
-
for unit_cell in self._args.stab_ucells[:-1]:
if isinstance(unit_cell, UnitCell):
unit_cell.close()
-
self._args.stab_ucells = self._args.stab_ucells[-1:]
self._args.stab_ucells[0].activated = False
self._current_idx = None
-
self.update()
def update_index(self):
- """
- Link colors with cube table here.
- """
-
- # similar code segment in method self.import_set with self._press_key == 2.
if self._args.sys_link_colors[1] and isinstance(self._args.stab_ucells[self._current_idx], UnitCell) and self._current_idx < len(self._args.stab_ucells) - 1:
self._args.stab_ucells[self._current_idx].update_colors([i.hsv for i in self._args.sys_color_set], self._args.hm_rule, self._args.sys_grid_locations, self._args.sys_grid_assitlocs, self._args.sys_grid_list, self._args.sys_grid_values)
-
if self._info.isVisible():
self._info.update_values()
-
self.update()
def clipboard_in(self):
- """
- Load depot from clipboard.
- """
-
clipboard = QApplication.clipboard().mimeData()
-
if clipboard.hasUrls():
try:
depot_file = clipboard.urls()[0].toLocalFile()
-
except Exception as err:
return
-
if depot_file.split(".")[-1].lower() in ("dpc", "json") and os.path.isfile(depot_file):
self.ps_dropped.emit((depot_file, False))
-
elif depot_file.split(".")[-1].lower() in ("dps", "json", "txt", "aco", "ase", "gpl", "xml") and os.path.isfile(depot_file):
self.ps_appended.emit((depot_file, False))
-
else:
try:
color_dict = json.loads(clipboard.text(), encoding="utf-8")
-
except Exception as err:
return
-
if isinstance(color_dict, dict) and "type" in color_dict and "palettes" in color_dict:
if color_dict["type"] == "depot":
self.ps_dropped.emit((color_dict, True))
-
elif color_dict["type"] == "set":
self.ps_appended.emit((color_dict, True))
def clipboard_cur(self, ctp):
- """
- Set the rgb, hsv or hec (hex code) of current color set as the clipboard data by shortcut Ctrl + r, h or x.
- """
-
def _func_():
data_lst = []
-
if self._current_idx == None or self._args.stab_ucells[self._current_idx] == None or self._current_idx >= len(self._args.stab_ucells) - 1:
for i in (2, 1, 0, 3, 4):
color = self._args.sys_color_set[i].getti(ctp)
-
if ctp == "hec":
color = self._args.hec_prefix[0] + str(color) + self._args.hec_prefix[1]
-
else:
color = self._args.rgb_prefix[1].join([self._args.r_prefix[0] + str(color[coi]) + self._args.r_prefix[1] for coi in range(3)])
color = self._args.rgb_prefix[0] + color + self._args.rgb_prefix[2]
-
data_lst.append(color)
-
else:
for i in (2, 1, 0, 3, 4):
color = getattr(self._args.stab_ucells[self._current_idx].color_set[i], ctp)
-
if ctp == "hec":
color = self._args.hec_prefix[0] + str(color) + self._args.hec_prefix[1]
-
else:
color = self._args.rgb_prefix[1].join([self._args.r_prefix[0] + str(color[coi]) + self._args.r_prefix[1] for coi in range(3)])
color = self._args.rgb_prefix[0] + color + self._args.rgb_prefix[2]
-
data_lst.append(color)
-
data = self._args.lst_prefix[1].join(data_lst)
data = self._args.lst_prefix[0] + data + self._args.lst_prefix[2]
-
mimedata = QMimeData()
mimedata.setText(data)
-
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
-
return _func_
def update_all(self):
- """
- Update all unit cells and self.
- """
-
for unit_cell in self._args.stab_ucells:
if isinstance(unit_cell, UnitCell):
unit_cell.update()
-
self.update()
def prompt(self, text, accept_action):
@@ -1415,112 +937,65 @@ def prompt(self, text, accept_action):
box.setWindowTitle(self._operation_warns[0])
box.setText(text)
box.setIcon(QMessageBox.Warning)
-
box.addButton(self._operation_warns[1], QMessageBox.AcceptRole)
box.addButton(self._operation_warns[2], QMessageBox.RejectRole)
-
if box.exec_() == 0:
accept_action()
- # ---------- ---------- ---------- Menu ---------- ---------- ---------- #
-
def create_menu(self):
- """
- Create a right clicked menu.
- """
-
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.show_menu)
-
self._menu = QMenu(self)
-
- # _translate("Depot", "Undo"), # 0
- # _translate("Depot", "Redo"), # 1
self._action_undo = QAction(self)
self._action_undo.triggered.connect(lambda: self.ps_undo.emit(True))
self._menu.addAction(self._action_undo)
-
self._action_redo = QAction(self)
self._action_redo.triggered.connect(lambda: self.ps_undo.emit(False))
self._menu.addAction(self._action_redo)
-
- # _translate("Depot", "Paste"), # 5
self._action_paste = QAction(self)
self._action_paste.triggered.connect(self.clipboard_in)
self._menu.addAction(self._action_paste)
-
- # _translate("Depot", "Copy RGB"), # 2
- # _translate("Depot", "Copy HSV"), # 3
- # _translate("Depot", "Copy Hex Code"), # 4
self._action_copy_rgb = QAction(self)
self._action_copy_rgb.triggered.connect(self.clipboard_cur("rgb"))
self._menu.addAction(self._action_copy_rgb)
-
self._action_copy_hsv = QAction(self)
self._action_copy_hsv.triggered.connect(self.clipboard_cur("hsv"))
self._menu.addAction(self._action_copy_hsv)
-
self._action_copy_hec = QAction(self)
self._action_copy_hec.triggered.connect(self.clipboard_cur("hec"))
self._menu.addAction(self._action_copy_hec)
-
- # _translate("Depot", "Zoom In"), # 6
- # _translate("Depot", "Zoom Out"), # 7
self._action_zoom_in = QAction(self)
self._action_zoom_in.triggered.connect(lambda: self.zoom(self._args.zoom_step))
self._menu.addAction(self._action_zoom_in)
-
self._action_zoom_out = QAction(self)
self._action_zoom_out.triggered.connect(lambda: self.zoom(1 / self._args.zoom_step))
self._menu.addAction(self._action_zoom_out)
-
- # _translate("Depot", "Replace Color (DK)"), # 8
- # _translate("Depot", "Rev-Replace Color (Alt+DK)"), # 16
self._action_import = QAction(self)
self._action_import.triggered.connect(self.import_set)
self._menu.addAction(self._action_import)
-
self._action_rev_import = QAction(self)
self._action_rev_import.triggered.connect(lambda: self.import_set(rev_import=True))
self._menu.addAction(self._action_rev_import)
-
- # _translate("Depot", "Export Color Set"), # 9
self._action_export = QAction(self)
self._action_export.triggered.connect(self.export_set)
self._menu.addAction(self._action_export)
-
- # _translate("Depot", "Insert Color Set (Shift+DK)"), # 10
self._action_attach_beside = QAction(self)
self._action_attach_beside.triggered.connect(lambda: self.attach_set(location_idx=self._current_idx))
self._menu.addAction(self._action_attach_beside)
-
- # _translate("Depot", "Append Color Set"), # 11
self._action_attach_append = QAction(self)
self._action_attach_append.triggered.connect(self.attach_set)
self._menu.addAction(self._action_attach_append)
-
- # _translate("Depot", "Delete Color Set"), # 12
self._action_delete = QAction(self)
self._action_delete.triggered.connect(self.delete_set)
self._menu.addAction(self._action_delete)
-
- # _translate("Depot", "Link with Result (Ctrl+DK)"), # 14
- # _translate("Depot", "Un-Link with Result (Ctrl+DK)"), # 15
self._action_link = QAction(self)
self._action_link.triggered.connect(lambda: self.link_set(not self._args.sys_link_colors[1]))
self._menu.addAction(self._action_link)
-
- # _translate("Depot", "Show Detail"), # 13
self._action_detail = QAction(self)
self._action_detail.triggered.connect(self.detail_set)
self._menu.addAction(self._action_detail)
def show_menu(self):
- """
- Show the right clicked menu.
- """
-
- # normal actions delete.
if self._current_idx == None or self._args.stab_ucells[self._current_idx] == None or self._current_idx >= len(self._args.stab_ucells) - 1:
self._action_copy_rgb.setVisible(False)
self._action_copy_hsv.setVisible(False)
@@ -1532,7 +1007,6 @@ def show_menu(self):
self._action_detail.setVisible(False)
self._action_attach_beside.setVisible(False)
self._action_link.setVisible(False)
-
else:
self._action_copy_rgb.setVisible(True)
self._action_copy_hsv.setVisible(True)
@@ -1544,205 +1018,131 @@ def show_menu(self):
self._action_detail.setVisible(True)
self._action_attach_beside.setVisible(True)
self._action_link.setVisible(True)
-
self._menu.exec_(QCursor.pos())
- # ---------- ---------- ---------- Shortcut ---------- ---------- ---------- #
-
def update_skey(self):
- """
- Set depot shortcuts.
- """
-
for skey in self._args.shortcut_keymaps[39]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.delete_set)
-
for skey in self._args.shortcut_keymaps[40]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.confirm_delete_set)
-
for skey in self._args.shortcut_keymaps[38]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.insert_set)
-
for skey in self._args.shortcut_keymaps[41]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.detail_set)
-
for skey in self._args.shortcut_keymaps[20]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_cur("rgb"))
-
for skey in self._args.shortcut_keymaps[21]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_cur("hsv"))
-
for skey in self._args.shortcut_keymaps[22]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_cur("hec"))
-
for skey in self._args.shortcut_keymaps[45]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_cur("hec"))
-
for skey in self._args.shortcut_keymaps[46]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_in)
-
for skey in self._args.shortcut_keymaps[36]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.page_up)
-
for skey in self._args.shortcut_keymaps[37]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.page_down)
-
for skey in self._args.shortcut_keymaps[35]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.page_end)
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_action_text(self):
- # _translate("Depot", "Undo"), # 0
- # _translate("Depot", "Redo"), # 1
self._action_undo.setText(self._action_descs[0])
self._action_redo.setText(self._action_descs[1])
-
- # _translate("Depot", "Copy RGB"), # 2
- # _translate("Depot", "Copy HSV"), # 3
- # _translate("Depot", "Copy Hex Code"), # 4
self._action_copy_rgb.setText(self._action_descs[2])
self._action_copy_hsv.setText(self._action_descs[3])
self._action_copy_hec.setText(self._action_descs[4])
-
- # _translate("Depot", "Paste"), # 5
self._action_paste.setText(self._action_descs[5])
-
- # _translate("Depot", "Zoom In"), # 6
- # _translate("Depot", "Zoom Out"), # 7
self._action_zoom_in.setText(self._action_descs[6])
self._action_zoom_out.setText(self._action_descs[7])
-
- # _translate("Depot", "Replace Color (DK)"), # 8
- # _translate("Depot", "Rev-Replace Color (Alt+DK)"), # 16
self._action_import.setText(self._action_descs[8])
self._action_rev_import.setText(self._action_descs[16])
-
- # _translate("Depot", "Export Color Set"), # 9
self._action_export.setText(self._action_descs[9])
-
- # _translate("Depot", "Insert Color Set (Shift+DK)"), # 10
self._action_attach_beside.setText(self._action_descs[10])
-
- # _translate("Depot", "Append Color Set"), # 11
self._action_attach_append.setText(self._action_descs[11])
-
- # _translate("Depot", "Delete Color Set"), # 12
self._action_delete.setText(self._action_descs[12])
-
- # _translate("Depot", "Show Detail"), # 13
self._action_detail.setText(self._action_descs[13])
-
- # _translate("Depot", "Link with Result (Ctrl+DK)"), # 14
- # _translate("Depot", "Un-Link with Result (Ctrl+DK)"), # 15
if self._args.sys_link_colors[1]:
self._action_link.setText(self._action_descs[15])
-
else:
self._action_link.setText(self._action_descs[14])
def update_text(self):
self.update_action_text()
-
self._info._func_tr_()
self._info.update_text()
-
for unit_cell in self._args.stab_ucells:
if isinstance(unit_cell, UnitCell):
unit_cell._func_tr_()
@@ -1750,7 +1150,6 @@ def update_text(self):
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._action_descs = (
_translate("Wheel", "Undo"), # 0
_translate("Wheel", "Redo"), # 1
@@ -1770,7 +1169,6 @@ def _func_tr_(self):
_translate("Depot", "Un-Link with Result (Ctrl+DK)"), # 15
_translate("Depot", "Rev-Replace Color (Alt+DK)"), # 16
)
-
self._operation_warns = (
_translate("Info", "Warning"),
_translate("Info", "OK"),
diff --git a/src/main/python/wgets/general.py b/src/main/python/wgets/general.py
index c364f40..e65a774 100644
--- a/src/main/python/wgets/general.py
+++ b/src/main/python/wgets/general.py
@@ -18,70 +18,37 @@
class NoWheelSlider(QSlider):
- """
- Slider without responding wheel event.
- """
-
def __init__(self, wget):
- """
- Init operation.
- """
-
super().__init__(wget)
def wheelEvent(self, event):
event.ignore()
-
class NoWheelDoubleSpinBox(QDoubleSpinBox):
- """
- DoubleSpinBox without responding wheel event.
- """
-
def __init__(self, wget):
- """
- Init operation.
- """
-
super().__init__(wget)
def wheelEvent(self, event):
event.ignore()
-
class SlideText(QWidget):
- """
- Box with a text label, a spin box and a slider.
- """
-
ps_value_changed = pyqtSignal(float)
def __init__(self, wget, num_range=(0.0, 1.0), maxlen=100000, interval=10000, step=1000, decimals=2, default_value=0.0):
- """
- Init operation.
- """
-
super().__init__(wget)
-
- # load args.
self._num_range = tuple([float(min(num_range)), float(max(num_range))])
self._maxlen = int(maxlen)
self._interval = int(interval)
self._step = int(step)
self._decimals = int(decimals)
self._value = float(default_value)
-
self._emitting = True
-
- # init qt args.
local_grid_layout = QGridLayout(self)
local_grid_layout.setContentsMargins(0, 0, 0, 0)
local_grid_layout.setHorizontalSpacing(2)
local_grid_layout.setVerticalSpacing(9)
-
self.lab_local = QLabel(self)
local_grid_layout.addWidget(self.lab_local, 0, 0, 1, 1)
-
self.dsp_local = NoWheelDoubleSpinBox(self)
self.dsp_local.setMinimum(self._num_range[0])
self.dsp_local.setMaximum(self._num_range[1])
@@ -92,10 +59,8 @@ def __init__(self, wget, num_range=(0.0, 1.0), maxlen=100000, interval=10000, st
self.dsp_local.setButtonSymbols(QDoubleSpinBox.NoButtons)
local_grid_layout.addWidget(self.dsp_local, 0, 1, 1, 1)
self.dsp_local.valueChanged.connect(self.value_changed_from_dsp)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
local_grid_layout.addItem(spacer, 0, 2, 1, 1)
-
self.sdr_local = NoWheelSlider(self)
self.sdr_local.setMinimum(0)
self.sdr_local.setMaximum(self._maxlen)
@@ -108,76 +73,39 @@ def __init__(self, wget, num_range=(0.0, 1.0), maxlen=100000, interval=10000, st
local_grid_layout.addWidget(self.sdr_local, 1, 0, 1, 3)
self.sdr_local.valueChanged.connect(self.value_changed_from_sdr)
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def norm_dsp_value(self, dsp_value):
- """
- Normalize value for dsp_local.
- """
-
norm_value = float(dsp_value)
norm_value = self._num_range[0] if norm_value < self._num_range[0] else norm_value
norm_value = self._num_range[1] if norm_value > self._num_range[1] else norm_value
-
return norm_value
def norm_sdr_value(self, sdr_value):
- """
- Normalize value for sdr_local.
- """
-
norm_value = int(sdr_value)
norm_value = 0 if norm_value < 0 else norm_value
norm_value = self._maxlen if norm_value > self._maxlen else norm_value
-
return norm_value
def value_dsp_to_sdr(self, dsp_value):
- """
- Arg sdr_value from self._num_range[0] to self._num_range[1].
- """
-
norm_value = self.norm_dsp_value(dsp_value)
-
return int((norm_value - self._num_range[0]) / (self._num_range[1] - self._num_range[0]) * self._maxlen)
def value_sdr_to_dsp(self, sdr_value):
- """
- Arg sdr_value from 0 to self._maxlen.
- """
-
norm_value = self.norm_sdr_value(sdr_value)
-
return float((norm_value / self._maxlen) * (self._num_range[1] - self._num_range[0]) + self._num_range[0])
def set_disabled(self, state):
- """
- Set state for tools.
- """
-
self.dsp_local.setDisabled(bool(state))
self.sdr_local.setDisabled(bool(state))
def set_value(self, value):
- """
- Set value for SlideText.
- """
-
norm_value = self.norm_dsp_value(value)
self._emitting = False
-
self._value = norm_value
-
self.dsp_local.setValue(self._value)
self.sdr_local.setValue(self.value_dsp_to_sdr(self._value))
-
self._emitting = True
def get_value(self):
- """
- Get value for SlideText.
- """
-
return self._value
def set_text(self, text):
@@ -186,112 +114,76 @@ def set_text(self, text):
def set_num_range(self, num_range):
sdr_value = self.value_dsp_to_sdr(self._value)
self._emitting = False
-
self._num_range = tuple([float(min(num_range)), float(max(num_range))])
self.dsp_local.setMinimum(self._num_range[0])
self.dsp_local.setMaximum(self._num_range[1])
self.dsp_local.setSingleStep(self._step * 1.0 / self._maxlen * (self._num_range[1] - self._num_range[0]))
-
self._value = self.value_sdr_to_dsp(sdr_value)
self.dsp_local.setValue(self._value)
-
self._emitting = True
def get_num_range(self):
return self._num_range
def value_changed_from_dsp(self, value):
- """
- Change dsp_local value.
- """
-
if value != self._value:
self._value = self.norm_dsp_value(value)
self.sdr_local.setValue(self.value_dsp_to_sdr(self._value))
-
if self._emitting:
self.ps_value_changed.emit(self._value)
def value_changed_from_sdr(self, value):
- """
- Change sdr_local value.
- """
-
if value != self.value_dsp_to_sdr(self._value):
self._value = self.value_sdr_to_dsp(value)
self.dsp_local.setValue(self._value)
-
if self._emitting:
self.ps_value_changed.emit(self._value)
-
class RGBHSVCkb(QWidget):
- """
- Box with a R, G, B, H, S, V ckeckboxes.
- """
-
ps_value_changed = pyqtSignal(tuple)
def __init__(self, wget, default_values=[], oneline_mode=True):
- """
- Init operation.
- """
-
super().__init__(wget)
-
- # load args.
self._avi_values = ("r", "g", "b", "h", "s", "v")
self._values = []
self._prefix_text = ""
-
self._emitting = True
-
if default_values and isinstance(default_values, (tuple, list)):
for vl in default_values:
if str(vl).lower() in self._avi_values:
self._values.append(str(vl).lower())
-
self._oneline_mode = bool(oneline_mode)
-
- # init qt args.
local_grid_layout = QGridLayout(self)
local_grid_layout.setContentsMargins(0, 0, 0, 0)
local_grid_layout.setHorizontalSpacing(2)
local_grid_layout.setVerticalSpacing(9)
-
self.lab_link = QLabel(self)
local_grid_layout.addWidget(self.lab_link, 0, 0, 1, 3)
-
self.ckb_r = QCheckBox(self)
self.ckb_r.setText("R")
self.ckb_r.setChecked("r" in self._values)
local_grid_layout.addWidget(self.ckb_r, 1, 0, 1, 1)
self.ckb_r.stateChanged.connect(self.set_value_from_ckb("r"))
-
self.ckb_g = QCheckBox(self)
self.ckb_g.setText("G")
self.ckb_g.setChecked("g" in self._values)
local_grid_layout.addWidget(self.ckb_g, 1, 1, 1, 1)
self.ckb_g.stateChanged.connect(self.set_value_from_ckb("g"))
-
self.ckb_b = QCheckBox(self)
self.ckb_b.setText("B")
self.ckb_b.setChecked("b" in self._values)
local_grid_layout.addWidget(self.ckb_b, 1, 2, 1, 1)
self.ckb_b.stateChanged.connect(self.set_value_from_ckb("b"))
-
self.ckb_h = QCheckBox(self)
self.ckb_h.setText("H")
self.ckb_h.setChecked("h" in self._values)
local_grid_layout.addWidget(self.ckb_h, 2, 0, 1, 1)
self.ckb_h.stateChanged.connect(self.set_value_from_ckb("h"))
-
self.ckb_s = QCheckBox(self)
self.ckb_s.setText("S")
self.ckb_s.setChecked("s" in self._values)
local_grid_layout.addWidget(self.ckb_s, 2, 1, 1, 1)
self.ckb_s.stateChanged.connect(self.set_value_from_ckb("s"))
-
self.ckb_v = QCheckBox(self)
self.ckb_v.setText("V")
self.ckb_v.setChecked("v" in self._values)
@@ -299,97 +191,60 @@ def __init__(self, wget, default_values=[], oneline_mode=True):
self.ckb_v.stateChanged.connect(self.set_value_from_ckb("v"))
def inner_set_value(self, name, state):
- """
- Inner func for set value.
-
- Args:
- name (str): "r", "g", "b", "h", "s" or "v".
- state (bool): box is checked or unchecked.
- """
-
norm_name = str(name).lower()
-
if norm_name in self._avi_values:
if state:
if self._oneline_mode:
changed_values = []
-
if norm_name in self._avi_values[:3]:
for vl in self._values:
if vl in self._avi_values[:3]:
changed_values.append(vl)
-
else:
for vl in self._values:
if vl in self._avi_values[3:]:
changed_values.append(vl)
-
self._values = changed_values
-
else:
self._values = []
-
if norm_name not in self._values:
self._values.append(norm_name)
-
else:
changed_values = []
-
for vl in self._values:
if vl != norm_name:
changed_values.append(vl)
-
- """
- if not changed_values:
- changed_values.append(norm_name)
- """
-
self._values = changed_values
-
- # sort the sequence.
if len(self._values) > 1:
changed_values = []
-
for vl in self._avi_values:
if vl in self._values:
changed_values.append(vl)
-
self._values = changed_values
-
- # check and uncheck the boxes.
for vl in self._avi_values:
ckb = getattr(self, "ckb_{}".format(vl))
-
if vl in self._values:
if not ckb.isChecked():
ckb.setChecked(True)
-
else:
if ckb.isChecked():
ckb.setChecked(False)
-
- # set label text.
if self._values:
self.lab_link.setText(self._prefix_text[1] + " ".join([x.upper() for x in self._values]))
-
else:
self.lab_link.setText(self._prefix_text[0])
def set_values(self, values):
self._emitting = False
-
self._values = tuple(values)
self.inner_set_value("", True)
-
self._emitting = True
def set_value_from_ckb(self, value):
def _func_(state):
self.inner_set_value(value, state)
-
if self._values and self._emitting:
self.ps_value_changed.emit(tuple(self._values))
-
return _func_
def get_values(self):
@@ -398,12 +253,9 @@ def get_values(self):
def set_prefix_text(self, text):
if isinstance(text, (tuple, list)) and len(text) > 1:
self._prefix_text = (str(text[0]), str(text[1]))
-
else:
self._prefix_text = (str(text), str(text))
-
if self._values:
self.lab_link.setText(self._prefix_text[1] + " ".join([x.upper() for x in self._values]))
-
else:
self.lab_link.setText(self._prefix_text[0])
diff --git a/src/main/python/wgets/image.py b/src/main/python/wgets/image.py
index 7a0fd77..b761bb3 100644
--- a/src/main/python/wgets/image.py
+++ b/src/main/python/wgets/image.py
@@ -30,10 +30,6 @@
class Image(QWidget):
- """
- Image object based on QWidget. Init a image pannel in workarea.
- """
-
ps_color_changed = pyqtSignal(bool)
ps_image_changed = pyqtSignal(bool)
ps_status_changed = pyqtSignal(tuple)
@@ -44,364 +40,244 @@ class Image(QWidget):
ps_undo = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init Image pannel.
- """
-
super().__init__(wget)
-
- # set name ids.
wget.setProperty("class", "WorkArea")
-
- # load args.
self._args = args
self._categories = set()
- self._drop_image = None
self._start_pt = None
self._enhance_lock = False
self._home_image = False
- self._press_key = 0
self._croping_img = False
self._locating_img = False
self._resized_img_pos = None
self._locating_colors = False
self._connected_keymaps = {}
-
- # load translations.
+ self.init_key()
self._func_tr_()
-
- # init qt args.
self.setFocusPolicy(Qt.StrongFocus)
self.setAcceptDrops(True)
-
self._tip_label = QLabel(self)
self._tip_label.setWordWrap(True)
-
self._loading_bar = QProgressBar(self)
self._loading_bar.setTextVisible(False)
self._loading_bar.setMaximum(100)
self._loading_bar.setValue(0)
-
self._ico = None
self.init_icon()
self._ico_label = QLabel(self)
-
self.image3c = Image3C(self._args.global_temp_dir)
self.image3c.ps_describe.connect(self.update_loading_label)
self.image3c.ps_proceses.connect(self.update_loading_bar)
self.image3c.ps_finished.connect(self.loading_finished)
self.image3c.ps_enhanced.connect(self.enhance_finished)
self.image3c.ps_extracts.connect(self.extract_finished)
-
- # outer circles.
self._outer_circles = None
-
- # shortcut is updated by _setup_skey in main.py.
# self.update_skey()
-
self.create_menu()
self.update_action_text()
def paintEvent(self, event):
- # norm assit point index.
if False: # self._args.sys_activated_assit_idx > len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]):
self._args.sys_activated_assit_idx = -1
self.ps_color_changed()
-
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setRenderHint(QPainter.TextAntialiasing, True)
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
-
if not self.image3c.img_data:
self._loading_bar.hide()
self._ico_label.hide()
self._tip_label.show()
-
- painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid, Qt.PenStyle(Qt.DashLine)))
- painter.setBrush(QColor(*self._args.wheel_ed_color))
-
+ alpha = 255 if self._args.style_id < 5 else 120
+ painter.setPen(QPen(QColor(*self._args.wheel_ed_color), self._args.wheel_ed_wid, Qt.PenStyle(Qt.DashLine)))
+ painter.setBrush(QColor(*self._args.negative_color, alpha))
self._tip_box = (self.width() * 0.2, self.height() * 0.2, self.width() * 0.6, self.height() * 0.6)
radius = int(min(self.width() * 0.1, self.height() * 0.1))
painter.drawRoundedRect(*self._tip_box, radius, radius)
-
self._tip_label.setGeometry(QRect(*self._tip_box))
-
self._tip_label.setText(self._open_descs[0])
self._tip_label.setAlignment(Qt.AlignCenter)
-
elif self._args.sys_category * 10 + self._args.sys_channel not in self._categories:
self._loading_bar.show()
self._ico_label.show()
self._tip_label.show()
-
bar_wid = int(self.width() * 0.8)
bar_hig = int(self.height() * 0.1)
-
self._loading_bar.setGeometry((self.width() - bar_wid) / 2, self.height() * 0.88, bar_wid, bar_hig)
self._tip_label.setGeometry((self.width() - bar_wid) / 2, self.height() * 0.76, bar_wid, bar_hig)
-
img_wid = int(min(self.width() * 0.8, self.height() * 0.6))
-
- resized_pix = QPixmap.fromImage(self._ico)
- resized_pix.setDevicePixelRatio(self._ico.width() / img_wid)
-
+ resized_pix = self._ico.scaled(img_wid * self.devicePixelRatioF(), img_wid * self.devicePixelRatioF(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
+ resized_pix = QPixmap.fromImage(resized_pix)
+ resized_pix.setDevicePixelRatio(self.devicePixelRatioF())
self._ico_label.setPixmap(resized_pix)
self._ico_label.setGeometry((self.width() - img_wid) / 2, (self.height() * 0.76 - img_wid) / 2, img_wid, img_wid)
-
else:
self._loading_bar.hide()
self._ico_label.hide()
self._tip_label.hide()
-
if not self.image3c.display:
self.image3c.load_image(self._args.sys_category, self._args.sys_channel)
-
else:
if not isinstance(self._resized_img_pos, np.ndarray):
self.home()
self._home_image = False
-
- # display resized image as background.
self._resized_img_pos[0] = int(self.width() - 2 if self._resized_img_pos[0] > self.width() - 2 else self._resized_img_pos[0])
self._resized_img_pos[1] = int(self.height() - 2 if self._resized_img_pos[1] > self.height() - 2 else self._resized_img_pos[1])
-
if self._resized_img_pos[0] < 2 - self._resized_img_pos[2]:
self._resized_img_pos[0] = int(2 - self._resized_img_pos[2])
-
if self._resized_img_pos[1] < 2 - self._resized_img_pos[3]:
self._resized_img_pos[1] = int(2 - self._resized_img_pos[3])
-
- # aspect ratio mode: IgnoreAspectRatio, KeepAspectRatio and KeepAspectRatioByExpanding.
resized_pix = QPixmap.fromImage(self.image3c.display)
resized_pix.setDevicePixelRatio(self.image3c.display.width() / self._resized_img_pos[2])
-
painter.drawPixmap(*self._resized_img_pos, resized_pix)
-
- # display locating circles.
idx_seq = list(range(5))
idx_seq = idx_seq[self._args.sys_activated_idx + 1: ] + idx_seq[: self._args.sys_activated_idx + 1]
-
for idx in idx_seq:
- # main points.
if self._args.sys_color_locs[idx]:
pt_xy = np.array((self._args.sys_color_locs[idx][0] * self._resized_img_pos[2] + self._resized_img_pos[0], self._args.sys_color_locs[idx][1] * self._resized_img_pos[3] + self._resized_img_pos[1]), dtype=int)
pt_rgb = self._args.sys_color_set[idx].rgb
-
else:
continue
-
- # assit sequence. this code is reused in four places.
assit_idx_seq = list(range(len(self._args.sys_grid_assitlocs[idx])))
if idx == self._args.sys_activated_idx and self._args.sys_activated_assit_idx >= 0:
assit_idx_seq = assit_idx_seq[self._args.sys_activated_assit_idx + 1: ] + assit_idx_seq[: self._args.sys_activated_assit_idx + 1]
-
- # assit points.
for assit_idx in assit_idx_seq:
if self._args.sys_assit_color_locs[idx][assit_idx]:
assit_pt_xy = np.array((self._args.sys_assit_color_locs[idx][assit_idx][0] * self._resized_img_pos[2] + self._resized_img_pos[0], self._args.sys_assit_color_locs[idx][assit_idx][1] * self._resized_img_pos[3] + self._resized_img_pos[1]), dtype=int)
assit_pt_rgb = gen_assit_color(self._args.sys_color_set[idx], *self._args.sys_grid_assitlocs[idx][assit_idx][2:6]).rgb
-
pt_box = get_outer_box(assit_pt_xy, self._args.circle_dist)
assit_frame_color = (0, 0, 0)
-
if self._press_key == 3:
painter.setBrush(QBrush(Qt.NoBrush))
-
else:
if idx == self._args.sys_activated_idx and assit_idx == self._args.sys_activated_assit_idx:
assit_frame_color = self._args.positive_color
-
else:
assit_frame_color = self._args.negative_color
-
painter.setBrush(QColor(*assit_pt_rgb))
-
painter.setPen(QPen(QColor(*assit_frame_color), self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
painter.drawLine(QPoint(*pt_xy), QPoint(*assit_pt_xy))
-
painter.setPen(QPen(QColor(*assit_frame_color), self._args.negative_wid))
painter.drawEllipse(*pt_box)
-
- # relative (move-able) or ref (un-move-able) point tag. assit dot box.
if not self._args.sys_grid_assitlocs[idx][assit_idx][5]:
dot_box = get_outer_box(assit_pt_xy, self._args.negative_wid * 2 / 3)
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QBrush(QColor(*assit_frame_color)))
painter.drawEllipse(*dot_box)
-
- # main points.
if self._args.sys_color_locs[idx]:
pt_xy = np.array((self._args.sys_color_locs[idx][0] * self._resized_img_pos[2] + self._resized_img_pos[0], self._args.sys_color_locs[idx][1] * self._resized_img_pos[3] + self._resized_img_pos[1]), dtype=int)
pt_rgb = self._args.sys_color_set[idx].rgb
-
pt_box = get_outer_box(pt_xy, self._args.dep_circle_dist_wid)
-
if self._press_key == 3:
painter.setPen(QPen(Qt.white, self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
painter.setBrush(QBrush(Qt.NoBrush))
-
else:
if idx == self._args.sys_activated_idx:
painter.setPen(QPen(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2]), self._args.positive_wid))
painter.setBrush(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2], 128))
-
else:
painter.setPen(QPen(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2], 128), self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
painter.setBrush(QColor(255 - pt_rgb[0], 255 - pt_rgb[1], 255 - pt_rgb[2], 64))
-
painter.drawEllipse(*pt_box)
-
pt_box = get_outer_box(pt_xy, self._args.circle_dist)
-
if self._press_key == 3:
painter.setPen(QPen(Qt.black, self._args.negative_wid))
painter.setBrush(QBrush(Qt.NoBrush))
-
else:
if idx == self._args.sys_activated_idx:
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
-
else:
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid))
-
painter.setBrush(QColor(*pt_rgb))
-
painter.drawEllipse(*pt_box)
-
if isinstance(self._croping_img, tuple):
sted_croping = self.get_sorted_croping()
-
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QColor(255, 255, 255, 160))
-
self.draw_twopt_rect(painter, 0, 0, sted_croping[0], self.height())
self.draw_twopt_rect(painter, sted_croping[2], 0, self.width(), self.height())
self.draw_twopt_rect(painter, sted_croping[0], 0, sted_croping[2], sted_croping[1])
self.draw_twopt_rect(painter, sted_croping[0], sted_croping[3], sted_croping[2], self.height())
-
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
-
painter.drawLine(QPoint(sted_croping[0] + self.x(), 0), QPoint(sted_croping[0] + self.x(), self.height()))
painter.drawLine(QPoint(0, sted_croping[1] + self.y()), QPoint(self.width(), sted_croping[1] + self.y()))
-
painter.drawLine(QPoint(sted_croping[2] + self.x(), 0), QPoint(sted_croping[2] + self.x(), self.height()))
painter.drawLine(QPoint(0, sted_croping[3] + self.y()), QPoint(self.width(), sted_croping[3] + self.y()))
-
self.ps_status_changed.emit((self.image3c.rgb_data.shape[1], self.image3c.rgb_data.shape[0], "{:.1f}".format((self._croping_img[2] - self._resized_img_pos[0]) * 100 / self._resized_img_pos[2]), "{:.1f}".format((self._croping_img[3] - self._resized_img_pos[1]) * 100 / self._resized_img_pos[3])))
-
elif isinstance(self._locating_img, tuple):
sted_locating = self.get_sorted_locating()
-
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QColor(255, 255, 255, 160))
-
painter.drawRect(0, 0, self.width(), self.height())
-
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
-
painter.drawLine(QPoint(sted_locating[0] + self.x(), 0), QPoint(sted_locating[0] + self.x(), self.height()))
painter.drawLine(QPoint(0, sted_locating[1] + self.y()), QPoint(self.width(), sted_locating[1] + self.y()))
-
self.ps_status_changed.emit((self.image3c.rgb_data.shape[1], self.image3c.rgb_data.shape[0], "{:.1f}".format((self._locating_img[0] - self._resized_img_pos[0]) * 100 / self._resized_img_pos[2]), "{:.1f}".format((self._locating_img[1] - self._resized_img_pos[1]) * 100 / self._resized_img_pos[3])))
-
elif self._croping_img or self._locating_img:
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QColor(255, 255, 255, 160))
-
painter.drawRect(0, 0, self.width(), self.height())
-
- elif self._args.sys_color_locs[self._args.sys_activated_idx]:
- self.ps_status_changed.emit((self.image3c.rgb_data.shape[1], self.image3c.rgb_data.shape[0], "{:.1f}".format(self._args.sys_color_locs[self._args.sys_activated_idx][0] * 100), "{:.1f}".format(self._args.sys_color_locs[self._args.sys_activated_idx][1] * 100), Color.sign(self._args.sys_color_set[self._args.sys_activated_idx].hsv)))
-
elif self._args.sys_activated_assit_idx >= 0 and self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx]:
curr_color = gen_assit_color(self._args.sys_color_set[self._args.sys_activated_idx], *self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2:6])
curr_loc = self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx]
-
self.ps_status_changed.emit((self.image3c.rgb_data.shape[1], self.image3c.rgb_data.shape[0], "{:.1f}".format(curr_loc[0] * 100), "{:.1f}".format(curr_loc[1] * 100), Color.sign(curr_color.hsv)))
-
+ elif self._args.sys_color_locs[self._args.sys_activated_idx]:
+ self.ps_status_changed.emit((self.image3c.rgb_data.shape[1], self.image3c.rgb_data.shape[0], "{:.1f}".format(self._args.sys_color_locs[self._args.sys_activated_idx][0] * 100), "{:.1f}".format(self._args.sys_color_locs[self._args.sys_activated_idx][1] * 100), Color.sign(self._args.sys_color_set[self._args.sys_activated_idx].hsv)))
else:
self.ps_status_changed.emit((self.image3c.rgb_data.shape[1], self.image3c.rgb_data.shape[0]))
-
- # outer circles.
if self._outer_circles:
frame_color = self._args.negative_color
-
if self._outer_circles[0] == self._args.sys_activated_idx and (self._outer_circles[1] == self._args.sys_activated_assit_idx or self._outer_circles[1] == -1):
frame_color = self._args.positive_color
-
- # circle 0.
if self._outer_circles[5] == 0:
painter.setPen(QPen(QColor(*frame_color, ), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][0]
painter.drawEllipse(*outer_circle[0])
-
for line in outer_circle[1:]:
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
if len(self._outer_circles[4]) > 2:
- # circle 1.
if self._outer_circles[5] == 1:
painter.setPen(QPen(QColor(*frame_color, ), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][1]
painter.drawEllipse(*outer_circle[0])
-
for line in outer_circle[1:]:
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
- # circle 2.
if self._outer_circles[5] == 2:
painter.setPen(QPen(QColor(*frame_color, ), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][2]
painter.drawEllipse(*outer_circle[0])
-
- # relative (move-able) or ref (un-move-able) point tag. assit dot box.
if self._outer_circles[1] < len(self._args.sys_grid_assitlocs[self._outer_circles[0]]) and self._args.sys_grid_assitlocs[self._outer_circles[0]][self._outer_circles[1]][5]:
line = outer_circle[1]
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
poly = QPolygon([QPoint(*i) for i in outer_circle[2]])
painter.drawPolygon(poly)
-
painter.end()
- # ---------- ---------- ---------- Mouse Event Funcs ---------- ---------- ---------- #
-
def keyPressEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
if event.key() == Qt.Key_Space and self.image3c.display:
self._press_key = 3
self.setCursor(QCursor(Qt.ClosedHandCursor))
-
event.accept()
self.update()
-
elif event.key() == Qt.Key_Control and self.image3c.display:
self._press_key = 2
event.accept()
-
else:
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
@@ -411,11 +287,9 @@ def keyReleaseEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
if self._press_key:
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
-
event.ignore()
self.update()
@@ -423,31 +297,23 @@ def mouseDoubleClickEvent(self, event):
if not self.image3c.img_data and event.button() == Qt.LeftButton:
p_x = event.x()
p_y = event.y()
-
if self._tip_box[0] < p_x < (self._tip_box[0] + self._tip_box[2]) and self._tip_box[1] < p_y < (self._tip_box[1] + self._tip_box[3]):
self.open_image_dialog()
-
event.accept()
self.update()
-
elif self.image3c.img_data and event.button() == Qt.LeftButton and self._args.sys_activated_assit_idx >= 0:
point = (event.x(), event.y())
assit_color_loc = self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx]
-
if assit_color_loc:
assit_pt_xy = np.array((assit_color_loc[0] * self._resized_img_pos[2] + self._resized_img_pos[0], assit_color_loc[1] * self._resized_img_pos[3] + self._resized_img_pos[1]), dtype=int)
-
if np.sum((point - assit_pt_xy) ** 2) < self._args.dep_circle_dist_2:
self.ps_assit_pt_changed.emit(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5])
self.ps_color_changed.emit(True)
event.accept()
-
else:
event.ignore()
-
else:
event.ignore()
-
else:
event.ignore()
@@ -455,18 +321,14 @@ def dragEnterEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
try:
image = event.mimeData().urls()[0].toLocalFile()
-
except Exception as err:
event.ignore()
return
-
if image.split(".")[-1].lower() in ("png", "bmp", "jpg", "jpeg", "tif", "tiff", "webp"):
self._drop_image = image
event.accept()
-
else:
event.ignore()
@@ -474,13 +336,10 @@ def dropEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
if self._drop_image:
self.open_image(self._drop_image)
self._drop_image = None
-
event.accept()
-
else:
event.ignore()
@@ -488,23 +347,16 @@ def wheelEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
if self.image3c.display:
point = (event.x(), event.y())
ratio = (event.angleDelta() / 120).y()
-
if ratio:
ratio = ratio * self._args.zoom_step if ratio > 0 else -1 * ratio / self._args.zoom_step
-
else:
ratio = 1
-
self.zoom(ratio, point)
-
event.accept()
- # self.update() is completed by self.zoom.
# self.update()
-
else:
event.ignore()
@@ -513,12 +365,9 @@ def mousePressEvent(self, event):
if event.button() == Qt.MidButton or (self._press_key == 3 and event.button() == Qt.LeftButton):
if event.button() == Qt.MidButton:
self.setCursor(QCursor(Qt.ClosedHandCursor))
-
self._start_pt = (event.x(), event.y())
-
event.accept()
self.update()
-
elif event.button() == Qt.LeftButton and self._croping_img:
self._croping_img = (
event.x() - self.x(),
@@ -526,192 +375,129 @@ def mousePressEvent(self, event):
event.x() - self.x(),
event.y() - self.y(),
)
-
event.accept()
self.update()
-
elif event.button() == Qt.LeftButton and self._locating_img:
self._locating_img = (
event.x() - self.x(),
event.y() - self.y(),
)
-
event.accept()
self.update()
-
elif event.button() == Qt.RightButton and self._croping_img:
self._croping_img = False
-
event.accept()
self.update()
-
elif event.button() == Qt.RightButton and self._locating_img:
self._locating_img = False
-
event.accept()
self.update()
-
elif self._press_key in (0, 2) and event.button() == Qt.LeftButton and not (self._croping_img or self._locating_img):
- # outer circle.
insert_assit_pt_by_info_tag = False
-
if self._press_key == 0 and self._outer_circles and self._outer_circles[5] > -1 and event.button() == Qt.LeftButton:
sel_idx, sel_assit_idx, is_in_pt, is_in_assit_pt, circle_locations, sel_info_idx = self._outer_circles
-
self._args.sys_activated_idx = sel_idx
self._args.sys_activated_assit_idx = sel_assit_idx
-
- # add a ref color.
if is_in_pt or (is_in_assit_pt and sel_info_idx == 0):
insert_assit_pt_by_info_tag = True
-
- # del the ref color.
elif is_in_assit_pt and sel_info_idx == 1:
self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx] = None
-
event.accept()
return
-
- # fix or unfix the ref color.
else:
self.ps_assit_pt_changed.emit(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5])
self.ps_color_changed.emit(True)
-
- # insert a new assit point.
if insert_assit_pt_by_info_tag or (self._press_key == 2 and self._args.sys_color_locs[self._args.sys_activated_idx]):
if self._args.sys_activated_assit_idx < 0:
self._args.sys_activated_assit_idx = 0
-
already_selected_assit = False
-
for ci in range(len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]) - self._args.sys_activated_assit_idx):
if self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx] == None:
already_selected_assit = True
-
break
-
self._args.sys_activated_assit_idx += 1
-
- # max assit len 30.
assit_len = len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx])
-
if not already_selected_assit and assit_len < 31:
self._args.sys_activated_assit_idx = assit_len
self._args.sys_grid_assitlocs[self._args.sys_activated_idx].append([0.1, 0.1, 15, 0, 0, True])
self._args.sys_assit_color_locs[self._args.sys_activated_idx].append(None)
-
self.ps_color_changed.emit(True)
-
point = np.array((event.x(), event.y()))
already_accept = False
-
for idx in range(5):
if self._args.sys_color_locs[idx] and np.sum((point - self._args.sys_color_locs[idx] * self._resized_img_pos[2:] - self._resized_img_pos[:2]) ** 2) < self._args.dep_circle_dist_wid_2:
self._args.sys_activated_idx = idx
self._args.sys_activated_assit_idx = -1
already_accept = True
-
else:
curr_locs = self._args.sys_assit_color_locs[idx]
-
for assit_idx in range(len(curr_locs)):
if curr_locs[assit_idx] and np.sum((point - curr_locs[assit_idx] * self._resized_img_pos[2:] - self._resized_img_pos[:2]) ** 2) < self._args.dep_circle_dist_wid_2 * 4 / 9:
self._args.sys_activated_idx = idx
self._args.sys_activated_assit_idx = assit_idx
already_accept = True
-
break
-
if already_accept:
break
-
- # select the main color before select assit color.
if self._args.sys_activated_assit_idx >= 0 and (not self._args.sys_color_locs[self._args.sys_activated_idx]):
self._args.sys_activated_assit_idx = -1
-
select_main_color = not self._args.sys_color_locs[self._args.sys_activated_idx]
select_assit_colors = self._args.sys_activated_assit_idx >= 0 and (not self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx])
-
- # select.
if event.button() == Qt.LeftButton and (((self._args.press_move or select_main_color or select_assit_colors) and self._resized_img_pos[0] < point[0] < self._resized_img_pos[0] + self._resized_img_pos[2] and self._resized_img_pos[1] < point[1] < self._resized_img_pos[1] + self._resized_img_pos[3]) or already_accept):
self._locating_colors = True
-
event.accept()
self.update()
-
else:
event.ignore()
-
else:
event.ignore()
-
else:
event.ignore()
def mouseMoveEvent(self, event):
point = np.array((event.x(), event.y()))
-
if isinstance(self._start_pt, np.ndarray) or self._start_pt:
self._outer_circles = None
-
if self._args.rev_direct:
self.move(self._start_pt[0] - point[0], self._start_pt[1] - point[1])
-
else:
self.move(point[0] - self._start_pt[0], point[1] - self._start_pt[1])
-
self._start_pt = point
-
event.accept()
- # self.update() is completed by self.move.
# self.update()
-
elif self._croping_img:
self._outer_circles = None
-
self._croping_img = (
self._croping_img[0],
self._croping_img[1],
event.x() - self.x(),
event.y() - self.y(),
)
-
event.accept()
self.update()
-
elif self._locating_img:
self._outer_circles = None
-
self._locating_img = (
event.x() - self.x(),
event.y() - self.y(),
)
-
event.accept()
self.update()
-
elif self._locating_colors:
self._outer_circles = None
-
loc = [(point[0] - self._resized_img_pos[0]) / self._resized_img_pos[2], (point[1] - self._resized_img_pos[1]) / self._resized_img_pos[3]]
loc[0] = 0.0 if loc[0] < 0.0 else loc[0]
loc[0] = 1.0 if loc[0] > 1.0 else loc[0]
loc[1] = 0.0 if loc[1] < 0.0 else loc[1]
loc[1] = 1.0 if loc[1] > 1.0 else loc[1]
-
if self._args.sys_activated_assit_idx < 0:
self._args.sys_color_locs[self._args.sys_activated_idx] = tuple(loc)
-
else:
self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx] = tuple(loc)
-
self.modify_color_loc()
-
event.accept()
self.update()
-
else:
- # outer circles.
if self._args.show_info_pts[1] and self._press_key == 0 and (not self._drop_image) and isinstance(self._resized_img_pos, np.ndarray):
color_locs = np.array([i * self._resized_img_pos[2:4] + self._resized_img_pos[0:2] if isinstance(i, (tuple, list, np.ndarray)) else (-100, -100) for i in self._args.sys_color_locs], dtype=int)
major = self._args.show_info_pts[1] in (1, 3)
@@ -719,118 +505,75 @@ def mouseMoveEvent(self, event):
minor = self._args.show_info_pts[1] > 1
last_count = bool(self._outer_circles)
self._outer_circles = get_outer_circles(point, self._args.sys_activated_idx, color_locs, assit_color_locs, (self._args.dep_circle_dist_wid) * 1.2, self._args.circle_dist * 1.2, self._args.circle_dist, self._outer_circles, major=major, minor=minor)
-
if self._outer_circles or last_count:
self.update()
-
else:
self._outer_circles = None
-
event.ignore()
def mouseReleaseEvent(self, event):
self.setCursor(QCursor(Qt.ArrowCursor))
self._locating_colors = False
self._start_pt = None
-
if event.button() == Qt.LeftButton:
self.ps_history_backup.emit(True)
-
event.ignore()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
+ def init_key(self):
+ self._press_key = 0
+ self._drop_image = None
def init_icon(self):
- """
- if self._args.style_id < 5:
- self._ico = QImage(":/images/images/icon_grey_1024.png")
- """
-
self._ico = QImage(":/images/images/icon_trans_1024.png")
def draw_twopt_rect(self, painter, x0, y0, x1, y1):
- """
- Draw rect by two points.
- """
-
if x0 == x1 or y0 == y1:
return
-
painter.drawRect(x0, y0, x1 - x0, y1 - y0)
def get_sorted_croping(self):
- """
- Sort the croping value from mouse move to standard value.
- """
-
croping = list(self._croping_img)
-
min_wid_rto = 10
min_hig_rto = 10
-
x_lim = (self.x() - min_wid_rto, self.x() + self.width() + min_wid_rto)
y_lim = (self.y() - min_hig_rto, self.y() + self.height() + min_hig_rto)
-
croping[0] = x_lim[0] if croping[0] < x_lim[0] else croping[0]
croping[0] = x_lim[1] if croping[0] > x_lim[1] else croping[0]
-
croping[1] = y_lim[0] if croping[1] < y_lim[0] else croping[1]
croping[1] = y_lim[1] if croping[1] > y_lim[1] else croping[1]
-
croping[2] = x_lim[0] if croping[2] < x_lim[0] else croping[2]
croping[2] = x_lim[1] if croping[2] > x_lim[1] else croping[2]
-
croping[3] = y_lim[0] if croping[3] < y_lim[0] else croping[3]
croping[3] = y_lim[1] if croping[3] > y_lim[1] else croping[3]
-
if croping[0] > croping[2]:
croping[0], croping[2] = croping[2], croping[0]
-
if croping[1] > croping[3]:
croping[1], croping[3] = croping[3], croping[1]
-
if croping[2] - croping[0] < min_wid_rto:
croping[2] = croping[0] + min_wid_rto
-
if croping[2] > x_lim[1]:
croping[2] = x_lim[1]
croping[0] = x_lim[1] - min_wid_rto
-
if croping[3] - croping[1] < min_hig_rto:
croping[3] = croping[1] + min_hig_rto
-
if croping[3] > y_lim[1]:
croping[3] = y_lim[1]
croping[1] = y_lim[1] - min_hig_rto
-
return croping
def get_sorted_locating(self):
- """
- Sort the locating value from mouse move to standard value.
- """
-
locating = list(self._locating_img)
-
min_wid_rto = 10
min_hig_rto = 10
-
x_lim = (self.x() - min_wid_rto, self.x() + self.width() + min_wid_rto)
y_lim = (self.y() - min_hig_rto, self.y() + self.height() + min_hig_rto)
-
locating[0] = x_lim[0] if locating[0] < x_lim[0] else locating[0]
locating[0] = x_lim[1] if locating[0] > x_lim[1] else locating[0]
-
locating[1] = y_lim[0] if locating[1] < y_lim[0] else locating[1]
locating[1] = y_lim[1] if locating[1] > y_lim[1] else locating[1]
-
return locating
def get_revised_croping_in_img(self):
- """
- Revise the croping value from mouse move to standard value (relative to full image).
- """
-
st_croping = self.get_sorted_croping()
relative_loc = [
(st_croping[0] - self._resized_img_pos[0]) / self._resized_img_pos[2],
@@ -838,740 +581,467 @@ def get_revised_croping_in_img(self):
(st_croping[2] - self._resized_img_pos[0]) / self._resized_img_pos[2],
(st_croping[3] - self._resized_img_pos[1]) / self._resized_img_pos[3],
]
-
if relative_loc[0] > 1.0 or relative_loc[1] > 1.0 or relative_loc[2] < 0.0 or relative_loc[3] < 0.0:
return None
-
else:
for idx in range(4):
relative_loc[idx] = 0.0 if relative_loc[idx] < 0.0 else relative_loc[idx]
relative_loc[idx] = 1.0 if relative_loc[idx] > 1.0 else relative_loc[idx]
-
return relative_loc
def get_revised_locating_in_img(self):
- """
- Revise the locating value from mouse move to standard value (relative to full image).
- """
-
st_locating = self.get_sorted_locating()
relative_loc = [
(st_locating[0] - self._resized_img_pos[0]) / self._resized_img_pos[2],
(st_locating[1] - self._resized_img_pos[1]) / self._resized_img_pos[3],
]
-
for idx in range(2):
if relative_loc[idx] < 0.0 or relative_loc[idx] > 1.0:
return None
-
return relative_loc
def zoom(self, ratio, center):
- """
- Zoom displayed image.
- """
-
if not (self.isVisible() and self.image3c.display and isinstance(self._resized_img_pos, np.ndarray)):
return
-
if center == "default":
center = np.array((self.width() / 2, self.height() / 2), dtype=int)
-
x, y, wid, hig = self._resized_img_pos
-
img_wid = int(self.image3c.display.size().width())
img_hig = int(self.image3c.display.size().height())
-
if img_wid < self.width() and img_hig < self.height():
max_wid = int(self.width() * 2)
max_hig = int(self.height() * 2)
-
elif img_wid < self.width() * 4 and img_hig < self.height() * 4:
max_wid = int(self.width() * 6)
max_hig = int(self.height() * 6)
-
elif img_wid < self.width() * 8 and img_hig < self.height() * 8:
max_wid = int(self.width() * 10)
max_hig = int(self.height() * 10)
-
else:
max_wid = img_wid
max_hig = img_hig
-
# min_wid = 24
# min_hig = 24
-
if wid * ratio > max_wid or hig * ratio > max_hig:
norm_ratio = min(max_wid / wid, max_hig / hig)
-
elif wid * ratio < 24 or hig * ratio < 24:
norm_ratio = max(24 / wid, 24 / hig)
-
else:
norm_ratio = ratio
-
x = (x - center[0]) * norm_ratio + center[0]
y = (y - center[1]) * norm_ratio + center[1]
-
self._resized_img_pos = np.array([round(x), round(y), round(wid * norm_ratio), round(hig * norm_ratio)], dtype=int)
self._home_image = False
-
self.update()
def move(self, shift_x, shift_y):
- """
- Move displayed image.
- """
-
if not (self.isVisible() and self.image3c.display and isinstance(self._resized_img_pos, np.ndarray)):
return
-
x, y, wid, hig = self._resized_img_pos
-
if self._args.rev_direct:
x = x - shift_x
y = y - shift_y
-
else:
x = x + shift_x
y = y + shift_y
-
self._resized_img_pos = np.array([x, y, wid, hig], dtype=int)
self._home_image = False
-
self.update()
def home(self):
- """
- Home displayed image.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
if self._home_image:
self.image3c.load_image(self._args.sys_category, self._args.sys_channel)
-
img_wid = int(self.image3c.display.size().width())
img_hig = int(self.image3c.display.size().height())
-
ratio = min(self.width() / img_wid, self.height() / img_hig)
-
self._resized_img_pos = np.array([
round((self.width() - img_wid * ratio) / 2),
round((self.height() - img_hig * ratio) / 2),
round(img_wid * ratio),
round(img_hig * ratio),
], dtype=int)
-
self._home_image = not self._home_image
-
self.update()
def open_image_dialog(self):
- """
- Open a image dialog.
- """
-
if not self.isVisible():
return
-
cb_filter = "{} (*.png *.bmp *.jpg *.jpeg *.tif *.tiff *.webp);; {} (*.png);; {} (*.bmp);; {} (*.jpg *.jpeg);; {} (*.tif *.tiff);; {} (*.webp)".format(*self._extend_descs)
cb_file = QFileDialog.getOpenFileName(None, self._open_descs[1], self._args.usr_image, filter=cb_filter)
-
if cb_file[0]:
self._args.usr_image = os.path.dirname(os.path.abspath(cb_file[0]))
self.open_image(cb_file[0])
-
else:
- # closed without open a file.
return
def open_image(self, image, script="", with_full_locs=[], direct=False):
- """
- Open a image.
- """
-
if isinstance(script, tuple) and (not self.isVisible() or direct):
return
-
if script and (not self.image3c.img_data):
return
-
if self.image3c.isRunning() or self._enhance_lock:
self.warning(self._image_errs[1])
return
-
if not self._args.check_temp_dir():
self.warning(self._image_errs[2])
return
-
if not isinstance(script, tuple):
if direct:
img_data = image
-
else:
try:
img_data = PImage.open(image)
-
except Exception as err:
self.warning(self._image_errs[4] + "\n{}\n{}".format(self._image_errs[8], err))
return
-
self.image3c.img_data = img_data
self._args.sys_image_url = image
-
self._categories = set()
-
self._args.sys_category = 0
self._args.sys_channel = 0
self.ps_image_changed.emit(True)
-
self._args.sys_activated_assit_idx = -1
self._args.sys_color_locs = [None, None, None, None, None]
self._args.sys_assit_color_locs = [[None for j in self._args.sys_grid_assitlocs[i]] for i in range(5)]
-
if with_full_locs and len(with_full_locs) == 5:
for fidx in range(5):
if len(with_full_locs[fidx]) > 0:
self._args.sys_color_locs[fidx] = tuple(with_full_locs[fidx][0]) if with_full_locs[fidx][0] else None
-
if len(with_full_locs[fidx]) - 1 == len(self._args.sys_assit_color_locs[fidx]):
self._args.sys_assit_color_locs[fidx] = list(with_full_locs[fidx][1:])
-
self.image3c.display = None
-
self.image3c.ori_display_data = None
self.image3c.res_display_data = None
self.image3c.rev_display_data = None
-
self.image3c.rgb_data = None
self.image3c.hsv_data = None
-
if isinstance(script, tuple):
if script[0] in ("ZOOM", "CROP"):
self._resized_img_pos = None
-
self.image3c.run_args = script
self.image3c.run_category = "init"
self.image3c.start()
-
else:
self._resized_img_pos = None
-
self.image3c.run_args = None
-
self.image3c.run_category = "init"
self.image3c.start()
-
self.ps_history_backup.emit(True)
self.update()
def open_category(self):
- """
- Open this image in other category.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
if not self.image3c.img_data:
return
-
if not self._args.check_temp_dir():
self.ps_recover_channel.emit(True)
self.warning(self._image_errs[2])
return
-
if self._enhance_lock:
self.ps_recover_channel.emit(True)
self.warning(self._image_errs[1])
return
-
self.image3c.display = None
-
self.image3c.ori_display_data = None
self.image3c.res_display_data = None
self.image3c.rev_display_data = None
-
if self._args.sys_category * 10 + self._args.sys_channel not in self._categories:
self.image3c.run_category = self._args.sys_category
self.image3c.start()
-
self.update()
def extract_image(self, values):
- """
- Extract a set of colors from image.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
if self.image3c.isRunning():
self.warning(self._image_errs[1])
return
-
self.image3c.run_args = (self._args.rand_num, values)
self.image3c.run_category = "extract"
self.image3c.start()
-
self.update()
def enhance_image(self, values):
- """
- Modify r, g or (and) b values to enhance or inverse the contrast of image.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
if self.image3c.isRunning():
self.warning(self._image_errs[1])
return
-
if values[0][:5] == "cover":
cb_filter = "{} (*.png *.bmp *.jpg *.jpeg *.tif *.tiff *.webp);; {} (*.png);; {} (*.bmp);; {} (*.jpg *.jpeg);; {} (*.tif *.tiff);; {} (*.webp)".format(*self._extend_descs)
cb_file = QFileDialog.getOpenFileName(None, self._open_descs[3], self._args.usr_image, filter=cb_filter)
-
if cb_file[0]:
self._args.usr_image = os.path.dirname(os.path.abspath(cb_file[0]))
values = list(values) + [os.path.abspath(cb_file[0])]
-
else:
- # closed without open a file.
return
-
self._enhance_lock = True
-
self.image3c.run_args = values[1:]
self.image3c.run_category = values[0]
self.image3c.start()
-
self.update()
def cancel_croping_or_locating(self):
- """
- Cancel the croping or locating actions.
- Esc refer to cancel them if they are activated (return True) in main window.
- """
-
if self._croping_img or self._locating_img:
self._croping_img = False
self._locating_img = False
-
self.update()
-
return True
-
else:
return False
def crop_image(self, value):
- """
- Crop image.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
if self._locating_img:
return
-
if self.image3c.isRunning() or self._enhance_lock:
self.warning(self._image_errs[1])
return
-
if value:
if isinstance(self._croping_img, tuple):
revised_croping_value = self.get_revised_croping_in_img()
-
if revised_croping_value:
self.open_image("", ("CROP", revised_croping_value))
-
else:
self._croping_img = False
-
else:
self._croping_img = True
-
else:
self._croping_img = False
-
self.update()
def replace_color(self, value):
- """
- Replace color.
- """
-
if not (self.isVisible() and self.image3c.display and isinstance(self.image3c.rgb_data, np.ndarray)):
return
-
if self.image3c.isRunning():
self.warning(self._image_errs[1])
return
-
if self._croping_img:
return
-
if value[0]:
if isinstance(self._locating_img, tuple):
shape = self.image3c.rgb_data.shape
revised_locating_value = self.get_revised_locating_in_img()
-
if revised_locating_value and value[4]:
- # using old algorithm.
- #
rgb = self.image3c.rgb_data[int(round(revised_locating_value[1] * (shape[0] - 1)))][int(round(revised_locating_value[0] * (shape[1] - 1)))]
separ = []
fact = []
-
if value[0] == 1:
for i in range(3):
if self._args.sys_color_set[self._args.sys_activated_idx].rgb[i] > rgb[i]:
separ.append(rgb[i] - rgb[i] * value[3])
- fact.append((self._args.sys_color_set[self._args.sys_activated_idx].rgb[i] - rgb[i]) / (255 - (rgb[i] - 0.00001))) # divide by zero error.
-
+ fact.append((self._args.sys_color_set[self._args.sys_activated_idx].rgb[i] - rgb[i]) / (255 - (rgb[i] - 0.00001)))
else:
separ.append(rgb[i] + 0.00001 + (255.0 - rgb[i]) * value[3])
- fact.append((rgb[i] - self._args.sys_color_set[self._args.sys_activated_idx].rgb[i]) / (rgb[i] + 0.00001)) # divide by zero error.
-
+ fact.append((rgb[i] - self._args.sys_color_set[self._args.sys_activated_idx].rgb[i]) / (rgb[i] + 0.00001))
self.image3c.run_args = ((0, 1, 2), tuple(separ), tuple(fact), value[1], value[2])
self.image3c.run_category = "enhance_rgb"
-
elif value[0] == 2:
point = Color(rgb, tp="rgb")
angle = self._args.sys_color_set[self._args.sys_activated_idx].ref_h(point.h)
-
hsv = list(point.hsv)
-
if angle > 0.0:
hsv[0] = float(hsv[0]) - 1E-4
-
elif angle < 0.0:
hsv[0] = float(hsv[0]) + 1E-4
-
else:
hsv[0] = float(hsv[0])
-
separ.append(hsv[0])
fact.append(abs(angle) / 180.0 * value[3])
-
if self._args.sys_color_set[self._args.sys_activated_idx].hsv[1] > hsv[1]:
separ.append(hsv[1] - hsv[1] * value[3])
fact.append((self._args.sys_color_set[self._args.sys_activated_idx].hsv[1] - hsv[1]) / (1.0 - hsv[1]))
-
else:
separ.append(hsv[1] + 0.00001 + (1.0 - hsv[1]) * value[3])
fact.append((hsv[1] - self._args.sys_color_set[self._args.sys_activated_idx].hsv[1]) / hsv[1])
-
if self._args.sys_color_set[self._args.sys_activated_idx].hsv[2] > hsv[2]:
separ.append(hsv[2] - hsv[2] * value[3])
fact.append((self._args.sys_color_set[self._args.sys_activated_idx].hsv[2] - hsv[2]) / (1.0 - hsv[2]))
-
else:
separ.append(hsv[2] + 0.00001 + (1.0 - hsv[1]) * value[3])
fact.append((hsv[2] - self._args.sys_color_set[self._args.sys_activated_idx].hsv[2]) / hsv[2])
-
self.image3c.run_args = ((0, 1, 2), tuple(separ), tuple(fact), value[1], value[2])
self.image3c.run_category = "enhance_hsv"
-
self.image3c.start()
-
self._enhance_lock = True
-
elif revised_locating_value:
- # using new algorithm.
- #
rgb = self.image3c.rgb_data[int(round(revised_locating_value[1] * (shape[0] - 1)))][int(round(revised_locating_value[0] * (shape[1] - 1)))]
-
fact = []
-
if value[0] == 1:
for i in range(3):
if self._args.sys_color_set[self._args.sys_activated_idx].rgb[i] > rgb[i]:
- fori = (self._args.sys_color_set[self._args.sys_activated_idx].rgb[i] - rgb[i]) / (255.0 - (rgb[i] - 0.00001)) # divide by zero error.
+ fori = (self._args.sys_color_set[self._args.sys_activated_idx].rgb[i] - rgb[i]) / (255.0 - (rgb[i] - 0.00001))
fact.append(fori * value[3])
-
else:
- fori = (rgb[i] - self._args.sys_color_set[self._args.sys_activated_idx].rgb[i]) / (rgb[i] + 0.00001) # divide by zero error.
+ fori = (rgb[i] - self._args.sys_color_set[self._args.sys_activated_idx].rgb[i]) / (rgb[i] + 0.00001)
fact.append(fori * value[3])
-
self.image3c.run_args = ((0, 1, 2), tuple(rgb), tuple(fact), value[1], value[2])
self.image3c.run_category = "enhance_rgb"
-
elif value[0] == 2:
point = Color(rgb, tp="rgb")
angle = self._args.sys_color_set[self._args.sys_activated_idx].ref_h(point.h)
-
hsv = list(point.hsv)
-
if angle > 0.0:
hsv[0] = float(hsv[0]) - 1E-4
-
elif angle < 0.0:
hsv[0] = float(hsv[0]) + 1E-4
-
else:
hsv[0] = float(hsv[0])
-
fact.append(abs(angle) / 180.0 * value[3])
-
if self._args.sys_color_set[self._args.sys_activated_idx].hsv[1] > hsv[1]:
fori = (self._args.sys_color_set[self._args.sys_activated_idx].hsv[1] - hsv[1]) / (1.0 - (hsv[1] - 0.00001))
fact.append(fori * value[3])
-
else:
fori = (hsv[1] - self._args.sys_color_set[self._args.sys_activated_idx].hsv[1]) / (hsv[1] + 0.00001)
fact.append(fori * value[3])
-
if self._args.sys_color_set[self._args.sys_activated_idx].hsv[2] > hsv[2]:
fori = (self._args.sys_color_set[self._args.sys_activated_idx].hsv[2] - hsv[2]) / (1.0 - (hsv[2] - 0.00001))
fact.append(fori * value[3])
-
else:
fori = (hsv[2] - self._args.sys_color_set[self._args.sys_activated_idx].hsv[2]) / (hsv[2] + 0.00001)
fact.append(fori * value[3])
-
self.image3c.run_args = ((0, 1, 2), tuple(hsv), tuple(fact), value[1], value[2])
self.image3c.run_category = "enhance_hsv"
-
self.image3c.start()
-
self._enhance_lock = True
-
else:
self._locating_img = False
-
else:
self._locating_img = True
-
else:
self._locating_img = False
-
self.update()
def update_loading_label(self, idx):
- """
- Loading descriptions when importing a image.
- """
-
self._tip_label.setText(self._image_descs[idx])
self._tip_label.setAlignment(Qt.AlignCenter)
-
self.update()
def update_loading_bar(self, idx):
- """
- Loading process when importing a image.
- """
-
self._loading_bar.setValue(idx)
-
self.update()
def loading_finished(self, idx):
- """
- Loading finished.
- """
-
self._categories.add(idx)
-
self._croping_img = False
self._locating_img = False
self._home_image = False
-
self.update()
def extract_finished(self, value):
- """
- Enhance finished.
- """
-
self._args.hm_rule = "custom"
self.ps_modify_rule.emit(True)
-
self._args.sys_color_locs = value
-
for i in range(5):
rgb = self.image3c.rgb_data[int(round(value[i][1] * (self.image3c.rgb_data.shape[0] - 1)))][int(round(value[i][0] * (self.image3c.rgb_data.shape[1] - 1)))]
-
color = Color(rgb, tp="rgb", overflow=self._args.sys_color_set.get_overflow())
self._args.sys_color_set.modify(self._args.hm_rule, i, color, do_sync=False)
-
self.ps_color_changed.emit(True)
# similar to modify_color_loc,
- # update_color_loc() is completed by
- # self._wget_image.ps_color_changed.connect(lambda x: self._wget_cube_table.update_color()) in main.py.
-
+ # update_color_loc() is completed by
self._home_image = False
-
self.ps_history_backup.emit(True)
self.update()
def enhance_finished(self, idx):
- """
- Enhance finished.
- """
-
if idx == 2:
self.warning(self._image_errs[6])
-
if idx == 3:
self.warning(self._image_errs[7])
-
self._enhance_lock = False
self._locating_img = False
self._home_image = False
-
self.update()
def modify_color_loc(self):
- """
- Modify color set by overlabel.
- """
-
if not isinstance(self.image3c.rgb_data, np.ndarray):
return
-
if self._args.sys_activated_assit_idx < 0:
loc = self._args.sys_color_locs[self._args.sys_activated_idx]
-
else:
loc = self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx]
-
if loc:
shape = self.image3c.rgb_data.shape
rgb = self.image3c.rgb_data[int(round(loc[1] * (shape[0] - 1)))][int(round(loc[0] * (shape[1] - 1)))]
-
if self._args.sys_activated_assit_idx < 0:
if not (rgb == self._args.sys_color_set[self._args.sys_activated_idx].rgb).all():
color = Color(rgb, tp="rgb", overflow=self._args.sys_color_set.get_overflow())
self._args.sys_color_set.modify(self._args.hm_rule, self._args.sys_activated_idx, color)
-
else:
color = Color(rgb, tp="rgb", overflow=self._args.sys_color_set.get_overflow())
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2:5] = gen_assit_args(self._args.sys_color_set[self._args.sys_activated_idx], color, self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5])
-
self.ps_color_changed.emit(True)
- # update_color_loc() is completed by
- # self._wget_image.ps_color_changed.connect(lambda x: self._wget_cube_table.update_color()) in main.py.
+ # update_color_loc() is completed by
def update_color_loc(self):
- """
- Update color set by overlabel.
- """
-
if not isinstance(self.image3c.rgb_data, np.ndarray):
return
-
for idx in range(5):
loc = self._args.sys_color_locs[idx]
-
if loc:
shape = self.image3c.rgb_data.shape
rgb = self.image3c.rgb_data[int(round(loc[1] * (shape[0] - 1)))][int(round(loc[0] * (shape[1] - 1)))]
-
if not (rgb == self._args.sys_color_set[idx].rgb).all():
self._args.sys_color_locs[idx] = None
-
for assit_idx in range(len(self._args.sys_grid_assitlocs[idx])):
loc = self._args.sys_assit_color_locs[idx][assit_idx]
-
if loc:
shape = self.image3c.rgb_data.shape
rgb = self.image3c.rgb_data[int(round(loc[1] * (shape[0] - 1)))][int(round(loc[0] * (shape[1] - 1)))]
-
curr_color = gen_assit_color(self._args.sys_color_set[idx], *self._args.sys_grid_assitlocs[idx][assit_idx][2:6])
-
if not (rgb == curr_color.rgb).all():
self._args.sys_assit_color_locs[idx][assit_idx] = None
-
- # self.ps_history_backup.emit(True) shouldn't be placed here.
- # it will record the moving path when moving tags.
-
self.update()
def freeze_image(self, value=None):
- """
- Freeze current image.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
if self.image3c.isRunning():
self.warning(self._image_errs[1])
return
-
load_image = ImageQt.fromqimage(self.image3c.display)
-
if load_image:
self.open_image(load_image, direct=True)
-
else:
self.warning(self._image_errs[5])
def save_image(self, value=None):
- """
- Exec save image.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
name = "{}".format(time.strftime("Rickrack_Image_%Y_%m_%d.png", time.localtime()))
-
cb_filter = "{} (*.png *.bmp *.jpg *.jpeg *.tif *.tiff *.webp);; {} (*.png);; {} (*.bmp);; {} (*.jpg *.jpeg);; {} (*.tif *.tiff);; {} (*.webp)".format(*self._extend_descs)
cb_file = QFileDialog.getSaveFileName(None, self._open_descs[2], os.sep.join((self._args.usr_image, name)), filter=cb_filter)
-
if cb_file[0]:
self._args.usr_image = os.path.dirname(os.path.abspath(cb_file[0]))
-
else:
- # closed without open a file.
return
-
self.image3c.display.save(cb_file[0])
def clipboard_in(self):
- """
- Load image from clipboard.
- """
-
if not self.isVisible():
return
-
clipboard = QApplication.clipboard().mimeData()
-
if clipboard.hasUrls():
try:
image = clipboard.urls()[0].toLocalFile()
-
except Exception as err:
return
-
if image.split(".")[-1].lower() in ("png", "bmp", "jpg", "jpeg", "tif", "tiff") and os.path.isfile(image):
self.open_image(image)
-
elif clipboard.hasImage():
load_image = self.image3c.save_load_data(clipboard.imageData())
-
if load_image:
self.open_image(load_image)
def clipboard_img(self):
- """
- Set the image as the clipboard data by Ctrl + c.
- """
-
if not (self.isVisible() and self.image3c.display):
return
-
mimedata = QMimeData()
mimedata.setImageData(QPixmap.fromImage(self.image3c.display))
-
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
@@ -1581,78 +1051,46 @@ def warning(self, text):
box.setText(text)
box.setIcon(QMessageBox.Warning)
box.addButton(self._image_errs[3], QMessageBox.AcceptRole)
-
box.exec_()
- # ---------- ---------- ---------- Menu ---------- ---------- ---------- #
-
def create_menu(self):
- """
- Create a right clicked menu.
- """
-
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.show_menu)
-
self._menu = QMenu(self)
-
- # _translate("Image", "Undo"), # 0
- # _translate("Image", "Redo"), # 1
self._action_undo = QAction(self)
self._action_undo.triggered.connect(lambda: self.ps_undo.emit(True))
self._menu.addAction(self._action_undo)
-
self._action_redo = QAction(self)
self._action_redo.triggered.connect(lambda: self.ps_undo.emit(False))
self._menu.addAction(self._action_redo)
-
# _translate("Image", "Reset"), # 5
self._action_reset = QAction(self)
self._action_reset.triggered.connect(self.home)
self._menu.addAction(self._action_reset)
-
- # _translate("Image", "Paste"), # 4
self._action_paste = QAction(self)
self._action_paste.triggered.connect(self.clipboard_in)
self._menu.addAction(self._action_paste)
-
- # _translate("Image", "Open Image"), # 2
self._action_open_img = QAction(self)
self._action_open_img.triggered.connect(self.open_image_dialog)
self._menu.addAction(self._action_open_img)
-
- # _translate("Image", "Copy Image"), # 3
self._action_copy_img = QAction(self)
self._action_copy_img.triggered.connect(self.clipboard_img)
self._menu.addAction(self._action_copy_img)
-
- # _translate("Board", "Freeze Image"), # 8
- # _translate("Board", "Save Image"), # 9
self._action_freeze_img = QAction(self)
self._action_freeze_img.triggered.connect(self.freeze_image)
self._menu.addAction(self._action_freeze_img)
-
self._action_save_img = QAction(self)
self._action_save_img.triggered.connect(self.save_image)
self._menu.addAction(self._action_save_img)
-
- # _translate("Image", "Zoom In"), # 6
- # _translate("Image", "Zoom Out"), # 7
self._action_zoom_in = QAction(self)
self._action_zoom_in.triggered.connect(lambda: self.zoom(self._args.zoom_step, center="default"))
self._menu.addAction(self._action_zoom_in)
-
self._action_zoom_out = QAction(self)
self._action_zoom_out.triggered.connect(lambda: self.zoom(1 / self._args.zoom_step, center="default"))
self._menu.addAction(self._action_zoom_out)
def show_menu(self):
- """
- Show the right clicked menu.
- """
-
self.update_action_text()
-
if self.image3c.display:
self._action_reset.setVisible(True)
self._action_copy_img.setVisible(True)
@@ -1660,7 +1098,6 @@ def show_menu(self):
self._action_zoom_out.setVisible(True)
self._action_freeze_img.setVisible(True)
self._action_save_img.setVisible(True)
-
else:
self._action_reset.setVisible(False)
self._action_copy_img.setVisible(False)
@@ -1668,71 +1105,41 @@ def show_menu(self):
self._action_zoom_out.setVisible(False)
self._action_freeze_img.setVisible(False)
self._action_save_img.setVisible(False)
-
self._menu.exec_(QCursor.pos())
- # ---------- ---------- ---------- Shortcut ---------- ---------- ---------- #
-
def update_skey(self):
- """
- Set depot shortcuts.
- """
-
for skey in self._args.shortcut_keymaps[45]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_img)
-
for skey in self._args.shortcut_keymaps[46]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_in)
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_action_text(self):
- # _translate("Image", "Undo"), # 0
- # _translate("Image", "Redo"), # 1
self._action_undo.setText(self._action_descs[0])
self._action_redo.setText(self._action_descs[1])
-
- # _translate("Image", "Open Image"), # 2
self._action_open_img.setText(self._action_descs[2])
-
- # _translate("Image", "Copy Image"), # 3
self._action_copy_img.setText(self._action_descs[3])
-
- # _translate("Image", "Paste"), # 4
self._action_paste.setText(self._action_descs[4])
-
# _translate("Image", "Reset"), # 5
self._action_reset.setText(self._action_descs[5])
-
- # _translate("Image", "Zoom In"), # 6
- # _translate("Image", "Zoom Out"), # 7
self._action_zoom_in.setText(self._action_descs[6])
self._action_zoom_out.setText(self._action_descs[7])
-
- # _translate("Board", "Freeze Image"), # 8
- # _translate("Board", "Save Image"), # 9
self._action_freeze_img.setText(self._action_descs[8])
self._action_save_img.setText(self._action_descs[9])
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._action_descs = (
_translate("Wheel", "Undo"), # 0
_translate("Wheel", "Redo"), # 1
@@ -1745,14 +1152,12 @@ def _func_tr_(self):
_translate("Image", "Freeze Image"), # 8
_translate("Image", "Save Image"), # 9
)
-
self._open_descs = (
_translate("Image", "Double click here to open an image."),
_translate("Image", "Open"),
_translate("Image", "Save"),
_translate("Image", "Cover"),
)
-
self._image_errs = (
_translate("Image", "Error"),
_translate("Image", "Could not process image. There is a process of image not finished."),
@@ -1764,7 +1169,6 @@ def _func_tr_(self):
_translate("Image", "Could not process image. This image is invalid."),
_translate("Operation", "Detail:"),
)
-
self._image_descs = (
_translate("Image", "Finishing."),
_translate("Image", "Loading RGB data."),
@@ -1785,7 +1189,6 @@ def _func_tr_(self):
_translate("Image", "Saving HSV final edge data."),
_translate("Image", "Applying filter to image data."),
)
-
self._extend_descs = (
_translate("Image", "All Acceptable Images"),
_translate("Image", "PNG Image"),
diff --git a/src/main/python/wgets/mode.py b/src/main/python/wgets/mode.py
index 3e75f0a..bcf7dd8 100644
--- a/src/main/python/wgets/mode.py
+++ b/src/main/python/wgets/mode.py
@@ -19,218 +19,148 @@
class Mode(QWidget):
- """
- Mode object based on QWidget. Init a mode in mode.
- """
-
ps_mode_changed = pyqtSignal(bool)
ps_assistp_changed = pyqtSignal(bool)
ps_info_changed = pyqtSignal(bool)
ps_color_sys_changed = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init mode.
- """
-
super().__init__(wget)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
- # load translations.
self._func_tr_()
-
- # init qt args.
mode_grid_layout = QGridLayout(self)
mode_grid_layout.setContentsMargins(0, 0, 0, 0)
mode_grid_layout.setHorizontalSpacing(0)
mode_grid_layout.setVerticalSpacing(0)
-
scroll_area = QScrollArea(self)
scroll_area.setFrameShape(QFrame.Box)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setWidgetResizable(True)
mode_grid_layout.addWidget(scroll_area)
-
scroll_contents = QWidget()
scroll_grid_layout = QGridLayout(scroll_contents)
scroll_grid_layout.setContentsMargins(3, 9, 3, 3)
scroll_grid_layout.setHorizontalSpacing(3)
scroll_grid_layout.setVerticalSpacing(12)
scroll_area.setWidget(scroll_contents)
-
- # color sys functional region.
self._color_sys_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._color_sys_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._color_sys_gbox, 0, 1, 1, 1)
-
self._color_sys_btns = []
-
for i in range(4):
btn = QRadioButton(self._color_sys_gbox)
gbox_grid_layout.addWidget(btn, i, 1, 1, 1)
-
btn.clicked.connect(self.modify_color_sys(i))
self._color_sys_btns.append(btn)
-
self._color_sys_btns[self._args.color_sys].setChecked(True)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 4, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 4, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 4, 2, 1, 1)
-
- # info functional region.
self._info_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._info_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._info_gbox, 1, 1, 1, 1)
-
self._cbox_major = QCheckBox(self._info_gbox)
self._cbox_major.setText("Major")
gbox_grid_layout.addWidget(self._cbox_major, 0, 1, 1, 1)
self._cbox_major.stateChanged.connect(lambda x: self.ps_info_changed.emit(x))
-
self._cbox_minor = QCheckBox(self._info_gbox)
self._cbox_minor.setText("Minor")
gbox_grid_layout.addWidget(self._cbox_minor, 1, 1, 1, 1)
self._cbox_minor.stateChanged.connect(lambda x: self.ps_info_changed.emit(x))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 2, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 2, 1, 1)
-
- # display functional region.
self._display_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._display_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._display_gbox, 2, 1, 1, 1)
-
self._cbox_rgb = QCheckBox(self._display_gbox)
self._cbox_rgb.setText("RGB")
gbox_grid_layout.addWidget(self._cbox_rgb, 0, 1, 1, 1)
self._cbox_rgb.stateChanged.connect(self.modify_state("rgb"))
-
self._cbox_hsv = QCheckBox(self._display_gbox)
self._cbox_hsv.setText("HSV")
gbox_grid_layout.addWidget(self._cbox_hsv, 1, 1, 1, 1)
self._cbox_hsv.stateChanged.connect(self.modify_state("hsv"))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 2, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 2, 1, 1)
-
- # grid functional region.
self._gridvls_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._gridvls_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._gridvls_gbox, 3, 1, 1, 1)
-
self.rhc_govalue = RGBHSVCkb(self._gridvls_gbox, oneline_mode=True)
gbox_grid_layout.addWidget(self.rhc_govalue, 0, 1, 1, 1)
self.rhc_govalue.ps_value_changed.connect(self.modify_grid_value("ctp", tuple))
-
self.ckb_rev_grid = QCheckBox(self._gridvls_gbox)
self.ckb_rev_grid.setChecked(False)
gbox_grid_layout.addWidget(self.ckb_rev_grid, 1, 1, 1, 1)
self.ckb_rev_grid.stateChanged.connect(self.modify_grid_value("rev_grid", bool))
-
self.sdt_col = SlideText(self._gridvls_gbox, num_range=(1, 51), maxlen=50, interval=10, step=1, decimals=0, default_value=9)
gbox_grid_layout.addWidget(self.sdt_col, 2, 1, 1, 1)
self.sdt_col.ps_value_changed.connect(self.modify_grid_value("col", int))
-
self.sdt_sum_factor = SlideText(self._gridvls_gbox, num_range=(0.0, 5.0), default_value=1.0)
gbox_grid_layout.addWidget(self.sdt_sum_factor, 3, 1, 1, 1)
self.sdt_sum_factor.ps_value_changed.connect(self.modify_grid_value("sum_factor", float))
-
self.sdt_dim_factor = SlideText(self._gridvls_gbox, num_range=(0.0, 1.0), default_value=1.0)
gbox_grid_layout.addWidget(self.sdt_dim_factor, 4, 1, 1, 1)
self.sdt_dim_factor.ps_value_changed.connect(self.modify_grid_value("dim_factor", float))
-
self.sdt_assist_factor = SlideText(self._gridvls_gbox, num_range=(0.0, 1.0), default_value=0.6)
gbox_grid_layout.addWidget(self.sdt_assist_factor, 5, 1, 1, 1)
self.sdt_assist_factor.ps_value_changed.connect(self.modify_grid_value("assist_factor", float))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 6, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 6, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 6, 2, 1, 1)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def sizeHint(self):
- return QSize(210, 60)
+ return QSize(250, 60)
def modify_state(self, tag):
- """
- Modify stored shown state set by cbox.
- """
-
def _func_(state):
setattr(self._args, "show_{}".format(tag), bool(state))
-
self.ps_mode_changed.emit(True)
-
return _func_
def update_mode(self):
- """
- Update mode cbox by self._args.show_rgb and show_hsv.
- """
-
self._cbox_rgb.setChecked(self._args.show_rgb)
self._cbox_hsv.setChecked(self._args.show_hsv)
self._color_sys_btns[self._args.color_sys].setChecked(True)
def modify_color_sys(self, idx):
- """
- Modify stored color system by btn.
- """
-
def _func_(value):
self._args.modify_settings("color_sys", idx)
self.ps_color_sys_changed.emit(True)
-
return _func_
def get_info(self):
- """
- Get value of cbox of self._args.show_info_pts.
- """
-
return int(self._cbox_major.isChecked()) + int(self._cbox_minor.isChecked()) * 2
def update_info(self, major, minor):
- """
- Update mode cbox by self._args.show_info_pts.
- """
-
self._cbox_major.stateChanged.disconnect()
self._cbox_minor.stateChanged.disconnect()
self._cbox_major.setChecked(major)
@@ -239,21 +169,12 @@ def update_info(self, major, minor):
self._cbox_minor.stateChanged.connect(lambda x: self.ps_info_changed.emit(x))
def modify_grid_value(self, name, dtype=float):
- """
- Modify a grid values.
- """
-
def _func_(value):
self._args.sys_grid_values[name] = dtype(value)
self.ps_assistp_changed.emit(True)
-
return _func_
def update_grid_vales(self):
- """
- Update grid values.
- """
-
self.rhc_govalue.set_values(self._args.sys_grid_values["ctp"])
self.sdt_col.set_value(self._args.sys_grid_values["col"])
self.sdt_sum_factor.set_value(self._args.sys_grid_values["sum_factor"])
@@ -261,32 +182,25 @@ def update_grid_vales(self):
self.sdt_assist_factor.set_value(self._args.sys_grid_values["assist_factor"])
self.ckb_rev_grid.setChecked(self._args.sys_grid_values["rev_grid"])
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self._display_gbox.setTitle(self._gbox_descs[0])
self._gridvls_gbox.setTitle(self._gbox_descs[2])
self._info_gbox.setTitle(self._gbox_descs[3])
self._color_sys_gbox.setTitle(self._gbox_descs[4])
-
self._cbox_major.setText(self._info_descs[0])
self._cbox_minor.setText(self._info_descs[1])
-
self.rhc_govalue.set_prefix_text((self._assistp_descs[0], self._assistp_descs[1]))
self.sdt_col.set_text(self._assistp_descs[3])
self.sdt_sum_factor.set_text(self._assistp_descs[4])
self.sdt_dim_factor.set_text(self._assistp_descs[5])
self.sdt_assist_factor.set_text(self._assistp_descs[6])
self.ckb_rev_grid.setText(self._assistp_descs[7])
-
for i in range(4):
self._color_sys_btns[i].setText(self._color_sys_descs[i])
-
self.update_mode()
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._gbox_descs = (
_translate("Mode", "Display"),
_translate("Mode", "Assistant"),
@@ -294,19 +208,16 @@ def _func_tr_(self):
_translate("Mode", "Info"),
_translate("Mode", "Color Space"),
)
-
self._info_descs = (
_translate("Mode", "Show Major Info"),
_translate("Mode", "Show Minor Info"),
)
-
self._color_sys_descs = (
_translate("Mode", "RGB Space"),
_translate("Mode", "Rev RGB Space"),
_translate("Mode", "RYB Space"),
_translate("Mode", "Rev RYB Space"),
)
-
self._assistp_descs = (
_translate("Mode", "Select"),
_translate("Mode", "Selected: "),
diff --git a/src/main/python/wgets/operation.py b/src/main/python/wgets/operation.py
index e1d3877..a36dc1c 100644
--- a/src/main/python/wgets/operation.py
+++ b/src/main/python/wgets/operation.py
@@ -26,375 +26,242 @@
class Operation(QWidget):
- """
- Operation object based on QWidget. Init a operation in operation.
- """
-
ps_update = pyqtSignal(bool)
ps_opened = pyqtSignal(bool)
ps_functn = pyqtSignal(int)
def __init__(self, wget, args):
- """
- Init operation.
- """
-
super().__init__(wget)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
- # load translations.
self._func_tr_()
-
- # init qt args.
operation_grid_layout = QGridLayout(self)
operation_grid_layout.setContentsMargins(0, 0, 0, 0)
operation_grid_layout.setHorizontalSpacing(0)
operation_grid_layout.setVerticalSpacing(0)
-
scroll_area = QScrollArea(self)
scroll_area.setFrameShape(QFrame.Box)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setWidgetResizable(True)
operation_grid_layout.addWidget(scroll_area)
-
scroll_contents = QWidget()
scroll_grid_layout = QGridLayout(scroll_contents)
scroll_grid_layout.setContentsMargins(3, 9, 3, 3)
scroll_grid_layout.setHorizontalSpacing(3)
scroll_grid_layout.setVerticalSpacing(12)
scroll_area.setWidget(scroll_contents)
-
- # file functional region.
self._file_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._file_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._file_gbox, 0, 1, 1, 1)
-
self.import_btn = QPushButton(self._file_gbox)
gbox_grid_layout.addWidget(self.import_btn, 0, 1, 1, 1)
self.import_btn.clicked.connect(self.exec_import)
-
self.export_btn = QPushButton(self._file_gbox)
gbox_grid_layout.addWidget(self.export_btn, 1, 1, 1, 1)
self.export_btn.clicked.connect(self.exec_export)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 2, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 2, 1, 1)
-
- # view functional region.
self._view_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._view_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._view_gbox, 1, 1, 1, 1)
-
self.functn = []
-
- # 0 create color set.
- # 1 reset.
- #
- # 2 open image.
- # 3 save image.
- # 4 pick-up.
- #
- # 5 save image.
- # 6 switch fix.
- # 7 switch ref.
- # 8 reset.
- #
- # 9 attach set.
- # 10 export set.
- # 11 detail set.
-
self.functn.append(QPushButton(self._view_gbox))
gbox_grid_layout.addWidget(self.functn[0], 0, 1, 1, 1)
self.functn[0].clicked.connect(lambda x: self.ps_functn.emit(0))
-
self.functn.append(QPushButton(self._view_gbox))
gbox_grid_layout.addWidget(self.functn[1], 1, 1, 1, 1)
self.functn[1].clicked.connect(lambda x: self.ps_functn.emit(1))
-
self.functn.append(QPushButton(self._view_gbox))
gbox_grid_layout.addWidget(self.functn[2], 2, 1, 1, 1)
self.functn[2].clicked.connect(lambda x: self.ps_functn.emit(2))
-
self.functn.append(QPushButton(self._view_gbox))
gbox_grid_layout.addWidget(self.functn[3], 3, 1, 1, 1)
self.functn[3].clicked.connect(lambda x: self.ps_functn.emit(3))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 4, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 4, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 4, 2, 1, 1)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def sizeHint(self):
- return QSize(210, 145)
+ return QSize(250, 145)
def exec_open(self, value):
- """
- Exec open operation.
- """
-
cb_filter = "{} (*.dpc; *.json);; {} (*.dpc);; {} (*.json)".format(self._file_descs[7], self._file_descs[4], self._file_descs[0])
cb_file = QFileDialog.getOpenFileName(None, self._operation_descs[6], self._args.usr_color, filter=cb_filter)
-
if cb_file[0]:
self._args.usr_color = os.path.dirname(os.path.abspath(cb_file[0]))
-
else:
- # closed without open a file.
return
-
self.dp_open(cb_file[0])
def dp_open(self, depot_file, direct_dict=False, dp_path=""):
- """
- Open a color depot file.
- """
-
color_dict = {}
curr_path = str(dp_path)
-
if direct_dict:
color_dict = depot_file
-
else:
curr_path = os.path.dirname(depot_file)
-
try:
with open(depot_file, "r", encoding="utf-8") as f:
color_dict = json.load(f)
-
except Exception as err:
self.warning(self._operation_errs[1] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
if not isinstance(color_dict, dict):
self.warning(self._operation_errs[2])
return
-
if "version" in color_dict:
vid = self._args.check_version_d(color_dict["version"])
-
if vid == 0 or vid > 3:
self.warning(self._operation_errs[3])
return
-
else:
self.warning(self._operation_errs[4])
return
-
if "type" in color_dict and "palettes" in color_dict:
if color_dict["type"] == "depot":
color_palettes = color_dict["palettes"]
-
elif color_dict["type"] == "set":
self.warning(self._operation_errs[15])
return
-
else:
self.warning(self._operation_errs[11])
return
-
else:
self.warning(self._operation_errs[12] + "\n{}\n{}".format(self._operation_errs[17], "type; palettes"))
return
-
finished_errs = []
color_list = []
-
if not isinstance(color_palettes, (tuple, list)):
self.warning(self._operation_errs[13] + "\n{}\n{}".format(self._operation_errs[17], "\"{}\" is not a list.".format(str(color_palettes)[:100] + " ...")))
return
-
for color_idx in range(len(color_palettes)):
color = color_palettes[color_idx]
hsv_set = []
broken_errs = []
-
if not isinstance(color, dict):
broken_errs.append("[id {}] {}".format(color_idx + 1, "\"{}\" is not a dict.".format(str(color)[25] + " ...")))
-
if broken_errs:
finished_errs += list(broken_errs)
continue
-
for i in range(5):
if broken_errs:
break
-
if "color_{}".format(i) in color:
hsv_tuple = (0.0, 0.0, 1.0)
-
if "hsv" in color["color_{}".format(i)]:
try:
hsv_tuple = Color.fmt_hsv(color["color_{}".format(i)]["hsv"]).tolist()
-
except Exception as err:
broken_errs.append("[id {}] {}".format(color_idx + 1, str(err)))
-
elif "rgb" in color["color_{}".format(i)]:
try:
hsv_tuple = Color.rgb2hsv(color["color_{}".format(i)]["rgb"]).tolist()
-
except Exception as err:
broken_errs.append("[id {}] {}".format(color_idx + 1, str(err)))
-
elif "hex_code" in color["color_{}".format(i)]:
try:
hsv_tuple = Color.hec2hsv(color["color_{}".format(i)]["hex_code"]).tolist()
-
except Exception as err:
broken_errs.append("[id {}] {}".format(color_idx + 1, str(err)))
-
elif "hex code" in color["color_{}".format(i)]:
try:
hsv_tuple = Color.hec2hsv(color["color_{}".format(i)]["hex code"]).tolist()
-
except Exception as err:
broken_errs.append("[id {}] {}".format(color_idx + 1, str(err)))
-
else:
broken_errs.append("[id {}] hsv value is not found.".format(color_idx + 1))
-
hsv_set.append(tuple(hsv_tuple))
-
else:
broken_errs.append("[id {}] {}".format(color_idx + 1, "\"color_{}\" is not found in color dict.".format(i)))
-
if broken_errs:
finished_errs += list(broken_errs)
continue
-
if "name" in color:
cr_name = str(color["name"])
-
else:
cr_name = ""
-
if "desc" in color:
cr_desc = str(color["desc"])
cr_desc = cr_desc.replace("$curr_path$", curr_path)
cr_desc = cr_desc.replace("$os_sep$", os.sep)
-
else:
cr_desc = ""
-
if "time" in color:
cr_time = fmt_im_time(color["time"])
-
else:
cr_time = (0, 0)
-
if "grid_locations" in color and "grid_assitlocs" in color:
grid_locations = color["grid_locations"]
grid_assitlocs = color["grid_assitlocs"]
-
else:
grid_locations = []
grid_assitlocs = []
-
if "grid_list" in color:
grid_list = color["grid_list"]
-
else:
grid_list = []
-
if "grid_values" in color:
grid_values = color["grid_values"]
-
else:
grid_values = {}
-
grid_locations, grid_assitlocs = norm_grid_locations(grid_locations, grid_assitlocs)
grid_list = norm_grid_list(grid_list)
grid_values = norm_grid_values(grid_values)
-
if len(hsv_set) == 5:
if "rule" in color and color["rule"] in self._args.global_hm_rules:
color_list.append((tuple(hsv_set), color["rule"], cr_name, cr_desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values))
-
else:
broken_errs.append("[id {}] color rule is not found.".format(color_idx + 1))
-
else:
broken_errs.append("[id {}] colors are not complete.".format(color_idx + 1))
-
finished_errs += list(broken_errs)
-
if finished_errs:
self.warning(self._operation_errs[14] + "\n{}\n{}".format(self._operation_errs[17], "; ".join(finished_errs)))
-
for unit_cell in self._args.stab_ucells:
if hasattr(unit_cell, "close"):
unit_cell.close()
-
self._args.stab_ucells = tuple(color_list)
self.ps_opened.emit(True)
def exec_save(self, value):
- """
- Exec save operation.
- """
-
name = "{}".format(time.strftime("Rickrack_Depot_%Y_%m_%d.dpc", time.localtime()))
-
cb_filter = "{} (*.dpc);; {} (*.txt);; {} (*.aco);; {} (*.ase);; {} (*.gpl);; {} (*.xml)".format(self._file_descs[4], self._file_descs[1], self._file_descs[2], self._file_descs[8], self._file_descs[5], self._file_descs[6])
cb_file = QFileDialog.getSaveFileName(None, self._operation_descs[7], os.sep.join((self._args.usr_color, name)), filter=cb_filter)
-
if cb_file[0]:
self._args.usr_color = os.path.dirname(os.path.abspath(cb_file[0]))
-
else:
- # closed without open a file.
return
-
self.dp_save(cb_file[0], value)
def dp_save(self, depot_file, value):
- """
- Save a color depot file.
- """
-
- # load color set from unit cells, which is different from export.
color_list = []
-
for unit_cell in self._args.stab_ucells[:-1]:
if unit_cell != None:
color_list.append((unit_cell.color_set, unit_cell.hm_rule, unit_cell.name, unit_cell.desc, unit_cell.cr_time, unit_cell.grid_locations, unit_cell.grid_assitlocs, unit_cell.grid_list, unit_cell.grid_values))
-
- # process start.
if depot_file.split(".")[-1].lower() in ("dpc", "json", "temp"):
color_dict = {"version": self._args.info_version_en, "site": self._args.info_main_site, "type": "depot"}
color_dict["palettes"] = export_list(color_list)
-
try:
with open(depot_file, "w", encoding="utf-8") as f:
json.dump(color_dict, f, indent=4, ensure_ascii=False)
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif depot_file.split(".")[-1].lower() == "txt":
try:
with open(depot_file, "w", encoding="utf-8") as f:
@@ -403,159 +270,115 @@ def dp_save(self, depot_file, value):
f.write("# Version: {}\n".format(self._args.info_version_en))
f.write("# Total: {}\n\n".format(len(color_list)))
f.write(export_text(color_list))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif depot_file.split(".")[-1].lower() == "aco":
try:
with open(depot_file, "wb") as f:
f.write(export_swatch(color_list, ctp=self._args.export_swatch_ctp, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
if self._args.export_grid_extns:
grid_file = depot_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "wb") as f:
f.write(export_swatch(color_list, ctp=self._args.export_swatch_ctp, export_grid=True, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif depot_file.split(".")[-1].lower() == "ase":
try:
with open(depot_file, "wb") as f:
f.write(export_ase(color_list, ctp=self._args.export_swatch_ctp, asetp=self._args.export_ase_type, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
if self._args.export_grid_extns:
grid_file = depot_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "wb") as f:
f.write(export_ase(color_list, ctp=self._args.export_swatch_ctp, asetp=self._args.export_ase_type, export_grid=True, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif depot_file.split(".")[-1].lower() == "gpl":
try:
with open(depot_file, "w", encoding="utf-8") as f:
f.write(export_gpl(color_list))
-
if self._args.export_grid_extns:
grid_file = depot_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "w", encoding="utf-8") as f:
f.write(export_gpl(color_list, export_grid=True))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif depot_file.split(".")[-1].lower() == "xml":
try:
with open(depot_file, "w", encoding="utf-8") as f:
f.write(export_xml(color_list))
-
if self._args.export_grid_extns:
grid_file = depot_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "w", encoding="utf-8") as f:
f.write(export_xml(color_list, export_grid=True))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
else:
self.warning(self._operation_errs[10])
def exec_import(self, value):
- """
- Exec import operation.
- """
-
cb_filter = "{} (*.dps; *.json; *.txt; *.aco; *.ase; *.gpl; *.xml);; {} (*.dps);; {} (*.json);; {} (*.txt);; {} (*.aco);; {} (*.ase);; {} (*.gpl);; {} (*.xml)".format(self._file_descs[7], self._file_descs[3], self._file_descs[0], self._file_descs[1], self._file_descs[2], self._file_descs[8], self._file_descs[5], self._file_descs[6])
cb_file = QFileDialog.getOpenFileName(None, self._operation_descs[0], self._args.usr_color, filter=cb_filter)
-
if cb_file[0]:
self._args.usr_color = os.path.dirname(os.path.abspath(cb_file[0]))
-
else:
- # closed without open a file.
return
-
self.dp_import(cb_file[0])
def dp_import(self, set_file, direct_dict=False, return_set=False):
- """
- Import a color set file.
- """
-
color_dict = {}
-
if direct_dict:
color_dict = set_file
-
elif set_file.split(".")[-1].lower() in ("txt", "aco", "ase", "gpl", "xml"):
grid_list = []
name_list = []
-
if set_file.split(".")[-1].lower() == "txt":
try:
grid_list, name_list = import_text(set_file)
-
except Exception as err:
self.warning(self._operation_errs[19] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
if set_file.split(".")[-1].lower() == "aco":
try:
grid_list, name_list = import_swatch(set_file, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer])
-
except Exception as err:
self.warning(self._operation_errs[20] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
if set_file.split(".")[-1].lower() == "ase":
try:
grid_list, name_list = import_ase(set_file, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer])
-
except Exception as err:
self.warning(self._operation_errs[20] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
if set_file.split(".")[-1].lower() == "gpl":
try:
grid_list, name_list = import_gpl(set_file)
-
except Exception as err:
self.warning(self._operation_errs[21] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
if set_file.split(".")[-1].lower() == "xml":
try:
grid_list, name_list = import_xml(set_file)
-
except Exception as err:
self.warning(self._operation_errs[22] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
imp_color_2 = "FFFFFF" if len(grid_list) < 1 else grid_list[0]
imp_color_1 = "FFFFFF" if len(grid_list) < 2 else grid_list[1]
imp_color_0 = "FFFFFF" if len(grid_list) < 3 else grid_list[2]
imp_color_3 = "FFFFFF" if len(grid_list) < 4 else grid_list[3]
imp_color_4 = "FFFFFF" if len(grid_list) < 5 else grid_list[4]
-
color_dict = {
"version": self._args.info_version_en,
"type": "set",
@@ -575,138 +398,102 @@ def dp_import(self, set_file, direct_dict=False, return_set=False):
}
]
}
-
else:
with open(set_file, "r", encoding="utf-8") as f:
try:
color_dict = json.load(f)
-
except Exception as err:
self.warning(self._operation_errs[1] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
if not isinstance(color_dict, dict):
self.warning(self._operation_errs[2])
return
-
if "version" in color_dict:
vid = self._args.check_version_s(color_dict["version"])
-
if vid == 0 or vid > 3:
self.warning(self._operation_errs[3])
return
-
else:
self.warning(self._operation_errs[4])
return
-
if "type" in color_dict and "palettes" in color_dict:
if color_dict["type"] == "set":
- #
- # color_dict is reset here.
color_dict = color_dict["palettes"][0]
-
elif color_dict["type"] == "depot":
self.warning(self._operation_errs[16])
return
-
else:
self.warning(self._operation_errs[11])
return
-
else:
self.warning(self._operation_errs[12] + "\n{}\n{}".format(self._operation_errs[17], "type; palettes"))
return
-
color_set = []
-
for i in range(5):
if "color_{}".format(i) in color_dict:
curr_color = Color((0.0, 0.0, 1.0), tp="hsv")
-
if "hsv" in color_dict["color_{}".format(i)]:
try:
hsv = color_dict["color_{}".format(i)]["hsv"]
curr_color = Color(hsv, tp="hsv", overflow=self._args.sys_color_set.get_overflow())
-
except Exception as err:
self.warning(self._operation_errs[5] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif "rgb" in color_dict["color_{}".format(i)]:
try:
hsv = color_dict["color_{}".format(i)]["rgb"]
curr_color = Color(hsv, tp="rgb", overflow=self._args.sys_color_set.get_overflow())
-
except Exception as err:
self.warning(self._operation_errs[5] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif "hex_code" in color_dict["color_{}".format(i)]:
try:
hsv = color_dict["color_{}".format(i)]["hex_code"]
curr_color = Color(hsv, tp="hec", overflow=self._args.sys_color_set.get_overflow())
-
except Exception as err:
self.warning(self._operation_errs[5] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif "hex code" in color_dict["color_{}".format(i)]:
try:
hsv = color_dict["color_{}".format(i)]["hex code"]
curr_color = Color(hsv, tp="hec", overflow=self._args.sys_color_set.get_overflow())
-
except Exception as err:
self.warning(self._operation_errs[5] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
else:
self.warning(self._operation_errs[6] + "\n{}\n{}".format(self._operation_errs[17], "hsv"))
return
-
color_set.append(curr_color)
-
else:
self.warning(self._operation_errs[7] + "\n{}\n{}".format(self._operation_errs[17], "color_{}".format(i)))
return
-
if "rule" in color_dict:
if color_dict["rule"] in self._args.global_hm_rules:
grid_locations = []
grid_assitlocs = []
grid_list = []
grid_values = {}
-
if "grid_locations" in color_dict and "grid_assitlocs" in color_dict:
grid_locations = color_dict["grid_locations"]
grid_assitlocs = color_dict["grid_assitlocs"]
-
if "grid_list" in color_dict:
grid_list = color_dict["grid_list"]
-
if "grid_values" in color_dict:
grid_values = color_dict["grid_values"]
-
grid_locations, grid_assitlocs = norm_grid_locations(grid_locations, grid_assitlocs)
grid_list = norm_grid_list(grid_list)
grid_values = norm_grid_values(grid_values)
-
if return_set:
set_name = ""
set_desc = ""
set_time = (0, 0)
-
if "name" in color_dict:
set_name = str(color_dict["name"])
-
if "desc" in color_dict:
set_desc = str(color_dict["desc"])
-
if "time" in color_dict:
set_time = fmt_im_time(color_dict["time"])
-
return (color_set, color_dict["rule"], set_name, set_desc, set_time, grid_locations, grid_assitlocs, grid_list, grid_values)
-
else:
self._args.hm_rule = color_dict["rule"]
self._args.sys_color_set.recover(color_set)
@@ -714,49 +501,30 @@ def dp_import(self, set_file, direct_dict=False, return_set=False):
self._args.sys_grid_assitlocs = grid_assitlocs
self._args.sys_grid_list = grid_list
self._args.sys_grid_values = grid_values
-
self._args.sys_activated_assit_idx = -1
self._args.sys_assit_color_locs = [[None for j in self._args.sys_grid_assitlocs[i]] for i in range(5)]
-
else:
self.warning(self._operation_errs[8] + "\n{}\n{}".format(self._operation_errs[17], color_dict["rule"]))
return
-
else:
self.warning(self._operation_errs[9] + "\n{}\n{}".format(self._operation_errs[17], "rule"))
return
-
self.ps_update.emit(True)
def exec_export(self, value):
- """
- Exec export operation.
- """
-
name = "{}".format(time.strftime("Rickrack_Set_%Y_%m_%d.dps", time.localtime()))
-
cb_filter = "{} (*.dps);; {} (*.txt);; {} (*.aco);; {} (*.ase);; {} (*.gpl);; {} (*.xml)".format(self._file_descs[3], self._file_descs[1], self._file_descs[2], self._file_descs[8], self._file_descs[5], self._file_descs[6])
cb_file = QFileDialog.getSaveFileName(None, self._operation_descs[1], os.sep.join((self._args.usr_color, name)), filter=cb_filter)
-
if cb_file[0]:
self._args.usr_color = os.path.dirname(os.path.abspath(cb_file[0]))
-
else:
- # closed without open a file.
return
-
self.dp_export(cb_file[0], value)
def dp_export(self, set_file, value):
- """
- Export a color set file.
- """
-
- # load color set from sys or depot, which is different from save.
color_set = None
hm_rule = None
desc = ""
-
if isinstance(value, bool):
color_set = self._args.sys_color_set
hm_rule = self._args.hm_rule
@@ -767,7 +535,6 @@ def dp_export(self, set_file, value):
grid_assitlocs = self._args.sys_grid_assitlocs
grid_list = self._args.sys_grid_list
grid_values = self._args.sys_grid_values
-
else:
color_set = self._args.stab_ucells[value].color_set
hm_rule = self._args.stab_ucells[value].hm_rule
@@ -778,26 +545,18 @@ def dp_export(self, set_file, value):
grid_assitlocs = self._args.stab_ucells[value].grid_assitlocs
grid_list = self._args.stab_ucells[value].grid_list
grid_values = self._args.stab_ucells[value].grid_values
-
color_list = [(color_set, hm_rule, cr_name, cr_desc, cr_time, grid_locations, grid_assitlocs, grid_list, grid_values),]
-
- # process start.
if set_file.split(".")[-1].lower() in ("dps", "json", "temp"):
color_dict = {"version": self._args.info_version_en, "site": self._args.info_main_site, "type": "set"}
color_dict["palettes"] = export_list(color_list)
-
- # delete the time of palette in color set temp file. for hash compare in main.py.
if set_file.split(".")[-1].lower() == "temp":
color_dict["palettes"][0]["time"] = [0, 0]
-
try:
with open(set_file, "w", encoding="utf-8") as f:
json.dump(color_dict, f, indent=4, ensure_ascii=False)
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif set_file.split(".")[-1].lower() == "txt":
try:
with open(set_file, "w", encoding="utf-8") as f:
@@ -806,107 +565,77 @@ def dp_export(self, set_file, value):
f.write("# Version: {}\n".format(self._args.info_version_en))
f.write("# Total: {}\n\n".format(len(color_list)))
f.write(export_text(color_list))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif set_file.split(".")[-1].lower() == "aco":
try:
with open(set_file, "wb") as f:
f.write(export_swatch(color_list, ctp=self._args.export_swatch_ctp, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
if self._args.export_grid_extns:
grid_file = set_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "wb") as f:
f.write(export_swatch(color_list, ctp=self._args.export_swatch_ctp, export_grid=True, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif set_file.split(".")[-1].lower() == "ase":
try:
with open(set_file, "wb") as f:
f.write(export_ase(color_list, ctp=self._args.export_swatch_ctp, asetp=self._args.export_ase_type, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
if self._args.export_grid_extns:
grid_file = set_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "wb") as f:
f.write(export_ase(color_list, ctp=self._args.export_swatch_ctp, asetp=self._args.export_ase_type, export_grid=True, white_ref=self._args.global_white_ref[self._args.white_illuminant][self._args.white_observer]))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif set_file.split(".")[-1].lower() == "gpl":
try:
with open(set_file, "w", encoding="utf-8") as f:
f.write(export_gpl(color_list))
-
if self._args.export_grid_extns:
grid_file = set_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "w", encoding="utf-8") as f:
f.write(export_gpl(color_list, export_grid=True))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
elif set_file.split(".")[-1].lower() == "xml":
try:
with open(set_file, "w", encoding="utf-8") as f:
f.write(export_xml(color_list))
-
if self._args.export_grid_extns:
grid_file = set_file.split(".")
grid_file[-2] = grid_file[-2] + self._args.export_grid_extns
grid_file = ".".join(grid_file)
-
with open(grid_file, "w", encoding="utf-8") as f:
f.write(export_xml(color_list, export_grid=True))
-
except Exception as err:
self.warning(self._operation_errs[23] + "\n{}\n{}".format(self._operation_errs[17], err))
return
-
else:
self.warning(self._operation_errs[10])
def show_import_export(self):
- """
- Show import and export and hide open and save.
- """
-
self.import_btn.clicked.disconnect()
self.export_btn.clicked.disconnect()
-
self.import_btn.clicked.connect(self.exec_import)
self.export_btn.clicked.connect(self.exec_export)
-
self.import_btn.setText(self._operation_descs[0])
self.export_btn.setText(self._operation_descs[1])
def show_open_and_save(self):
- """
- Show open and save and hide import and export.
- """
-
self.import_btn.clicked.disconnect()
self.export_btn.clicked.disconnect()
-
self.import_btn.clicked.connect(self.exec_open)
self.export_btn.clicked.connect(self.exec_save)
-
self.import_btn.setText(self._operation_descs[6])
self.export_btn.setText(self._operation_descs[7])
@@ -916,75 +645,47 @@ def warning(self, text):
box.setText(text)
box.setIcon(QMessageBox.Warning)
box.addButton(self._operation_errs[18], QMessageBox.AcceptRole)
-
box.exec_()
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self._file_gbox.setTitle(self._gbox_descs[0])
self._view_gbox.setTitle(self._gbox_descs[1])
-
self.import_btn.setText(self._operation_descs[0])
self.export_btn.setText(self._operation_descs[1])
-
def update_functn_text(self, view_idx=0):
- # 0 create color set.
- # 1 reset.
- #
- # 2 open image.
- # 3 save image.
- # 4 pick-up.
- #
- # 5 save image.
- # 6 switch fix.
- # 7 switch ref.
- # 8 reset.
- #
- # 9 attach set.
- # 10 export set.
- # 11 detail set.
-
if view_idx == 0:
# self.functn[0].show()
# self.functn[1].show()
# self.functn[2].show()
# self.functn[3].hide()
-
self.functn[0].setText(self._shortcut_descs[12])
self.functn[1].setText(self._shortcut_descs[0])
self.functn[2].setText(self._shortcut_descs[1])
self.functn[3].setText(self._shortcut_descs[13])
-
elif view_idx == 1:
# self.functn[0].show()
# self.functn[1].show()
# self.functn[2].show()
# self.functn[3].hide()
-
self.functn[0].setText(self._shortcut_descs[2])
self.functn[1].setText(self._shortcut_descs[3])
self.functn[2].setText(self._shortcut_descs[4])
self.functn[3].setText(self._shortcut_descs[13])
-
elif view_idx == 2:
# self.functn[0].show()
# self.functn[1].show()
# self.functn[2].show()
# self.functn[3].show()
-
self.functn[0].setText(self._shortcut_descs[5])
self.functn[1].setText(self._shortcut_descs[6])
self.functn[2].setText(self._shortcut_descs[7])
self.functn[3].setText(self._shortcut_descs[8])
-
elif view_idx == 3:
# self.functn[0].show()
# self.functn[1].show()
# self.functn[2].show()
# self.functn[3].hide()
-
self.functn[1].setText(self._shortcut_descs[9])
self.functn[2].setText(self._shortcut_descs[10])
self.functn[3].setText(self._shortcut_descs[11])
@@ -992,12 +693,10 @@ def update_functn_text(self, view_idx=0):
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._gbox_descs = (
_translate("MainWindow", "File"),
_translate("MainWindow", "View"),
)
-
self._shortcut_descs = (
_translate("MainWindow", "Create Colors"),
_translate("Wheel", "Reset"),
@@ -1015,7 +714,6 @@ def _func_tr_(self):
_translate("Wheel", "Generate Palette"),
_translate("Depot", "Import Color Set"),
)
-
self._operation_descs = (
_translate("MainWindow", "Import"),
_translate("MainWindow", "Export"),
@@ -1026,7 +724,6 @@ def _func_tr_(self):
_translate("MainWindow", "Open"),
_translate("MainWindow", "Save"),
)
-
self._sub_descs = (
_translate("Rickrack", "{} ({})"),
_translate("MainWindow", "Wheel"),
@@ -1034,7 +731,6 @@ def _func_tr_(self):
_translate("MainWindow", "Board"),
_translate("MainWindow", "Depot"),
)
-
self._file_descs = (
_translate("Operation", "Rickrack Json File"),
_translate("Operation", "Plain Text File"),
@@ -1046,11 +742,9 @@ def _func_tr_(self):
_translate("Operation", "All Acceptable Files"),
_translate("Operation", "Adobe Exchange File"),
)
-
self._import_descs = (
_translate("Operation", "This color set is imported from file at {}."),
)
-
self._operation_errs = (
_translate("Operation", "Error"),
_translate("Operation", "Import color file error. Color file is broken."),
@@ -1077,7 +771,6 @@ def _func_tr_(self):
_translate("Operation", "Import color list from Pencil palette file error."),
_translate("Operation", "Export color file error."),
)
-
self.main_errs = (
_translate("Operation", "Could not load settings. Settings file is broken. Old settings file has been backed up as 'settings_bak.json'."),
_translate("Operation", "Could not load settings. Version does not match. Old settings file has been backed up as 'settings_bak.json'."),
diff --git a/src/main/python/wgets/rule.py b/src/main/python/wgets/rule.py
index 609d1e7..349eb2e 100644
--- a/src/main/python/wgets/rule.py
+++ b/src/main/python/wgets/rule.py
@@ -18,150 +18,98 @@
class Rule(QWidget):
- """
- Rule object based on QWidget. Init a rule in rule.
- """
-
ps_rule_changed = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init rule.
- """
-
super().__init__(wget)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
- # load translations.
self._func_tr_()
-
- # init qt args.
rule_grid_layout = QGridLayout(self)
rule_grid_layout.setContentsMargins(0, 0, 0, 0)
rule_grid_layout.setHorizontalSpacing(0)
rule_grid_layout.setVerticalSpacing(0)
-
scroll_area = QScrollArea(self)
scroll_area.setFrameShape(QFrame.Box)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setWidgetResizable(True)
rule_grid_layout.addWidget(scroll_area)
-
scroll_contents = QWidget()
scroll_grid_layout = QGridLayout(scroll_contents)
scroll_grid_layout.setContentsMargins(3, 9, 3, 3)
scroll_grid_layout.setHorizontalSpacing(3)
scroll_grid_layout.setVerticalSpacing(12)
scroll_area.setWidget(scroll_contents)
-
self._rule_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._rule_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(16)
scroll_grid_layout.addWidget(self._rule_gbox, 0, 1, 1, 1)
-
self._rule_btns = []
for i in range(8):
btn = QRadioButton(self._rule_gbox)
gbox_grid_layout.addWidget(btn, i, 0, 1, 1)
-
btn.clicked.connect(self.modify_rule(i))
self._rule_btns.append(btn)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 8, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 8, 1, 1, 1)
-
self._synchronization_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._synchronization_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(16)
scroll_grid_layout.addWidget(self._synchronization_gbox, 1, 1, 1, 1)
-
self._synchronization_btns = []
-
for i in range(7):
btn = QRadioButton(self._synchronization_gbox)
gbox_grid_layout.addWidget(btn, i, 0, 1, 1)
-
btn.clicked.connect(self.modify_synchronization(i))
self._synchronization_btns.append(btn)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 7, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 7, 1, 1, 1)
-
self.update_rule()
self._synchronization_btns[self._args.sys_color_set.synchronization].setChecked(True)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def sizeHint(self):
- return QSize(210, 90)
+ return QSize(250, 90)
def modify_rule(self, idx):
- """
- Modify stored rule set by btn.
- """
-
def _func_(value):
self._args.hm_rule = self._args.global_hm_rules[idx]
self.ps_rule_changed.emit(True)
-
return _func_
def modify_synchronization(self, idx):
- """
- Modify stored synchronization set by btn.
- """
-
def _func_(value):
self._args.sys_color_set.synchronization = idx
- # synchronization works in mouse moving event in wheel.
# self.ps_rule_changed.emit(True)
-
return _func_
def update_rule(self):
- """
- Update rule btn by self._args.hm_rule.
- """
-
idx = self._args.global_hm_rules.index(self._args.hm_rule)
self._rule_btns[idx].setChecked(True)
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self._rule_gbox.setTitle(self._gbox_descs[0])
self._synchronization_gbox.setTitle(self._gbox_descs[1])
-
for i in range(8):
self._rule_btns[i].setText(self._rule_descs[i])
-
for i in range(7):
self._synchronization_btns[i].setText(self._synchronization_descs[i])
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._gbox_descs = (
_translate("Channel", "Harmony"),
_translate("Channel", "Synchronization"),
)
-
self._rule_descs = (
_translate("Rule", "Analogous"),
_translate("Rule", "Monochromatic"),
@@ -172,7 +120,6 @@ def _func_tr_(self):
_translate("Rule", "Shades"),
_translate("Rule", "Custom"),
)
-
self._synchronization_descs = (
_translate("Rule", "Unlimited"),
_translate("Rule", "H Locked"),
diff --git a/src/main/python/wgets/script.py b/src/main/python/wgets/script.py
index 53f807f..f99011d 100644
--- a/src/main/python/wgets/script.py
+++ b/src/main/python/wgets/script.py
@@ -19,10 +19,6 @@
class Script(QWidget):
- """
- Script object based on QWidget. Init a script in script.
- """
-
ps_filter = pyqtSignal(tuple)
ps_crop = pyqtSignal(bool)
ps_freeze = pyqtSignal(bool)
@@ -30,247 +26,176 @@ class Script(QWidget):
ps_extract = pyqtSignal(int)
def __init__(self, wget, args):
- """
- Init operation.
- """
-
super().__init__(wget)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
- # load translations.
self._func_tr_()
-
- # init qt args.
script_grid_layout = QGridLayout(self)
script_grid_layout.setContentsMargins(0, 0, 0, 0)
script_grid_layout.setHorizontalSpacing(0)
script_grid_layout.setVerticalSpacing(0)
-
scroll_area = QScrollArea(self)
scroll_area.setFrameShape(QFrame.Box)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setWidgetResizable(True)
script_grid_layout.addWidget(scroll_area)
-
scroll_contents = QWidget()
scroll_grid_layout = QGridLayout(scroll_contents)
scroll_grid_layout.setContentsMargins(3, 9, 3, 3)
scroll_grid_layout.setHorizontalSpacing(3)
scroll_grid_layout.setVerticalSpacing(12)
scroll_area.setWidget(scroll_contents)
-
- # filter functional region.
self._filter_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._filter_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._filter_gbox, 1, 1, 1, 1)
-
self._filter_btns = []
for i in range(10):
btn = QPushButton(self._filter_gbox)
self._filter_btns.append(btn)
-
gbox_grid_layout.addWidget(self._filter_btns[0], 0, 1, 1, 1)
self._filter_btns[0].clicked.connect(lambda x: self.ps_filter.emit(("BLUR", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[1], 1, 1, 1, 1)
self._filter_btns[1].clicked.connect(lambda x: self.ps_filter.emit(("CONTOUR", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[2], 2, 1, 1, 1)
self._filter_btns[2].clicked.connect(lambda x: self.ps_filter.emit(("DETAIL", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[3], 3, 1, 1, 1)
self._filter_btns[3].clicked.connect(lambda x: self.ps_filter.emit(("EDGE_ENHANCE", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[4], 4, 1, 1, 1)
self._filter_btns[4].clicked.connect(lambda x: self.ps_filter.emit(("EDGE_ENHANCE_MORE", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[5], 5, 1, 1, 1)
self._filter_btns[5].clicked.connect(lambda x: self.ps_filter.emit(("EMBOSS", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[6], 6, 1, 1, 1)
self._filter_btns[6].clicked.connect(lambda x: self.ps_filter.emit(("FIND_EDGES", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[7], 7, 1, 1, 1)
self._filter_btns[7].clicked.connect(lambda x: self.ps_filter.emit(("SHARPEN", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[8], 8, 1, 1, 1)
self._filter_btns[8].clicked.connect(lambda x: self.ps_filter.emit(("SMOOTH", None)))
-
gbox_grid_layout.addWidget(self._filter_btns[9], 9, 1, 1, 1)
self._filter_btns[9].clicked.connect(lambda x: self.ps_filter.emit(("SMOOTH_MORE", None)))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 10, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 10, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 10, 2, 1, 1)
-
- # zoom functional region.
self._zoom_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._zoom_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._zoom_gbox, 4, 1, 1, 1)
-
self.sdt_zoom = SlideText(self._zoom_gbox, num_range=(0.0, 3.0), default_value=1.0)
gbox_grid_layout.addWidget(self.sdt_zoom, 0, 1, 1, 1)
self.sdt_zoom.ps_value_changed.connect(self.update_zoom)
-
self.btn_zoom = QPushButton(self._zoom_gbox)
gbox_grid_layout.addWidget(self.btn_zoom, 1, 1, 1, 1)
self.btn_zoom.clicked.connect(lambda x: self.ps_filter.emit(("ZOOM", self.sdt_zoom.get_value())))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 2, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 2, 1, 1)
-
- # crop functional region.
self._crop_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._crop_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._crop_gbox, 3, 1, 1, 1)
-
self.btn_crop = QPushButton(self._crop_gbox)
gbox_grid_layout.addWidget(self.btn_crop, 0, 1, 1, 1)
self.btn_crop.clicked.connect(lambda x: self.ps_crop.emit(True))
-
self.btn_cancel = QPushButton(self._crop_gbox)
gbox_grid_layout.addWidget(self.btn_cancel, 1, 1, 1, 1)
self.btn_cancel.clicked.connect(lambda x: self.ps_crop.emit(False))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 2, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 2, 1, 1)
-
- # snap functional region.
self._snap_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._snap_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._snap_gbox, 2, 1, 1, 1)
-
self.btn_freeze = QPushButton(self._snap_gbox)
gbox_grid_layout.addWidget(self.btn_freeze, 0, 1, 1, 1)
self.btn_freeze.clicked.connect(lambda x: self.ps_freeze.emit(True))
-
self.btn_print = QPushButton(self._snap_gbox)
gbox_grid_layout.addWidget(self.btn_print, 1, 1, 1, 1)
self.btn_print.clicked.connect(lambda x: self.ps_print.emit(True))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 2, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 2, 2, 1, 1)
-
- # extract functional region.
self._extract_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._extract_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._extract_gbox, 0, 1, 1, 1)
-
self._extract_btns = []
for i in range(6):
btn = QPushButton(self._extract_gbox)
self._extract_btns.append(btn)
-
gbox_grid_layout.addWidget(self._extract_btns[0], 0, 1, 1, 1)
self._extract_btns[0].clicked.connect(lambda x: self.ps_extract.emit(0))
-
gbox_grid_layout.addWidget(self._extract_btns[1], 1, 1, 1, 1)
self._extract_btns[1].clicked.connect(lambda x: self.ps_extract.emit(1))
-
gbox_grid_layout.addWidget(self._extract_btns[2], 2, 1, 1, 1)
self._extract_btns[2].clicked.connect(lambda x: self.ps_extract.emit(2))
-
gbox_grid_layout.addWidget(self._extract_btns[3], 3, 1, 1, 1)
self._extract_btns[3].clicked.connect(lambda x: self.ps_extract.emit(3))
-
gbox_grid_layout.addWidget(self._extract_btns[4], 4, 1, 1, 1)
self._extract_btns[4].clicked.connect(lambda x: self.ps_extract.emit(4))
-
gbox_grid_layout.addWidget(self._extract_btns[5], 5, 1, 1, 1)
self._extract_btns[5].clicked.connect(lambda x: self.ps_extract.emit(5))
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 6, 1, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 6, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 6, 2, 1, 1)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def sizeHint(self):
- return QSize(210, 145)
+ return QSize(250, 145)
def update_zoom(self):
- """
- Update zoom region.
- """
-
if self.sdt_zoom.get_value() == 1.0:
self.btn_zoom.setText(self._zoom_descs[1])
-
elif self.sdt_zoom.get_value() < 1.0:
self.btn_zoom.setText(self._zoom_descs[2])
-
else:
self.btn_zoom.setText(self._zoom_descs[3])
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self._filter_gbox.setTitle(self._gbox_descs[0])
-
for i in range(10):
self._filter_btns[i].setText(self._filter_descs[i])
-
self._zoom_gbox.setTitle(self._gbox_descs[1])
self.sdt_zoom.set_text(self._zoom_descs[0])
self.update_zoom()
-
self._crop_gbox.setTitle(self._gbox_descs[2])
self.btn_crop.setText(self._crop_descs[0])
self.btn_cancel.setText(self._crop_descs[1])
-
self._snap_gbox.setTitle(self._gbox_descs[3])
self.btn_freeze.setText(self._snap_descs[0])
self.btn_print.setText(self._snap_descs[1])
-
self._extract_gbox.setTitle(self._gbox_descs[4])
-
for i in range(6):
self._extract_btns[i].setText(self._extract_descs[i])
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._gbox_descs = (
_translate("Script", "Filter"),
_translate("Script", "Zoom"),
@@ -278,7 +203,6 @@ def _func_tr_(self):
_translate("Script", "Snap"),
_translate("Script", "Extract"),
)
-
self._extract_descs = (
_translate("Script", "Bright Colorful"),
_translate("Script", "Light Colorful"),
@@ -287,7 +211,6 @@ def _func_tr_(self):
_translate("Script", "Light"),
_translate("Script", "Dark"),
)
-
self._filter_descs = (
_translate("Script", "Blur"),
_translate("Script", "Contour"),
@@ -300,19 +223,16 @@ def _func_tr_(self):
_translate("Script", "Smooth"),
_translate("Script", "Smooth More"),
)
-
self._zoom_descs = (
_translate("Script", "Ratio - "),
_translate("Script", "Zoom"),
_translate("Script", "Zoom In"),
_translate("Script", "Zoom Out"),
)
-
self._crop_descs = (
_translate("Script", "Crop"),
_translate("Script", "Cancel"),
)
-
self._snap_descs = (
_translate("Script", "Freeze Image"),
_translate("Script", "Save Image"),
diff --git a/src/main/python/wgets/settings.py b/src/main/python/wgets/settings.py
index b060b0c..7f35015 100644
--- a/src/main/python/wgets/settings.py
+++ b/src/main/python/wgets/settings.py
@@ -23,10 +23,6 @@
class Settings(QDialog, Ui_SettingsDialog):
- """
- Settings object based on QDialog. Init a settings in settings.
- """
-
ps_rule_changed = pyqtSignal()
ps_lang_changed = pyqtSignal()
ps_skey_changed = pyqtSignal()
@@ -36,67 +32,42 @@ class Settings(QDialog, Ui_SettingsDialog):
ps_theme_changed = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init settings.
- """
-
super().__init__(wget, Qt.WindowCloseButtonHint)
self.setupUi(self)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
self._is_initializing = False
-
- # load translations.
self._func_tr_()
-
- # init qt args.
app_icon = QIcon()
app_icon.addPixmap(QPixmap(":/images/images/icon_128.png"), QIcon.Normal, QIcon.Off)
self.setWindowIcon(app_icon)
-
- # init shortcuts.
scroll_grid_layout = QGridLayout(self.shortcuts_scroll_contents)
-
self._skey_gboxes = []
self._skey_labels = []
self._skey_ledits = []
self._skey_accept = []
-
skey_gboxe_layouts = []
-
self._skey_distribution = (6, 8, 9, 5, 10, 10)
-
g0_seq = (0, 1, 2, 4, 7, 8)
g5_seq = (0, 1, 2, 3, 4, 5, 6, 8, 9, 10)
-
for gbox_id in range(len(self._skey_distribution)):
skey_gbox = QGroupBox(self.shortcuts_scroll_contents)
gbox_grid_layout = QGridLayout(skey_gbox)
scroll_grid_layout.addWidget(skey_gbox, gbox_id, 1, 1, 1)
self._skey_gboxes.append(skey_gbox)
skey_gboxe_layouts.append(gbox_grid_layout)
-
for curr_id in range(self._skey_distribution[gbox_id]):
if gbox_id == 0:
skey_id = g0_seq[curr_id]
-
elif gbox_id == 5:
skey_id = g5_seq[curr_id]
-
else:
skey_id = curr_id
-
skey_label = QLabel(skey_gbox)
skey_label.setMinimumSize(200, 25)
skey_label.setMaximumSize(400, 40)
gbox_grid_layout.addWidget(skey_label, skey_id, 0, 1, 1)
self._skey_labels.append(skey_label)
-
for ledit_id in range(3):
skey_ledit = QLineEdit(skey_gbox)
skey_ledit.setMinimumSize(68, 25)
@@ -104,15 +75,11 @@ def __init__(self, wget, args):
gbox_grid_layout.addWidget(skey_ledit, skey_id, ledit_id + 1, 1, 1)
skey_ledit.textChanged.connect(self.verify_shortcut_keymaps)
self._skey_ledits.append(skey_ledit)
-
- # new shortcuts not in range.
- # key no. 48 at line 5, g0.
skey_label = QLabel(self._skey_gboxes[0])
skey_label.setMinimumSize(200, 25)
skey_label.setMaximumSize(400, 40)
skey_gboxe_layouts[0].addWidget(skey_label, 5, 0, 1, 1)
self._skey_labels.append(skey_label)
-
for ledit_id in range(3):
skey_ledit = QLineEdit(self._skey_gboxes[0])
skey_ledit.setMinimumSize(68, 25)
@@ -120,14 +87,11 @@ def __init__(self, wget, args):
skey_gboxe_layouts[0].addWidget(skey_ledit, 5, ledit_id + 1, 1, 1)
skey_ledit.textChanged.connect(self.verify_shortcut_keymaps)
self._skey_ledits.append(skey_ledit)
-
- # key no. 49 at line 6, g0.
skey_label = QLabel(self._skey_gboxes[0])
skey_label.setMinimumSize(200, 25)
skey_label.setMaximumSize(400, 40)
skey_gboxe_layouts[0].addWidget(skey_label, 6, 0, 1, 1)
self._skey_labels.append(skey_label)
-
for ledit_id in range(3):
skey_ledit = QLineEdit(self._skey_gboxes[0])
skey_ledit.setMinimumSize(68, 25)
@@ -135,14 +99,11 @@ def __init__(self, wget, args):
skey_gboxe_layouts[0].addWidget(skey_ledit, 6, ledit_id + 1, 1, 1)
skey_ledit.textChanged.connect(self.verify_shortcut_keymaps)
self._skey_ledits.append(skey_ledit)
-
- # key no. 50 at line 3, g0.
skey_label = QLabel(self._skey_gboxes[0])
skey_label.setMinimumSize(200, 25)
skey_label.setMaximumSize(400, 40)
skey_gboxe_layouts[0].addWidget(skey_label, 3, 0, 1, 1)
self._skey_labels.append(skey_label)
-
for ledit_id in range(3):
skey_ledit = QLineEdit(self._skey_gboxes[0])
skey_ledit.setMinimumSize(68, 25)
@@ -150,14 +111,11 @@ def __init__(self, wget, args):
skey_gboxe_layouts[0].addWidget(skey_ledit, 3, ledit_id + 1, 1, 1)
skey_ledit.textChanged.connect(self.verify_shortcut_keymaps)
self._skey_ledits.append(skey_ledit)
-
- # key no. 51 at line 7, g5.
skey_label = QLabel(self._skey_gboxes[5])
skey_label.setMinimumSize(200, 25)
skey_label.setMaximumSize(400, 40)
skey_gboxe_layouts[5].addWidget(skey_label, 7, 0, 1, 1)
self._skey_labels.append(skey_label)
-
for ledit_id in range(3):
skey_ledit = QLineEdit(self._skey_gboxes[5])
skey_ledit.setMinimumSize(68, 25)
@@ -165,15 +123,12 @@ def __init__(self, wget, args):
skey_gboxe_layouts[5].addWidget(skey_ledit, 7, ledit_id + 1, 1, 1)
skey_ledit.textChanged.connect(self.verify_shortcut_keymaps)
self._skey_ledits.append(skey_ledit)
-
- # key no. 52-55 at line 5-8, g3.
for key_id in range(4):
skey_label = QLabel(self._skey_gboxes[3])
skey_label.setMinimumSize(200, 25)
skey_label.setMaximumSize(400, 40)
skey_gboxe_layouts[3].addWidget(skey_label, key_id + 5, 0, 1, 1)
self._skey_labels.append(skey_label)
-
for ledit_id in range(3):
skey_ledit = QLineEdit(self._skey_gboxes[3])
skey_ledit.setMinimumSize(68, 25)
@@ -181,14 +136,11 @@ def __init__(self, wget, args):
skey_gboxe_layouts[3].addWidget(skey_ledit, key_id + 5, ledit_id + 1, 1, 1)
skey_ledit.textChanged.connect(self.verify_shortcut_keymaps)
self._skey_ledits.append(skey_ledit)
-
- # key no. 56 at line 11, g5.
skey_label = QLabel(self._skey_gboxes[5])
skey_label.setMinimumSize(200, 25)
skey_label.setMaximumSize(400, 40)
skey_gboxe_layouts[5].addWidget(skey_label, 11, 0, 1, 1)
self._skey_labels.append(skey_label)
-
for ledit_id in range(3):
skey_ledit = QLineEdit(self._skey_gboxes[5])
skey_ledit.setMinimumSize(68, 25)
@@ -196,73 +148,46 @@ def __init__(self, wget, args):
skey_gboxe_layouts[5].addWidget(skey_ledit, 11, ledit_id + 1, 1, 1)
skey_ledit.textChanged.connect(self.verify_shortcut_keymaps)
self._skey_ledits.append(skey_ledit)
-
- # init comb boxes.
for lang in self._args.usr_langs:
self.lang_comb.addItem("")
-
for method in self._args.global_hm_rules:
self.hm_rule_comb.addItem("")
-
for i in range(len(self._color_sys_descs)):
self.color_sys_comb.addItem("")
-
for overfl in self._args.global_overflows:
self.overflow_comb.addItem("")
-
for ctp in ("rgb", "hsv", "cmyk", "lab", "gray"):
self.export_swatch_ctp_comb.addItem(ctp.upper())
-
for atp in range(3):
self.export_ase_type_comb.addItem("")
-
for wref in range(20):
self.white_illuminant_comb.addItem("")
-
for wref in range(2):
self.white_observer_comb.addItem("")
-
for fweight in range(9):
self.font_weight_comb.addItem(str((fweight + 1) * 100))
-
for bakid in range(17):
self.bakgd_id_comb.addItem("")
-
for styid in range(17):
self.style_id_comb.addItem("")
-
- # init clean up button.
self.clean_up_btn.clicked.connect(lambda x: self.ps_clean_up.emit())
self.restore_original_btn.clicked.connect(lambda x: self.ps_restore_layout.emit())
-
- # init buttons.
self.buttonBox.clear()
-
self._btn_1 = QPushButton()
self._btn_1.clicked.connect(self.application)
self.buttonBox.addButton(self._btn_1, QDialogButtonBox.AcceptRole)
-
self._btn_2 = QPushButton()
self._btn_2.clicked.connect(self.close)
self.buttonBox.addButton(self._btn_2, QDialogButtonBox.RejectRole)
-
self._btn_3 = QPushButton()
self._btn_3.clicked.connect(self.update_values)
self.buttonBox.addButton(self._btn_3, QDialogButtonBox.ApplyRole)
-
self._btn_4 = QPushButton()
self._btn_4.clicked.connect(self.reset_values)
self.buttonBox.addButton(self._btn_4, QDialogButtonBox.ResetRole)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def setup_colors(self):
- """
- Initialize color dp values by colors in self._args.
- """
-
self.positive_color_0_dp.setValue(self._args.positive_color[0])
self.positive_color_1_dp.setValue(self._args.positive_color[1])
self.positive_color_2_dp.setValue(self._args.positive_color[2])
@@ -274,32 +199,20 @@ def setup_colors(self):
self.wheel_ed_color_2_dp.setValue(self._args.wheel_ed_color[2])
def initialize(self):
- """
- Initialize values of boxes in settings dialog by self._args.
- """
-
self._is_initializing = True
-
self._skey_accept = []
-
for i in range(len(self._args.shortcut_keymaps)):
keymaps = self._args.shortcut_keymaps[i]
-
for j in range(3):
self._skey_ledits[i * 3 + j].setStyleSheet("")
-
if j < len(keymaps):
self._skey_ledits[i * 3 + j].setText(keymaps[j])
-
else:
self._skey_ledits[i * 3 + j].setText("")
-
self.usr_color_ledit.setText(self._args.usr_color)
self.usr_image_ledit.setText(self._args.usr_image)
-
self.store_loc_cbox.setChecked(self._args.store_loc)
self.win_on_top_cbox.setChecked(self._args.win_on_top)
-
self.lang_comb.setCurrentIndex([x[1] for x in self._args.usr_langs].index(self._args.lang))
self.hm_rule_comb.setCurrentIndex(self._args.global_hm_rules.index(self._args.hm_rule))
self.color_sys_comb.setCurrentIndex(self._args.color_sys)
@@ -311,28 +224,21 @@ def initialize(self):
self.style_id_comb.setCurrentIndex(self._args.style_id)
self.white_illuminant_comb.setCurrentIndex(self._args.white_illuminant)
self.white_observer_comb.setCurrentIndex(self._args.white_observer)
-
self.font_family_ledit.setText("; ".join(self._args.font_family))
self.font_size_sp.setValue(self._args.font_size)
-
self.max_history_files_sp.setValue(self._args.max_history_files)
self.max_history_steps_sp.setValue(self._args.max_history_steps)
self.export_grid_extns_ledit.setText(self._args.export_grid_extns)
-
self.r_prefix_0_ledit.setText(self._args.r_prefix[0].replace("\n", "\\n").replace("\t", "\\t"))
self.r_prefix_1_ledit.setText(self._args.r_prefix[1].replace("\n", "\\n").replace("\t", "\\t"))
-
self.rgb_prefix_0_ledit.setText(self._args.rgb_prefix[0].replace("\n", "\\n").replace("\t", "\\t"))
self.rgb_prefix_1_ledit.setText(self._args.rgb_prefix[1].replace("\n", "\\n").replace("\t", "\\t"))
self.rgb_prefix_2_ledit.setText(self._args.rgb_prefix[2].replace("\n", "\\n").replace("\t", "\\t"))
-
self.hec_prefix_0_ledit.setText(self._args.hec_prefix[0].replace("\n", "\\n").replace("\t", "\\t"))
self.hec_prefix_1_ledit.setText(self._args.hec_prefix[1].replace("\n", "\\n").replace("\t", "\\t"))
-
self.lst_prefix_0_ledit.setText(self._args.lst_prefix[0].replace("\n", "\\n").replace("\t", "\\t"))
self.lst_prefix_1_ledit.setText(self._args.lst_prefix[1].replace("\n", "\\n").replace("\t", "\\t"))
self.lst_prefix_2_ledit.setText(self._args.lst_prefix[2].replace("\n", "\\n").replace("\t", "\\t"))
-
self.press_move_cbox.setChecked(self._args.press_move)
self.show_hsv_cbox.setChecked(self._args.show_hsv)
self.show_rgb_cbox.setChecked(self._args.show_rgb)
@@ -342,278 +248,192 @@ def initialize(self):
self.show_minor_info_image_cbox.setChecked(self._args.show_info_pts[1] > 1)
self.show_major_info_board_cbox.setChecked(self._args.show_info_pts[2] in (1, 3))
self.show_minor_info_board_cbox.setChecked(self._args.show_info_pts[2] > 1)
-
self.h_range_0_dp.setValue(self._args.h_range[0])
self.h_range_1_dp.setValue(self._args.h_range[1])
self.s_range_0_dp.setValue(self._args.s_range[0])
self.s_range_1_dp.setValue(self._args.s_range[1])
self.v_range_0_dp.setValue(self._args.v_range[0])
self.v_range_1_dp.setValue(self._args.v_range[1])
-
self.wheel_ratio_dp.setValue(self._args.wheel_ratio)
self.volum_ratio_dp.setValue(self._args.volum_ratio)
self.cubic_ratio_dp.setValue(self._args.cubic_ratio)
self.coset_ratio_dp.setValue(self._args.coset_ratio)
-
self.stab_column_dp.setValue(self._args.stab_column)
-
self.rev_direct_cbox.setChecked(self._args.rev_direct)
-
self.s_tag_radius_dp.setValue(self._args.s_tag_radius)
self.v_tag_radius_dp.setValue(self._args.v_tag_radius)
-
self.zoom_step_dp.setValue(self._args.zoom_step)
self.move_step_dp.setValue(self._args.move_step)
-
self.rand_num_sp.setValue(self._args.rand_num)
self.circle_dist_sp.setValue(self._args.circle_dist)
-
self.positive_wid_sp.setValue(self._args.positive_wid)
self.negative_wid_sp.setValue(self._args.negative_wid)
self.wheel_ed_wid_sp.setValue(self._args.wheel_ed_wid)
-
self.setup_colors()
-
self._is_initializing = False
def application(self):
- """
- Modify self._args by values of boxes in settings dialog.
- """
-
if self._skey_accept:
self._args.modify_settings("shortcut_keymaps", [(self._skey_accept[i * 3], self._skey_accept[i * 3 + 1], self._skey_accept[i * 3 + 2]) for i in range(len(self._args.shortcut_keymaps))])
self.ps_skey_changed.emit()
-
self._args.modify_settings("usr_color", self.usr_color_ledit.text())
self._args.modify_settings("usr_image", self.usr_image_ledit.text())
-
self._args.modify_settings("store_loc", self.store_loc_cbox.isChecked())
self._args.modify_settings("win_on_top", self.win_on_top_cbox.isChecked())
-
hm_rule = self._args.hm_rule
self._args.modify_settings("hm_rule", self._args.global_hm_rules[self.hm_rule_comb.currentIndex()])
-
self._args.modify_settings("color_sys", self.color_sys_comb.currentIndex())
-
if self._args.hm_rule != hm_rule:
self.ps_rule_changed.emit()
-
self._args.modify_settings("overflow", self._args.global_overflows[self.overflow_comb.currentIndex()])
-
lang = self._args.lang
self._args.modify_settings("lang", self._args.usr_langs[self.lang_comb.currentIndex()][1])
-
if self._args.lang != lang:
self.ps_lang_changed.emit()
-
self._args.modify_settings("export_swatch_ctp", self.export_swatch_ctp_comb.currentText().lower())
self._args.modify_settings("export_ase_type", ("spot", "global", "process")[self.export_ase_type_comb.currentIndex()])
-
self._args.modify_settings("white_illuminant", self.white_illuminant_comb.currentIndex())
self._args.modify_settings("white_observer", self.white_observer_comb.currentIndex())
-
new_bakgd_id = self.bakgd_id_comb.currentIndex()
new_style_id = self.style_id_comb.currentIndex()
new_font_weight = self.font_weight_comb.currentIndex() + 1
new_font_size = int(self.font_size_sp.value())
new_font_family = check_nonempt_str_lst(re.split(r"[\v\a\f\n\r\t\[\]\(\),;:#]", str(self.font_family_ledit.text())))
-
if new_bakgd_id != self._args.bakgd_id or new_style_id != self._args.style_id or new_font_weight != self._args.font_weight or new_font_size != self._args.font_size or new_font_family != self._args.font_family:
if new_bakgd_id == self._args.bakgd_id and new_style_id == self._args.style_id:
change_pn_colors = False
-
else:
change_pn_colors = True
-
self._args.modify_settings("bakgd_id", new_bakgd_id)
self._args.modify_settings("style_id", new_style_id)
-
self._args.modify_settings("font_weight", new_font_weight)
self._args.modify_settings("font_size", new_font_size)
self._args.modify_settings("font_family", new_font_family)
-
self.ps_theme_changed.emit(change_pn_colors)
-
else:
self._args.modify_settings("positive_color", (self.positive_color_0_dp.value(), self.positive_color_1_dp.value(), self.positive_color_2_dp.value()))
self._args.modify_settings("negative_color", (self.negative_color_0_dp.value(), self.negative_color_1_dp.value(), self.negative_color_2_dp.value()))
self._args.modify_settings("wheel_ed_color", (self.wheel_ed_color_0_dp.value(), self.wheel_ed_color_1_dp.value(), self.wheel_ed_color_2_dp.value()))
-
self._args.modify_settings("max_history_files", self.max_history_files_sp.value())
self._args.modify_settings("max_history_steps", self.max_history_steps_sp.value())
self._args.modify_settings("export_grid_extns", self.export_grid_extns_ledit.text())
-
self._args.modify_settings("r_prefix", (self.r_prefix_0_ledit.text().replace("\\n", "\n").replace("\\t", "\t"), self.r_prefix_1_ledit.text().replace("\\n", "\n").replace("\\t", "\t")))
self._args.modify_settings("rgb_prefix", (self.rgb_prefix_0_ledit.text().replace("\\n", "\n").replace("\\t", "\t"), self.rgb_prefix_1_ledit.text().replace("\\n", "\n").replace("\\t", "\t"), self.rgb_prefix_2_ledit.text().replace("\\n", "\n").replace("\\t", "\t")))
self._args.modify_settings("hec_prefix", (self.hec_prefix_0_ledit.text().replace("\\n", "\n").replace("\\t", "\t"), self.hec_prefix_1_ledit.text().replace("\\n", "\n").replace("\\t", "\t")))
self._args.modify_settings("lst_prefix", (self.lst_prefix_0_ledit.text().replace("\\n", "\n").replace("\\t", "\t"), self.lst_prefix_1_ledit.text().replace("\\n", "\n").replace("\\t", "\t"), self.lst_prefix_2_ledit.text().replace("\\n", "\n").replace("\\t", "\t")))
-
self._args.modify_settings("press_move", self.press_move_cbox.isChecked())
self._args.modify_settings("show_hsv", self.show_hsv_cbox.isChecked())
self._args.modify_settings("show_rgb", self.show_rgb_cbox.isChecked())
-
w = int(self.show_major_info_wheel_cbox.isChecked()) + int(self.show_minor_info_wheel_cbox.isChecked()) * 2
i = int(self.show_major_info_image_cbox.isChecked()) + int(self.show_minor_info_image_cbox.isChecked()) * 2
b = int(self.show_major_info_board_cbox.isChecked()) + int(self.show_minor_info_board_cbox.isChecked()) * 2
self._args.modify_settings("show_info_pts", (w, i, b))
-
self._args.modify_settings("h_range", (self.h_range_0_dp.value(), self.h_range_1_dp.value()))
self._args.modify_settings("s_range", (self.s_range_0_dp.value(), self.s_range_1_dp.value()))
self._args.modify_settings("v_range", (self.v_range_0_dp.value(), self.v_range_1_dp.value()))
-
self._args.modify_settings("wheel_ratio", self.wheel_ratio_dp.value())
self._args.modify_settings("volum_ratio", self.volum_ratio_dp.value())
self._args.modify_settings("cubic_ratio", self.cubic_ratio_dp.value())
self._args.modify_settings("coset_ratio", self.coset_ratio_dp.value())
-
self._args.modify_settings("stab_column", self.stab_column_dp.value())
-
self._args.modify_settings("rev_direct", self.rev_direct_cbox.isChecked())
-
self._args.modify_settings("s_tag_radius", self.s_tag_radius_dp.value())
self._args.modify_settings("v_tag_radius", self.v_tag_radius_dp.value())
-
self._args.modify_settings("zoom_step", self.zoom_step_dp.value())
self._args.modify_settings("move_step", self.move_step_dp.value())
-
self._args.modify_settings("rand_num", self.rand_num_sp.value())
self._args.modify_settings("circle_dist", self.circle_dist_sp.value())
-
self._args.modify_settings("positive_wid", self.positive_wid_sp.value())
self._args.modify_settings("negative_wid", self.negative_wid_sp.value())
self._args.modify_settings("wheel_ed_wid", self.wheel_ed_wid_sp.value())
-
self.ps_settings_changed.emit()
def showup(self):
- """
- Initialize and show.
- """
-
self.initialize()
self.show()
def update_values(self):
- """
- For button apply.
- """
-
self.application()
self.initialize()
def reset_values(self):
- """
- For button reset.
- """
-
hm_rule = self._args.hm_rule
lang = self._args.lang
-
old_bakgd_id = self._args.bakgd_id
old_style_id = self._args.style_id
old_font_weight = self._args.font_weight
old_font_size = self._args.font_size
old_font_family = self._args.font_family
-
self._args.init_settings()
self.initialize()
-
if self._args.hm_rule != hm_rule:
self.ps_rule_changed.emit()
-
if self._args.lang != lang:
self.ps_lang_changed.emit()
-
self.ps_settings_changed.emit()
self.ps_theme_changed.emit(True)
def verify_shortcut_keymaps(self):
if self._is_initializing:
return
-
self._skey_accept = []
-
skey_copies = []
-
for i in range(len(self._skey_labels)):
for j in range(3):
self._skey_ledits[i * 3 + j].setStyleSheet("color: '#202020'; background-color: '#F9FFDF';")
skey_copies.append(self._skey_ledits[i * 3 + j].text())
-
err_id = []
used_names = []
-
for i in range(len(skey_copies)):
if not skey_copies[i]:
self._skey_accept.append("")
continue
-
skey_name = check_key(skey_copies[i])
-
if not skey_name:
self._skey_accept.append("")
err_id.append(i)
-
elif skey_name in self._skey_accept:
self._skey_accept.append("")
-
for copy_id in range(len(skey_copies)):
if skey_copies[copy_id] == skey_name and copy_id not in err_id:
err_id.append(copy_id)
-
else:
self._skey_accept.append(skey_name)
-
for i in err_id:
self._skey_ledits[i].setStyleSheet("color: '#202020'; background-color: '#FFB6AE';")
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self.setWindowTitle(self._dialog_descs[0])
self._btn_1.setText(self._dialog_descs[1])
self._btn_2.setText(self._dialog_descs[2])
self._btn_3.setText(self._dialog_descs[3])
self._btn_4.setText(self._dialog_descs[4])
-
for i in range(len(self._skey_gboxes)):
self._skey_gboxes[i].setTitle(self._skey_blocks[i])
-
for i in range(len(self._skey_labels)):
self._skey_labels[i].setText(self._skey_seqs[i])
-
for idx in range(len(self._args.usr_langs)):
lang = self._args.usr_langs[idx]
self.lang_comb.setItemText(idx, self._lang_descs[0].format(self._lang_descs[lang[0] + 1], lang[1].split(".")[0]))
-
for idx in range(len(self._args.global_hm_rules)):
self.hm_rule_comb.setItemText(idx, self._rule_descs[idx])
-
for idx in range(len(self._color_sys_descs)):
self.color_sys_comb.setItemText(idx, self._color_sys_descs[idx])
-
for idx in range(len(self._args.global_overflows)):
self.overflow_comb.setItemText(idx, self._overflow_descs[idx])
-
for idx in range(3):
self.export_ase_type_comb.setItemText(idx, self._ase_descs[idx])
-
for idx in range(17):
self.bakgd_id_comb.setItemText(idx, self._bakgd_descs[idx])
-
for idx in range(17):
self.style_id_comb.setItemText(idx, self._theme_descs[idx])
-
for idx in range(20):
self.white_illuminant_comb.setItemText(idx, self._white_illuminant_descs[idx])
-
for idx in range(2):
self.white_observer_comb.setItemText(idx, self._white_observer_descs[idx])
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._dialog_descs = (
_translate("Settings", "Settings"),
_translate("Settings", "OK"),
@@ -621,7 +441,6 @@ def _func_tr_(self):
_translate("Settings", "Apply"),
_translate("Settings", "Reset"),
)
-
self._rule_descs = (
_translate("Rule", "Analogous"),
_translate("Rule", "Monochromatic"),
@@ -632,20 +451,17 @@ def _func_tr_(self):
_translate("Rule", "Shades"),
_translate("Rule", "Custom"),
)
-
self._overflow_descs = (
_translate("Rule", "Cutoff"),
_translate("Rule", "Return"),
_translate("Rule", "Repeat"),
)
-
self._color_sys_descs = (
_translate("Mode", "RGB Space"),
_translate("Mode", "Rev RGB Space"),
_translate("Mode", "RYB Space"),
_translate("Mode", "Rev RYB Space"),
)
-
self._bakgd_descs = (
_translate("Settings", "Colorful"),
_translate("Settings", "White"),
@@ -665,7 +481,6 @@ def _func_tr_(self):
_translate("Settings", "Dark Blue"),
_translate("Settings", "Dark Magenta"),
)
-
self._theme_descs = (
_translate("Settings", "Default"),
_translate("Settings", "White"),
@@ -685,7 +500,6 @@ def _func_tr_(self):
_translate("Settings", "Dark Blue"),
_translate("Settings", "Dark Magenta"),
)
-
self._skey_blocks = (
_translate("Settings", "General"),
_translate("Settings", "Operation"),
@@ -694,13 +508,11 @@ def _func_tr_(self):
_translate("Settings", "Transformation"),
_translate("Settings", "Storage"),
)
-
self._ase_descs = (
_translate("Settings", "Spot"),
_translate("Settings", "Global"),
_translate("Settings", "Process"),
)
-
self._skey_seqs = (
_translate("Settings", "Homepage"),
_translate("Settings", "Update"),
@@ -760,7 +572,6 @@ def _func_tr_(self):
_translate("Settings", "Depot_View"),
_translate("Settings", "Redo"),
)
-
self._white_illuminant_descs = (
_translate("Settings", "A (Incandescent/tungsten)"),
_translate("Settings", "B (Old direct sunlight at noon)"),
@@ -783,12 +594,10 @@ def _func_tr_(self):
_translate("Settings", "F11 (Ultralume 40, Philips TL84)"),
_translate("Settings", "F12 (Ultralume 30, Philips TL83)"),
)
-
self._white_observer_descs = (
_translate("Settings", "2Ang (CIE 1931)"),
_translate("Settings", "10Ang (CIE 1964)"),
)
-
self._lang_descs = (
_translate("Rickrack", "{} ({})"),
_translate("Settings", "en"),
diff --git a/src/main/python/wgets/splash.py b/src/main/python/wgets/splash.py
index 53fb438..41a27b5 100644
--- a/src/main/python/wgets/splash.py
+++ b/src/main/python/wgets/splash.py
@@ -17,50 +17,34 @@
import json
import locale
from PyQt5.QtWidgets import QSplashScreen
+from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QImage
from cguis.resource import view_rc
class DPSplash(QSplashScreen):
- """
- Show image when loading.
- """
-
def __init__(self, resources, sys_argv):
- """
- Init splash.
- """
-
display_lang = "en"
-
if sys_argv["lang"]:
if sys_argv["lang"][:2].lower() in ("zh", "ja", "ko"):
display_lang = "zh"
-
else:
default_locale = locale.getdefaultlocale()[0]
default_locale = str(default_locale).lower() if default_locale else ""
-
if len(default_locale) > 1 and default_locale[:2].lower() in ("zh", "ja", "ko"):
display_lang = "zh"
-
else:
try:
with open(os.sep.join((resources, "settings.json")), "r", encoding="utf-8") as sf:
uss = json.load(sf)
-
except Exception as err:
uss = None
-
if isinstance(uss, dict) and "lang" in uss and str(uss["lang"])[:2].lower() in ("zh", "ja", "ko"):
display_lang = "zh"
-
super().__init__()
-
- design_pix = QPixmap.fromImage(QImage(":/images/images/design_{}.png".format(display_lang)))
- design_pix.setDevicePixelRatio(2)
-
- self.setPixmap(design_pix)
+ design_img = QImage(":/images/images/design_{}.png".format(display_lang)).scaled(780 * 1.2 * self.devicePixelRatioF(), 500 * 1.2 * self.devicePixelRatioF(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
+ design_img.setDevicePixelRatio(self.devicePixelRatioF())
+ self.setPixmap(QPixmap.fromImage(design_img))
def mousePressEvent(self, event):
event.ignore()
diff --git a/src/main/python/wgets/transformation.py b/src/main/python/wgets/transformation.py
index 51f07bf..846827d 100644
--- a/src/main/python/wgets/transformation.py
+++ b/src/main/python/wgets/transformation.py
@@ -19,10 +19,6 @@
class Transformation(QWidget):
- """
- Transformation object based on QWidget. Init a transformation in transformation.
- """
-
ps_move = pyqtSignal(tuple)
ps_zoom = pyqtSignal(float)
ps_home = pyqtSignal(bool)
@@ -30,51 +26,33 @@ class Transformation(QWidget):
ps_enhance = pyqtSignal(tuple)
def __init__(self, wget, args):
- """
- Init transformation.
- """
-
super().__init__(wget)
-
- # set attr.
self.setAttribute(Qt.WA_AcceptTouchEvents)
-
- # load args.
self._args = args
-
- # load translations.
self._func_tr_()
-
- # init qt args.
transf_grid_layout = QGridLayout(self)
transf_grid_layout.setContentsMargins(0, 0, 0, 0)
transf_grid_layout.setHorizontalSpacing(0)
transf_grid_layout.setVerticalSpacing(0)
-
scroll_area = QScrollArea(self)
scroll_area.setFrameShape(QFrame.Box)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll_area.setWidgetResizable(True)
transf_grid_layout.addWidget(scroll_area)
-
scroll_contents = QWidget()
scroll_grid_layout = QGridLayout(scroll_contents)
scroll_grid_layout.setContentsMargins(3, 9, 3, 3)
scroll_grid_layout.setHorizontalSpacing(3)
scroll_grid_layout.setVerticalSpacing(12)
scroll_area.setWidget(scroll_contents)
-
- # move functional region.
self._move_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._move_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(6)
gbox_grid_layout.setVerticalSpacing(6)
scroll_grid_layout.addWidget(self._move_gbox, 0, 1, 1, 1)
-
self.move_btns = []
-
btn = QPushButton(self._move_gbox)
btn.setMinimumSize(40, 40)
btn.setMaximumSize(40, 40)
@@ -82,7 +60,6 @@ def __init__(self, wget, args):
btn.setStyleSheet("padding: 0px 0px 0px 0px;")
gbox_grid_layout.addWidget(btn, 0, 2, 1, 1)
btn.clicked.connect(lambda x: self.move_up())
-
btn = QPushButton(self._move_gbox)
btn.setMinimumSize(40, 40)
btn.setMaximumSize(40, 40)
@@ -90,7 +67,6 @@ def __init__(self, wget, args):
btn.setStyleSheet("padding: 0px 0px 0px 0px;")
gbox_grid_layout.addWidget(btn, 2, 2, 1, 1)
btn.clicked.connect(lambda x: self.move_down())
-
btn = QPushButton(self._move_gbox)
btn.setMinimumSize(40, 40)
btn.setMaximumSize(40, 40)
@@ -98,7 +74,6 @@ def __init__(self, wget, args):
btn.setStyleSheet("padding: 0px 0px 0px 0px;")
gbox_grid_layout.addWidget(btn, 1, 1, 1, 1)
btn.clicked.connect(lambda x: self.move_left())
-
btn = QPushButton(self._move_gbox)
btn.setMinimumSize(40, 40)
btn.setMaximumSize(40, 40)
@@ -106,7 +81,6 @@ def __init__(self, wget, args):
btn.setStyleSheet("padding: 0px 0px 0px 0px;")
gbox_grid_layout.addWidget(btn, 1, 3, 1, 1)
btn.clicked.connect(lambda x: self.move_right())
-
btn = QPushButton(self._move_gbox)
btn.setMinimumSize(40, 40)
btn.setMaximumSize(40, 40)
@@ -114,22 +88,18 @@ def __init__(self, wget, args):
btn.setStyleSheet("padding: 0px 0px 0px 0px;")
gbox_grid_layout.addWidget(btn, 1, 2, 1, 1)
btn.clicked.connect(lambda x: self.reset_home())
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 3, 2, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 3, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 3, 4, 1, 1)
-
- # zoom functional region.
self._zoom_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._zoom_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(6)
gbox_grid_layout.setVerticalSpacing(6)
scroll_grid_layout.addWidget(self._zoom_gbox, 1, 1, 1, 1)
-
btn = QPushButton(self._zoom_gbox)
btn.setMinimumSize(40, 40)
btn.setMaximumSize(40, 40)
@@ -137,7 +107,6 @@ def __init__(self, wget, args):
btn.setStyleSheet("padding: 0px 0px 0px 0px;")
gbox_grid_layout.addWidget(btn, 0, 1, 1, 1)
btn.clicked.connect(lambda x: self.zoom_in())
-
btn = QPushButton(self._zoom_gbox)
btn.setMinimumSize(40, 40)
btn.setMaximumSize(40, 40)
@@ -145,190 +114,101 @@ def __init__(self, wget, args):
btn.setStyleSheet("padding: 0px 0px 0px 0px;")
gbox_grid_layout.addWidget(btn, 0, 3, 1, 1)
btn.clicked.connect(lambda x: self.zoom_out())
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 1, 2, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 1, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Expanding, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 1, 4, 1, 1)
-
- # enhance functional region.
self._enhance_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._enhance_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._enhance_gbox, 2, 1, 1, 1)
-
self.rhc_ehs = RGBHSVCkb(self._enhance_gbox, default_values=("r", "g", "b"), oneline_mode=True)
gbox_grid_layout.addWidget(self.rhc_ehs, 0, 1, 1, 3)
-
self.ckb_reserve_ehs = QCheckBox(self._enhance_gbox)
self.ckb_reserve_ehs.setChecked(False)
gbox_grid_layout.addWidget(self.ckb_reserve_ehs, 1, 1, 1, 3)
self.ckb_reserve_ehs.stateChanged.connect(self.sync_reserve)
-
self.ckb_ubox_ehs = QCheckBox(self._enhance_gbox)
self.ckb_ubox_ehs.setChecked(False)
gbox_grid_layout.addWidget(self.ckb_ubox_ehs, 2, 1, 1, 3)
-
self.sdt_extd_ehs = SlideText(self._enhance_gbox, num_range=(0.0, 100.0), default_value=100.0)
gbox_grid_layout.addWidget(self.sdt_extd_ehs, 3, 1, 1, 3)
self.sdt_extd_ehs.ps_value_changed.connect(self.sync_extd)
-
self.sdt_sepr_ehs = SlideText(self._enhance_gbox, num_range=(0.0, 100.0))
gbox_grid_layout.addWidget(self.sdt_sepr_ehs, 4, 1, 1, 3)
self.ckb_ubox_ehs.stateChanged.connect(lambda x: self.sdt_sepr_ehs.set_disabled(x))
-
self.sdt_fact_ehs = SlideText(self._enhance_gbox, num_range=(0.0, 100.0))
gbox_grid_layout.addWidget(self.sdt_fact_ehs, 5, 1, 1, 3)
-
self.btn_enhs = QPushButton(self._enhance_gbox)
gbox_grid_layout.addWidget(self.btn_enhs, 6, 1, 1, 3)
self.btn_enhs.clicked.connect(self.emit_enhance)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 7, 1, 1, 3)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 7, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 7, 4, 1, 1)
-
- # inverse functional region.
self._inverse_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._inverse_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._inverse_gbox, 3, 1, 1, 1)
-
self.rhc_inv = RGBHSVCkb(self._enhance_gbox, default_values=("r", "g", "b"), oneline_mode=True)
gbox_grid_layout.addWidget(self.rhc_inv, 0, 1, 1, 3)
-
self.ckb_reserve_inv = QCheckBox(self._inverse_gbox)
self.ckb_reserve_inv.setChecked(False)
gbox_grid_layout.addWidget(self.ckb_reserve_inv, 1, 1, 1, 3)
self.ckb_reserve_inv.stateChanged.connect(self.sync_reserve)
-
self.btn_invs = QPushButton(self._inverse_gbox)
gbox_grid_layout.addWidget(self.btn_invs, 2, 1, 1, 3)
self.btn_invs.clicked.connect(self.emit_inverse)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 3, 1, 1, 3)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 3, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 3, 4, 1, 1)
-
- """
- -> Tag: This segment is deleted.
-
- # replace functional region.
- self._replace_gbox = QGroupBox(scroll_contents)
- gbox_grid_layout = QGridLayout(self._replace_gbox)
- gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
- gbox_grid_layout.setHorizontalSpacing(3)
- gbox_grid_layout.setVerticalSpacing(12)
- scroll_grid_layout.addWidget(self._replace_gbox, 4, 1, 1, 1)
-
- self.ckb_reserve_rep = QCheckBox(self._replace_gbox)
- self.ckb_reserve_rep.setChecked(False)
- gbox_grid_layout.addWidget(self.ckb_reserve_rep, 0, 1, 1, 3)
- self.ckb_reserve_rep.stateChanged.connect(self.sync_reserve)
-
- self.ckb_uold_rep = QCheckBox(self._replace_gbox)
- self.ckb_uold_rep.setChecked(False)
- gbox_grid_layout.addWidget(self.ckb_uold_rep, 1, 1, 1, 3)
-
- self.sdt_extd_rep = SlideText(self._replace_gbox, num_range=(0.0, 100.0), default_value=100.0)
- gbox_grid_layout.addWidget(self.sdt_extd_rep, 2, 1, 1, 3)
- self.sdt_extd_rep.ps_value_changed.connect(self.sync_extd)
-
- self.sdt_scal_rep = SlideText(self._replace_gbox, num_range=(0.0, 100.0), default_value=100.0)
- gbox_grid_layout.addWidget(self.sdt_scal_rep, 3, 1, 1, 3)
-
- self.btn_replace_rgb = QPushButton(self._replace_gbox)
- gbox_grid_layout.addWidget(self.btn_replace_rgb, 4, 1, 1, 3)
- self.btn_replace_rgb.clicked.connect(lambda x: self.ps_replace.emit((1, self.ckb_reserve_rep.isChecked(), self.sdt_extd_rep.get_value() / 100.0, self.sdt_scal_rep.get_value() / 100.0, self.ckb_uold_rep.isChecked())))
-
- self.btn_replace_hsv = QPushButton(self._replace_gbox)
- gbox_grid_layout.addWidget(self.btn_replace_hsv, 5, 1, 1, 3)
- self.btn_replace_hsv.clicked.connect(lambda x: self.ps_replace.emit((2, self.ckb_reserve_rep.isChecked(), self.sdt_extd_rep.get_value() / 100.0, self.sdt_scal_rep.get_value() / 100.0, self.ckb_uold_rep.isChecked())))
-
- self.btn_replace_cancel = QPushButton(self._replace_gbox)
- gbox_grid_layout.addWidget(self.btn_replace_cancel, 6, 1, 1, 3)
- self.btn_replace_cancel.clicked.connect(lambda x: self.ps_replace.emit((0, None, None)))
-
- spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
- gbox_grid_layout.addItem(spacer, 7, 1, 1, 3)
- spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
- gbox_grid_layout.addItem(spacer, 7, 0, 1, 1)
- spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
- gbox_grid_layout.addItem(spacer, 7, 4, 1, 1)
- """
-
- # cover functional region.
self._cover_gbox = QGroupBox(scroll_contents)
gbox_grid_layout = QGridLayout(self._cover_gbox)
gbox_grid_layout.setContentsMargins(3, 12, 3, 12)
gbox_grid_layout.setHorizontalSpacing(3)
gbox_grid_layout.setVerticalSpacing(12)
scroll_grid_layout.addWidget(self._cover_gbox, 5, 1, 1, 1)
-
self.rhc_cov = RGBHSVCkb(self._enhance_gbox, default_values=("r", "g", "b"), oneline_mode=True)
gbox_grid_layout.addWidget(self.rhc_cov, 0, 1, 1, 3)
-
self.ckb_reserve_cov = QCheckBox(self._cover_gbox)
self.ckb_reserve_cov.setChecked(False)
gbox_grid_layout.addWidget(self.ckb_reserve_cov, 1, 1, 1, 3)
self.ckb_reserve_cov.stateChanged.connect(self.sync_reserve)
-
self.btn_cover = QPushButton(self._cover_gbox)
gbox_grid_layout.addWidget(self.btn_cover, 2, 1, 1, 3)
self.btn_cover.clicked.connect(self.emit_cover)
-
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
gbox_grid_layout.addItem(spacer, 3, 1, 1, 3)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 3, 0, 1, 1)
spacer = QSpacerItem(5, 5, QSizePolicy.Minimum, QSizePolicy.Minimum)
gbox_grid_layout.addItem(spacer, 3, 4, 1, 1)
-
self.update_text()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
-
def sizeHint(self):
- return QSize(210, 60)
+ return QSize(250, 60)
def move_up(self):
- """
- Move image up.
- """
-
self.ps_move.emit((0, self._args.move_step * -1))
def move_down(self):
- """
- Move image down.
- """
-
self.ps_move.emit((0, self._args.move_step))
def move_left(self):
- """
- Move image left.
- """
-
self.ps_move.emit((self._args.move_step * -1, 0))
def move_right(self):
- """
- Move image right.
- """
-
self.ps_move.emit((self._args.move_step, 0))
def reset_home(self):
@@ -341,146 +221,91 @@ def zoom_out(self):
self.ps_zoom.emit(1 / self._args.zoom_step)
def sync_reserve(self, state):
- """
- Sync enhance, inverse and replace reserve boxes.
- """
-
if state != self.ckb_reserve_ehs.isChecked():
self.ckb_reserve_ehs.setChecked(state)
-
if state != self.ckb_reserve_inv.isChecked():
self.ckb_reserve_inv.setChecked(state)
-
if state != self.ckb_reserve_rep.isChecked():
self.ckb_reserve_rep.setChecked(state)
-
if state != self.ckb_reserve_cov.isChecked():
self.ckb_reserve_cov.setChecked(state)
def sync_extd(self, value):
- """
- Sync enhance and replace extd sdr.
- """
-
if self.sdt_extd_ehs.get_value() != value:
self.sdt_extd_ehs.set_value(value)
-
if self.sdt_extd_rep.get_value() != value:
self.sdt_extd_rep.set_value(value)
def emit_enhance(self, value):
- """
- Emit enhance.
- """
-
region = []
separ = []
-
checked_values = self.rhc_ehs.get_values()
-
if not checked_values:
return
-
if checked_values[0] in ("r", "g", "b"):
for vl in checked_values:
reg = {"r": 0, "g": 1, "b": 2}[vl]
region.append(reg)
-
sepr = self._args.sys_color_set[self._args.sys_activated_idx].rgb[reg]
separ.append(sepr)
-
if not self.ckb_ubox_ehs.isChecked():
sepr = self.sdt_sepr_ehs.get_value() / 100.0
separ = (sepr * 255.0, sepr * 255.0, sepr * 255.0)
-
self.ps_enhance.emit(("enhance_rgb", tuple(region), tuple(separ), self.sdt_fact_ehs.get_value() / 100.0, self.ckb_reserve_ehs.isChecked(), self.sdt_extd_ehs.get_value() / 100.0))
-
else:
for vl in checked_values:
reg = {"h": 0, "s": 1, "v": 2}[vl]
region.append(reg)
-
sepr = self._args.sys_color_set[self._args.sys_activated_idx].hsv[reg]
separ.append(sepr)
-
if not self.ckb_ubox_ehs.isChecked():
sepr = self.sdt_sepr_ehs.get_value() / 100.0
separ = (sepr * 360.0, sepr, sepr)
-
self.ps_enhance.emit(("enhance_hsv", tuple(region), tuple(separ), self.sdt_fact_ehs.get_value() / 100.0, self.ckb_reserve_ehs.isChecked(), self.sdt_extd_ehs.get_value() / 100.0))
def emit_inverse(self, value):
- """
- Emit inverse.
- """
-
region = set()
checked_values = self.rhc_inv.get_values()
-
if not checked_values:
return
-
if checked_values[0] in ("r", "g", "b"):
for vl in checked_values:
region.add({"r": 0, "g": 1, "b": 2}[vl])
-
self.ps_enhance.emit(("inverse_rgb", region, self.ckb_reserve_inv.isChecked()))
-
else:
for vl in checked_values:
region.add({"h": 0, "s": 1, "v": 2}[vl])
-
self.ps_enhance.emit(("inverse_hsv", region, self.ckb_reserve_inv.isChecked()))
def emit_cover(self, value):
- """
- Emit cover.
- """
-
region = set()
checked_values = self.rhc_cov.get_values()
-
if not checked_values:
return
-
if checked_values[0] in ("r", "g", "b"):
for vl in checked_values:
region.add({"r": 0, "g": 1, "b": 2}[vl])
-
self.ps_enhance.emit(("cover_rgb", region, self.ckb_reserve_cov.isChecked()))
-
else:
for vl in checked_values:
region.add({"h": 0, "s": 1, "v": 2}[vl])
-
self.ps_enhance.emit(("cover_hsv", region, self.ckb_reserve_cov.isChecked()))
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_text(self):
self._move_gbox.setTitle(self._gbox_descs[0])
self._zoom_gbox.setTitle(self._gbox_descs[1])
-
- """
- for i in range(7):
- self.move_btns[i].setText(self._move_descs[i])
- """
-
self.sdt_sepr_ehs.set_text(self._enhance_descs[1])
self.sdt_fact_ehs.set_text(self._enhance_descs[2])
self.sdt_extd_ehs.set_text(self._enhance_descs[6])
self.ckb_ubox_ehs.setText(self._enhance_descs[10])
-
self._enhance_gbox.setTitle(self._gbox_descs[3])
self.rhc_ehs.set_prefix_text((self._enhance_descs[0], self._enhance_descs[9]))
self.ckb_reserve_ehs.setText(self._enhance_descs[3])
self.btn_enhs.setText(self._enhance_descs[4])
-
self._inverse_gbox.setTitle(self._gbox_descs[4])
self.rhc_inv.set_prefix_text((self._enhance_descs[0], self._enhance_descs[9]))
self.ckb_reserve_inv.setText(self._enhance_descs[3])
self.btn_invs.setText(self._enhance_descs[5])
-
self._cover_gbox.setTitle(self._gbox_descs[5])
self.rhc_cov.set_prefix_text((self._enhance_descs[0], self._enhance_descs[9]))
self.ckb_reserve_cov.setText(self._enhance_descs[3])
@@ -488,7 +313,6 @@ def update_text(self):
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._gbox_descs = (
_translate("Transformation", "Move"),
_translate("Transformation", "Zoom"),
@@ -497,7 +321,6 @@ def _func_tr_(self):
_translate("Transformation", "Inverse"),
_translate("Transformation", "Cover"),
)
-
self._move_descs = (
_translate("Transformation", "U"),
_translate("Transformation", "D"),
@@ -507,14 +330,12 @@ def _func_tr_(self):
_translate("Transformation", "I"),
_translate("Transformation", "O"),
)
-
self._replace_descs = (
_translate("Transformation", "Replace RGB"),
_translate("Transformation", "Replace HSV"),
_translate("Transformation", "Cancel"),
_translate("Transformation", "Use Old Algorithm"),
)
-
self._enhance_descs = (
_translate("Transformation", "Link"),
_translate("Transformation", "Space - "),
@@ -528,7 +349,6 @@ def _func_tr_(self):
_translate("Transformation", "Linked: "),
_translate("Transformation", "Use Result Color"),
)
-
self._extend_descs = (
_translate("Image", "All Images"),
_translate("Image", "PNG Image"),
diff --git a/src/main/python/wgets/wheel.py b/src/main/python/wgets/wheel.py
index 47bdb5e..51e26dc 100644
--- a/src/main/python/wgets/wheel.py
+++ b/src/main/python/wgets/wheel.py
@@ -28,10 +28,6 @@
class Wheel(QWidget):
- """
- Wheel object based on QWidget. Init a color wheel in workarea.
- """
-
ps_color_changed = pyqtSignal(bool)
ps_index_changed = pyqtSignal(bool)
ps_status_changed = pyqtSignal(tuple)
@@ -40,77 +36,38 @@ class Wheel(QWidget):
ps_undo = pyqtSignal(bool)
def __init__(self, wget, args):
- """
- Init color wheel.
- """
-
super().__init__(wget)
-
- # set name ids.
wget.setProperty("class", "WorkArea")
-
- # load args.
self._args = args
self._backup = self._args.sys_color_set.backup()
- self._drag_file = False
- self._drop_file = None
- self._press_key = 0
self._connected_keymaps = {}
-
- # init global args.
+ self.init_key()
self._pressed_in_wheel = False
self._pressed_in_bar_1 = False
self._pressed_in_bar_2 = False
-
- # load translations.
self._func_tr_()
-
- # init qt args.
self.setFocusPolicy(Qt.StrongFocus)
self.setAcceptDrops(True)
-
self.setMinimumSize(QSize(150, 100))
-
- # generate point centers and radii.
- # self._center = ...
- # self._radius = ...
- # self._tag_centers = ...
- # self._tag_radii = ...
- # self._assit_tag_centers = ...
- # self._assit_tag_radii = ...
self.init_pt_centers_and_radii()
-
- # outer circles.
self._outer_circles = None
-
- # shortcut is updated by _setup_skey in main.py.
# self.update_skey()
-
self.create_menu()
self.update_action_text()
- # ---------- ---------- ---------- Paint Funcs ---------- ---------- ---------- #
-
def paintEvent(self, event):
- # norm assit point index.
if False: # self._args.sys_activated_assit_idx > len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]):
self._args.sys_activated_assit_idx = -1
self.ps_color_changed()
-
- # generate point centers and radii.
self.init_pt_centers_and_radii()
-
painter = QPainter()
painter.begin(self)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setRenderHint(QPainter.TextAntialiasing, True)
painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
-
- # color wheel. hue.
wheel_box = get_outer_box(self._center, self._radius)
painter.setPen(QPen(QColor(*self._args.wheel_ed_color), self._args.wheel_ed_wid))
cgrad = QConicalGradient(*self._center, 0)
-
if self._args.dep_wtp:
cgrad.setColorAt(0.00000, QColor(255, 0 , 0 ))
cgrad.setColorAt(0.16667, QColor(255, 0 , 255))
@@ -119,7 +76,6 @@ def paintEvent(self, event):
cgrad.setColorAt(0.55555, QColor(0 , 255, 0 ))
cgrad.setColorAt(0.66667, QColor(255, 255, 0 ))
cgrad.setColorAt(1.00000, QColor(255, 0 , 0 ))
-
else:
cgrad.setColorAt(0.00000, QColor(255, 0 , 0 ))
cgrad.setColorAt(0.16667, QColor(255, 0 , 255))
@@ -128,52 +84,36 @@ def paintEvent(self, event):
cgrad.setColorAt(0.66667, QColor(0 , 255, 0 ))
cgrad.setColorAt(0.83333, QColor(255, 255, 0 ))
cgrad.setColorAt(1.00000, QColor(255, 0 , 0 ))
-
painter.setBrush(cgrad)
painter.drawEllipse(*wheel_box)
-
- # color wheel. saturation.
rgrad = QRadialGradient(*self._center, self._radius)
-
if self._args.dep_rtp:
rgrad.setColorAt(0.0, Qt.black)
-
else:
rgrad.setColorAt(0.0, Qt.white)
-
rgrad.setColorAt(1.0, Qt.transparent)
painter.setBrush(rgrad)
painter.drawEllipse(*wheel_box)
-
- # bars.
if self._args.sys_activated_assit_idx < 0:
bar_hsv = self._args.sys_color_set[self._args.sys_activated_idx].hsv
-
else:
bar_hsv = gen_assit_color(self._args.sys_color_set[self._args.sys_activated_idx], *self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2:6]).hsv
-
bar_i = bar_hsv[self._args.dep_wtp_rev_n]
-
if self._args.dep_rtp:
bar_rgb_1 = Color.hsv2rgb((bar_hsv[0], 1.0, 1.0))
bar_end_rgb_1 = Color.hsv2rgb((bar_hsv[0], 0.0, 1.0))
bar_rgb_2 = Color.hsv2rgb((bar_hsv[0], 1.0, bar_hsv[2]))
bar_end_rgb_2 = Color.hsv2rgb((bar_hsv[0], 0.0, bar_hsv[2]))
-
else:
bar_rgb_1 = Color.hsv2rgb((bar_hsv[0], 0.0, 1.0))
bar_end_rgb_1 = Color.hsv2rgb((bar_hsv[0], 0.0, 0.0))
bar_rgb_2 = Color.hsv2rgb((bar_hsv[0], bar_hsv[1], 1.0))
bar_end_rgb_2 = Color.hsv2rgb((bar_hsv[0], bar_hsv[1], 0.0))
-
self._v_tag_radius = min(self.width(), self.height()) * self._args.v_tag_radius / 2
self._v_tag_radius_2 = self._v_tag_radius ** 2
-
re_wid = int(self.width() * (1 - self._args.wheel_ratio) / 2 * self._args.volum_ratio)
-
if self._v_tag_radius * 3 < re_wid:
re_wid = int(self._v_tag_radius * 3)
-
bar_1_center = np.array(((self.width() - self._radius * 2) / 4, self.height() / 2), dtype=int)
self._bar_1_box = (bar_1_center[0] - re_wid / 2, bar_1_center[1] - self.height() * self._args.volum_ratio / 2, re_wid, self.height() * self._args.volum_ratio)
painter.setPen(QPen(QColor(*self._args.wheel_ed_color), self._args.wheel_ed_wid))
@@ -182,13 +122,11 @@ def paintEvent(self, event):
lgrad.setColorAt(0.0, QColor(*bar_end_rgb_1))
painter.setBrush(lgrad)
painter.drawRect(*self._bar_1_box)
-
self._cir_1_center = np.array((bar_1_center[0], self._bar_1_box[1] + self._bar_1_box[3] * bar_i), dtype=int)
cir_1_box = get_outer_box(self._cir_1_center, self._v_tag_radius)
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawEllipse(*cir_1_box)
-
bar_2_center = np.array((self.width() - (self.width() - self._radius * 2) / 4, self.height() / 2), dtype=int)
self._bar_2_box = (bar_2_center[0] - re_wid / 2, bar_2_center[1] - self.height() * self._args.volum_ratio / 2, re_wid, self.height() * self._args.volum_ratio)
painter.setPen(QPen(QColor(*self._args.wheel_ed_color), self._args.wheel_ed_wid))
@@ -197,178 +135,117 @@ def paintEvent(self, event):
lgrad.setColorAt(0.0, QColor(*bar_end_rgb_2))
painter.setBrush(lgrad)
painter.drawRect(*self._bar_2_box)
-
self._cir_2_center = np.array((bar_2_center[0], self._bar_2_box[1] + self._bar_2_box[3] * bar_i), dtype=int)
cir_2_box = get_outer_box(self._cir_2_center, self._v_tag_radius)
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawEllipse(*cir_2_box)
-
- # color set tags.
self._idx_seq = list(range(5))
self._idx_seq = self._idx_seq[self._args.sys_activated_idx + 1: ] + self._idx_seq[: self._args.sys_activated_idx + 1]
-
- # lines.
for idx in self._idx_seq:
- # main points.
color_center = self._tag_centers[idx]
-
- # assit sequence. this code is reused in four places.
assit_idx_seq = list(range(len(self._args.sys_grid_assitlocs[idx])))
-
if idx == self._args.sys_activated_idx and self._args.sys_activated_assit_idx >= 0:
assit_idx_seq = assit_idx_seq[self._args.sys_activated_assit_idx + 1: ] + assit_idx_seq[: self._args.sys_activated_assit_idx + 1]
-
- # assit lines.
for assit_idx in assit_idx_seq:
- # assit points.
assit_center = self._assit_tag_centers[idx][assit_idx]
-
- # draw assit points.
if idx == self._args.sys_activated_idx and assit_idx == self._args.sys_activated_assit_idx:
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
-
else:
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid, Qt.PenStyle(Qt.DashLine)))
-
painter.drawLine(QPoint(*color_center), QPoint(*assit_center))
-
- # draw main points.
if idx == self._args.sys_activated_idx:
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
-
else:
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid))
-
painter.drawLine(QPoint(*self._center), QPoint(*color_center))
-
- # dot.
dot_box = get_outer_box(self._center, self._args.positive_wid)
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QBrush(QColor(*self._args.positive_color)))
painter.drawEllipse(*dot_box)
-
- # circles.
for idx in self._idx_seq:
- # main points.
color_box = get_outer_box(self._tag_centers[idx], self._tag_radii)
-
- # assit sequence. this code is reused in four places.
assit_idx_seq = list(range(len(self._args.sys_grid_assitlocs[idx])))
if idx == self._args.sys_activated_idx and self._args.sys_activated_assit_idx >= 0:
assit_idx_seq = assit_idx_seq[self._args.sys_activated_assit_idx + 1: ] + assit_idx_seq[: self._args.sys_activated_assit_idx + 1]
-
- # assit circles.
for assit_idx in assit_idx_seq:
- # assit points.
assit_color = gen_assit_color(self._args.sys_color_set[idx], *self._args.sys_grid_assitlocs[idx][assit_idx][2:6])
assit_box = get_outer_box(self._assit_tag_centers[idx][assit_idx], self._assit_tag_radii)
- assit_frame_color = self._args.positive_color if idx == self._args.sys_activated_idx and assit_idx == self._args.sys_activated_assit_idx else self._args.negative_color
-
+ if idx == self._args.sys_activated_idx and assit_idx == self._args.sys_activated_assit_idx:
+ assit_frame_color = self._args.positive_color
+ self.ps_status_changed.emit(Color.sign(assit_color.hsv))
+ else:
+ assit_frame_color = self._args.negative_color
painter.setPen(QPen(QColor(*assit_frame_color), self._args.negative_wid))
-
painter.setBrush(QColor(*assit_color.rgb))
painter.drawEllipse(*assit_box)
-
- # relative (move-able) or ref (un-move-able) point tag. assit dot box.
if not self._args.sys_grid_assitlocs[idx][assit_idx][5]:
dot_box = get_outer_box(self._assit_tag_centers[idx][assit_idx], self._args.negative_wid * 2 / 3)
painter.setPen(QPen(Qt.NoPen))
painter.setBrush(QBrush(QColor(*assit_frame_color)))
painter.drawEllipse(*dot_box)
-
- # draw main points.
if idx == self._args.sys_activated_idx:
painter.setPen(QPen(QColor(*self._args.positive_color), self._args.positive_wid))
-
+ if self._args.sys_activated_assit_idx < 0:
+ self.ps_status_changed.emit(Color.sign(self._args.sys_color_set[idx].hsv))
else:
painter.setPen(QPen(QColor(*self._args.negative_color), self._args.negative_wid))
-
painter.setBrush(QColor(*self._args.sys_color_set[idx].rgb))
painter.drawEllipse(*color_box)
-
- # outer circles.
if self._outer_circles:
frame_color = self._args.negative_color
-
if self._outer_circles[0] == self._args.sys_activated_idx and (self._outer_circles[1] == self._args.sys_activated_assit_idx or self._outer_circles[1] == -1):
frame_color = self._args.positive_color
-
- # circle 0.
if self._outer_circles[5] == 0:
painter.setPen(QPen(QColor(*frame_color, 160), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][0]
painter.drawEllipse(*outer_circle[0])
-
for line in outer_circle[1:]:
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
if len(self._outer_circles[4]) > 2:
- # circle 1.
if self._outer_circles[5] == 1:
painter.setPen(QPen(QColor(*frame_color, 160), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][1]
painter.drawEllipse(*outer_circle[0])
-
for line in outer_circle[1:]:
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
- # circle 2.
if self._outer_circles[5] == 2:
painter.setPen(QPen(QColor(*frame_color, 160), self._args.negative_wid * 2/3))
painter.setBrush(QBrush(QColor(*frame_color, 120)))
-
else:
painter.setPen(QPen(QColor(*frame_color, 100), self._args.negative_wid * 2/3))
painter.setBrush(Qt.NoBrush)
-
outer_circle = self._outer_circles[4][2]
painter.drawEllipse(*outer_circle[0])
-
- # relative (move-able) or ref (un-move-able) point tag. assit dot box.
if self._outer_circles[1] < len(self._args.sys_grid_assitlocs[self._outer_circles[0]]) and self._args.sys_grid_assitlocs[self._outer_circles[0]][self._outer_circles[1]][5]:
line = outer_circle[1]
painter.drawLine(QPoint(*line[0]), QPoint(*line[1]))
-
poly = QPolygon([QPoint(*i) for i in outer_circle[2]])
painter.drawPolygon(poly)
-
painter.end()
- self.ps_status_changed.emit(Color.sign(self._args.sys_color_set[self._args.sys_activated_idx].hsv))
-
- # ---------- ---------- ---------- Mouse Event Funcs ---------- ---------- ---------- #
-
def keyPressEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
if event.key() == Qt.Key_Shift:
self._press_key = 1
self.setCursor(QCursor(Qt.PointingHandCursor))
event.accept()
-
elif event.key() == Qt.Key_Control:
self._press_key = 2
event.accept()
-
elif event.key() == Qt.Key_Alt:
self._press_key = 4
event.accept()
-
else:
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
@@ -378,7 +255,6 @@ def keyReleaseEvent(self, event):
if self._outer_circles:
self._outer_circles = None
self.update()
-
self._press_key = 0
self.setCursor(QCursor(Qt.ArrowCursor))
event.ignore()
@@ -386,63 +262,40 @@ def keyReleaseEvent(self, event):
def mouseDoubleClickEvent(self, event):
if self._args.sys_activated_assit_idx >= 0 and event.button() == Qt.LeftButton:
point = (event.x(), event.y())
-
if np.sum((point - self._assit_tag_centers[self._args.sys_activated_idx][self._args.sys_activated_assit_idx]) ** 2) < self._assit_tag_radii_2:
self.change_assit_point(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5])
-
self.ps_color_changed.emit(True)
event.accept()
-
else:
event.ignore()
-
else:
event.ignore()
def mousePressEvent(self, event):
point = np.array((event.x(), event.y()))
-
if self._press_key == 0 and self._outer_circles and self._outer_circles[5] > -1 and event.button() == Qt.LeftButton:
sel_idx, sel_assit_idx, is_in_pt, is_in_assit_pt, circle_locations, sel_info_idx = self._outer_circles
-
self._args.sys_activated_idx = sel_idx
self._args.sys_activated_assit_idx = sel_assit_idx
-
self.ps_index_changed.emit(True)
-
- # add a ref color.
if is_in_pt or (is_in_assit_pt and sel_info_idx == 0):
self._outer_circles = None
-
- # max assit len 30.
ans = self.insert_assit_point(0.0, 0.0, 0.0)
self._pressed_in_wheel = ans
-
- # del the ref color.
elif is_in_assit_pt and sel_info_idx == 1:
self._outer_circles = None
self.delete_assit_point()
-
- # fix or unfix the ref color.
else:
self.change_assit_point(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5])
-
self.ps_color_changed.emit(True)
event.accept()
-
elif self._press_key == 1 and event.button() == Qt.LeftButton:
- #
- # Sync to board.py.
- # May exist difference.
color_dict = {"version": self._args.info_version_en, "site": self._args.info_main_site, "type": "set"}
color_dict["palettes"] = export_list([(self._args.sys_color_set, self._args.hm_rule, "", "", (time.time(), time.time()), self._args.sys_grid_locations, self._args.sys_grid_assitlocs, self._args.sys_grid_list, self._args.sys_grid_values),])
color_path = os.sep.join((self._args.global_temp_dir.path(), "Rickrack_Set_{}.dps".format(abs(hash(str(color_dict))))))
-
with open(color_path, "w", encoding="utf-8") as f:
json.dump(color_dict, f, indent=4, ensure_ascii=False)
-
self._drag_file = True
-
drag = QDrag(self)
mimedata = QMimeData()
mimedata.setUrls([QUrl.fromLocalFile(color_path)])
@@ -451,120 +304,79 @@ def mousePressEvent(self, event):
drag.setPixmap(pixmap)
drag.setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2))
drag.exec_(Qt.CopyAction | Qt.MoveAction)
-
self._drag_file = False
self.setCursor(QCursor(Qt.ArrowCursor))
-
event.accept()
-
elif self._press_key == 2 and event.button() == Qt.LeftButton:
if np.sum((point - self._center) ** 2) < self._radius_2:
curr_color = self._args.sys_color_set[self._args.sys_activated_idx]
-
- # revise angle for ryb.
assit_h = get_theta_center(self._center, point)
-
if self._args.dep_wtp:
assit_h = Color.sys_ryb2rgb(assit_h)
-
delta_point = [assit_h - curr_color.h, 0.0, 0.0]
delta_point[self._args.dep_wtp_n] = np.linalg.norm(point - self._center) / self._radius - curr_color.hsv[self._args.dep_wtp_n]
self.insert_assit_point(*delta_point)
-
self._pressed_in_wheel = True
self.ps_color_changed.emit(True)
-
event.accept()
-
elif event.button() in (Qt.LeftButton, Qt.RightButton):
self._backup = self._args.sys_color_set.backup()
-
already_accepted = False
-
for idx in self._idx_seq[::-1]:
if np.sum((point - self._tag_centers[idx]) ** 2) < self._tag_radii_2:
self._args.sys_activated_idx = idx
self._args.sys_activated_assit_idx = -1
-
self.ps_index_changed.emit(True)
already_accepted = True
-
else:
for assit_idx in range(len(self._args.sys_grid_assitlocs[idx])):
if np.sum((point - self._assit_tag_centers[idx][assit_idx]) ** 2) < self._assit_tag_radii_2:
self._args.sys_activated_idx = idx
self._args.sys_activated_assit_idx = assit_idx
-
self.ps_index_changed.emit(True)
already_accepted = True
-
break
-
if already_accepted:
event.accept()
- # self.update() is completed by
- # self._wget_cube_table.ps_color_changed.connect(lambda x: self._wget_wheel.update()) in main.py.
- # same below.
+ # self.update() is completed by
break
-
if event.button() == Qt.RightButton:
event.ignore()
-
return
-
if already_accepted or (self._args.press_move and np.sum((point - self._center) ** 2) < self._radius_2):
self._pressed_in_wheel = True
-
event.accept()
- # self.update() is completed by
- # self._wget_cube_table.ps_color_changed.connect(lambda x: self._wget_wheel.update()) in main.py.
- # same below.
-
+ # self.update() is completed by
elif (not already_accepted) and ((self._bar_1_box[0] < point[0] < self._bar_1_box[0] + self._bar_1_box[2] and self._bar_1_box[1] < point[1] < self._bar_1_box[1] + self._bar_1_box[3]) or np.sum((point - self._cir_1_center) ** 2) < self._v_tag_radius_2):
if np.sum((point - self._cir_1_center) ** 2) < self._v_tag_radius_2 or self._args.press_move:
self._pressed_in_bar_1 = True
-
event.accept()
-
else:
event.ignore()
-
elif (not already_accepted) and ((self._bar_2_box[0] < point[0] < self._bar_2_box[0] + self._bar_2_box[2] and self._bar_2_box[1] < point[1] < self._bar_2_box[1] + self._bar_2_box[3]) or np.sum((point - self._cir_2_center) ** 2) < self._v_tag_radius_2):
if np.sum((point - self._cir_2_center) ** 2) < self._v_tag_radius_2 or self._args.press_move:
self._pressed_in_bar_2 = True
-
event.accept()
-
else:
event.ignore()
-
else:
event.ignore()
-
else:
event.ignore()
def mouseMoveEvent(self, event):
point = np.array((event.x(), event.y()))
-
if self._pressed_in_wheel:
self._outer_circles = None
-
if self._args.sys_activated_assit_idx < 0:
color = Color(self._backup[self._args.sys_activated_idx], tp="color", overflow=self._backup[0].get_overflow())
color.setti(np.linalg.norm(point - self._center) / self._radius, self._args.dep_wtp_s)
color.h = get_theta_center(self._center, point)
-
- # gen relative angle for ryb system.
if self._args.dep_wtp:
previous_color_set = self._args.sys_color_set.backup()
-
- # revise angle for ryb.
color.h = Color.sys_ryb2rgb(color.h)
-
self._args.sys_color_set.recover(self._backup)
self._args.sys_color_set.modify(self._args.hm_rule, self._args.sys_activated_idx, color)
-
for main_i in range(5):
for assit_i in range(len(self._args.sys_grid_assitlocs[main_i])):
if self._args.sys_grid_assitlocs[main_i][assit_i][5]:
@@ -574,92 +386,60 @@ def mouseMoveEvent(self, event):
relative_h = Color.sys_ryb2rgb(Color.sys_rgb2ryb(self._args.sys_color_set[main_i].h) + relative_h)
relative_h = relative_h - self._args.sys_color_set[main_i].h
self._args.sys_grid_assitlocs[main_i][assit_i][2] = relative_h
-
else:
self._args.sys_color_set.recover(self._backup)
self._args.sys_color_set.modify(self._args.hm_rule, self._args.sys_activated_idx, color)
-
else:
assit_i = np.linalg.norm(point - self._center) / self._radius
assit_h = get_theta_center(self._center, point)
-
if self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5]:
curr_color = self._args.sys_color_set[self._args.sys_activated_idx]
-
- # revise angle for ryb.
if self._args.dep_wtp:
delta_h = Color.sys_ryb2rgb(assit_h) - curr_color.h
-
else:
delta_h = assit_h - curr_color.h
-
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2] = delta_h
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2 + self._args.dep_wtp_n] = assit_i - curr_color.hsv[self._args.dep_wtp_n]
-
else:
- # revise angle for ryb.
if self._args.dep_wtp:
assit_h = Color.sys_ryb2rgb(assit_h)
-
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2] = assit_h
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2 + self._args.dep_wtp_n] = assit_i
-
self.ps_color_changed.emit(True)
-
event.accept()
-
elif self._pressed_in_bar_1:
self._outer_circles = None
-
val = (point[1] - self._bar_1_box[1]) / self._bar_1_box[3]
-
if self._args.sys_activated_assit_idx < 0:
color = Color(self._backup[self._args.sys_activated_idx], tp="color", overflow=self._backup[0].get_overflow())
color.setti(val, self._args.dep_wtp_rev_s)
-
self._args.sys_color_set.recover(self._backup)
self._args.sys_color_set.modify(self._args.hm_rule, self._args.sys_activated_idx, color)
-
else:
if self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5]:
curr_color = self._args.sys_color_set[self._args.sys_activated_idx]
-
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2 + self._args.dep_wtp_rev_n] = val - curr_color.hsv[self._args.dep_wtp_rev_n]
-
else:
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2 + self._args.dep_wtp_rev_n] = val
-
self.ps_color_changed.emit(True)
-
event.accept()
-
elif self._pressed_in_bar_2:
self._outer_circles = None
-
val = (point[1] - self._bar_2_box[1]) / self._bar_2_box[3]
-
if self._args.sys_activated_assit_idx < 0:
color = Color(self._backup[self._args.sys_activated_idx], tp="color", overflow=self._backup[0].get_overflow())
color.setti(val, self._args.dep_wtp_rev_s)
-
self._args.sys_color_set.recover(self._backup)
self._args.sys_color_set.modify(self._args.hm_rule, self._args.sys_activated_idx, color)
-
else:
if self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5]:
curr_color = self._args.sys_color_set[self._args.sys_activated_idx]
-
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2 + self._args.dep_wtp_rev_n] = val - curr_color.hsv[self._args.dep_wtp_rev_n]
-
else:
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2 + self._args.dep_wtp_rev_n] = val
-
self.ps_color_changed.emit(True)
-
event.accept()
-
else:
- # outer circles.
if self._args.show_info_pts[0] and self._press_key == 0 and (not self._drop_file):
pts = self._tag_centers
major = self._args.show_info_pts[0] in (1, 3)
@@ -667,296 +447,182 @@ def mouseMoveEvent(self, event):
minor = self._args.show_info_pts[0] > 1
last_count = bool(self._outer_circles)
self._outer_circles = get_outer_circles(point, self._args.sys_activated_idx, pts, assit_pts, self._tag_radii * 1.2, self._assit_tag_radii * 1.2, self._assit_tag_radii, self._outer_circles, major=major, minor=minor)
-
if self._outer_circles or last_count:
self.update()
-
else:
self._outer_circles = None
-
event.ignore()
def mouseReleaseEvent(self, event):
self.setCursor(QCursor(Qt.ArrowCursor))
-
if self._pressed_in_wheel or self._pressed_in_bar_1 or self._pressed_in_bar_2:
self._pressed_in_wheel = False
self._pressed_in_bar_1 = False
self._pressed_in_bar_2 = False
-
if event.button() == Qt.LeftButton:
self.ps_history_backup.emit(True)
-
event.ignore()
def dragEnterEvent(self, event):
- """
- Sync to board.py. May exist difference.
- """
-
if self._outer_circles:
self._outer_circles = None
self.update()
-
- # drag file out from depot.
if self._drag_file:
event.ignore()
return
-
try:
set_file = event.mimeData().urls()[0].toLocalFile()
-
except Exception as err:
event.ignore()
return
-
if set_file.split(".")[-1].lower() in ("dps", "json", "txt", "aco", "ase", "gpl", "xml"):
self._drop_file = set_file
event.accept()
-
else:
event.ignore()
def dropEvent(self, event):
- """
- Sync to board.py. May exist difference.
- """
-
if self._outer_circles:
self._outer_circles = None
self.update()
-
if self._drop_file:
self.ps_dropped.emit((self._drop_file, False))
self._drop_file = None
-
event.accept()
-
else:
event.ignore()
- # ---------- ---------- ---------- Public Funcs ---------- ---------- ---------- #
+ def init_key(self):
+ self._press_key = 0
+ self._drag_file = False
+ self._drop_file = None
def init_pt_centers_and_radii(self):
- # color set tags.
self._center = np.array((self.width() / 2.0, self.height() / 2.0), dtype=int)
self._radius = int(min(self.width(), self.height()) * self._args.wheel_ratio / 2)
self._radius_2 = self._radius ** 2
-
self._tag_centers = [None] * 5
self._tag_radii = int(min(self.width(), self.height()) * self._args.s_tag_radius / 2)
self._tag_radii_2 = self._tag_radii ** 2
-
self._assit_tag_centers = [[None] * len(self._args.sys_grid_assitlocs[i]) for i in range(5)]
self._assit_tag_radii = self._tag_radii * 2 / 3
self._assit_tag_radii_2 = self._assit_tag_radii ** 2
-
- # lines.
for idx in range(5):
- # revise angle for ryb.
angle = self._args.sys_color_set[idx].h
-
if self._args.dep_wtp:
angle = Color.sys_rgb2ryb(angle)
-
- # main points.
color_center = np.array([self._args.sys_color_set[idx].hsv[self._args.dep_wtp_n] * self._radius, 0], dtype=int) + self._center
color_center = rotate_point_center(self._center, color_center, angle)
self._tag_centers[idx] = color_center.astype(int)
-
- # assit lines.
for assit_idx in range(len(self._args.sys_grid_assitlocs[idx])):
_, _, assit_h, assit_s, assit_v, assit_relativity = self._args.sys_grid_assitlocs[idx][assit_idx]
-
- # revise angle for ryb.
angle = self._args.sys_color_set[idx].h
assit_angle = assit_h
sum_angle = angle + assit_angle
-
if self._args.dep_wtp:
sum_angle = Color.sys_rgb2ryb(sum_angle)
assit_angle = Color.sys_rgb2ryb(assit_angle)
-
- """
- # revise angle for ryb.
- angle = self._args.sys_color_set[idx].h
- assit_angle = assit_h
-
- if self._args.dep_wtp:
- angle = Color.sys_rgb2ryb(angle)
- assit_angle = Color.sys_rgb2ryb(assit_angle)
-
- sum_angle = angle + assit_angle
- """
-
- # assit points.
if assit_relativity:
assit_center = np.array([(self._args.sys_color_set[idx].hsv[self._args.dep_wtp_n] + (assit_s, assit_v)[self._args.dep_wtp_n - 1]) * self._radius, 0], dtype=int) + self._center
assit_center = rotate_point_center(self._center, assit_center, sum_angle)
-
else:
assit_center = np.array([(assit_s, assit_v)[self._args.dep_wtp_n - 1] * self._radius, 0], dtype=int) + self._center
assit_center = rotate_point_center(self._center, assit_center, assit_angle)
-
self._assit_tag_centers[idx][assit_idx] = assit_center.astype(int)
def reset_assit_point(self):
- """
- Delete all assit points.
- """
-
if not self.isVisible():
return
-
self._args.sys_grid_assitlocs = [[], [], [], [], []]
self._args.sys_assit_color_locs = [[], [], [], [], []]
self._args.sys_activated_assit_idx = -1
-
self.ps_color_changed.emit(True)
self.update()
def insert_assit_point(self, delta_h, delta_s, delta_v):
- """
- Insert (Append) an assitant point.
-
- Args:
- delta_h: increment of h relative to the h of the activated-idx color.
- delta_s: increment of s relative to the s of the activated-idx color.
- delta_v: increment of v relative to the v of the activated-idx color.
- """
-
if not self.isVisible():
return False
-
- # max assit len 30.
assit_len = len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx])
-
if assit_len > 30:
return False
-
loc_a, loc_b = 0.1, 0.1
-
self._args.sys_activated_assit_idx = assit_len
self._args.sys_grid_assitlocs[self._args.sys_activated_idx].append([loc_a, loc_b, delta_h, delta_s, delta_v, True])
self._args.sys_assit_color_locs[self._args.sys_activated_idx].append(None)
-
self.ps_color_changed.emit(True)
self.update()
-
return True
def change_assit_point(self, relativity):
- """
- Change the relativity of assit point.
- """
-
if len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]) > self._args.sys_activated_assit_idx >= 0:
if self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5] == bool(relativity):
return
-
if bool(relativity):
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2] - self._args.sys_color_set[self._args.sys_activated_idx].h
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][3] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][3] - self._args.sys_color_set[self._args.sys_activated_idx].s
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][4] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][4] - self._args.sys_color_set[self._args.sys_activated_idx].v
-
else:
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][2] + self._args.sys_color_set[self._args.sys_activated_idx].h
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][3] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][3] + self._args.sys_color_set[self._args.sys_activated_idx].s
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][4] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][4] + self._args.sys_color_set[self._args.sys_activated_idx].v
-
self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5] = bool(relativity)
-
self.ps_color_changed.emit(True)
self.update()
def delete_assit_point(self):
- """
- Delete the last assitant point.
- """
-
if len(self._args.sys_grid_assitlocs[self._args.sys_activated_idx]) > self._args.sys_activated_assit_idx >= 0:
if self._args.sys_activated_assit_idx == 0:
self._args.sys_grid_assitlocs[self._args.sys_activated_idx] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][1:]
self._args.sys_assit_color_locs[self._args.sys_activated_idx] = self._args.sys_assit_color_locs[self._args.sys_activated_idx][1:]
-
else:
self._args.sys_grid_assitlocs[self._args.sys_activated_idx] = self._args.sys_grid_assitlocs[self._args.sys_activated_idx][:self._args.sys_activated_assit_idx] + self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx + 1:]
self._args.sys_assit_color_locs[self._args.sys_activated_idx] = self._args.sys_assit_color_locs[self._args.sys_activated_idx][:self._args.sys_activated_assit_idx] + self._args.sys_assit_color_locs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx + 1:]
-
self._args.sys_activated_assit_idx = -1
-
self.ps_color_changed.emit(True)
self.update()
def confirm_delete_assit_point(self):
- """
- Act delete_assit_point with confirmation.
- """
-
if not self.isVisible():
return
-
self.prompt(self._operation_warns[3], self.delete_assit_point)
def clipboard_in(self):
- """
- Load set from clipboard. Sync to board.py. May exist difference.
- """
-
clipboard = QApplication.clipboard().mimeData()
-
if clipboard.hasUrls():
try:
set_file = clipboard.urls()[0].toLocalFile()
-
except Exception as err:
return
-
if set_file.split(".")[-1].lower() in ("dps", "json", "txt", "aco", "ase", "gpl", "xml") and os.path.isfile(set_file):
self.ps_dropped.emit((set_file, False))
self.ps_history_backup.emit(True)
-
else:
try:
color_dict = json.loads(clipboard.text(), encoding="utf-8")
-
except Exception as err:
return
-
if isinstance(color_dict, dict) and "type" in color_dict and "palettes" in color_dict:
if color_dict["type"] == "set":
self.ps_dropped.emit((color_dict, True))
self.ps_history_backup.emit(True)
def clipboard_all(self, ctp):
- """
- Set the rgb, hsv or hec (hex code) of all result colors as the clipboard data by shortcut Shift + r, h or c.
- """
-
def _func_():
data_lst = []
-
for i in (2, 1, 0, 3, 4):
color = self._args.sys_color_set[i].getti(ctp)
-
if ctp == "hec":
color = self._args.hec_prefix[0] + str(color) + self._args.hec_prefix[1]
-
else:
color = self._args.rgb_prefix[1].join([self._args.r_prefix[0] + str(color[coi]) + self._args.r_prefix[1] for coi in range(3)])
color = self._args.rgb_prefix[0] + color + self._args.rgb_prefix[2]
-
data_lst.append(color)
-
data = self._args.lst_prefix[1].join(data_lst)
data = self._args.lst_prefix[0] + data + self._args.lst_prefix[2]
-
mimedata = QMimeData()
mimedata.setText(data)
-
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
-
return _func_
def prompt(self, text, accept_action):
@@ -964,194 +630,115 @@ def prompt(self, text, accept_action):
box.setWindowTitle(self._operation_warns[0])
box.setText(text)
box.setIcon(QMessageBox.Warning)
-
box.addButton(self._operation_warns[1], QMessageBox.AcceptRole)
box.addButton(self._operation_warns[2], QMessageBox.RejectRole)
-
if box.exec_() == 0:
accept_action()
- # ---------- ---------- ---------- Menu ---------- ---------- ---------- #
-
def create_menu(self):
- """
- Create a right clicked menu.
- """
-
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.show_menu)
-
self._menu = QMenu(self)
-
- # _translate("Wheel", "Undo"), # 0
- # _translate("Wheel", "Redo"), # 1
self._action_undo = QAction(self)
self._action_undo.triggered.connect(lambda: self.ps_undo.emit(True))
self._menu.addAction(self._action_undo)
-
self._action_redo = QAction(self)
self._action_redo.triggered.connect(lambda: self.ps_undo.emit(False))
self._menu.addAction(self._action_redo)
-
- # _translate("Board", "Reset"), # 10
self._action_reset = QAction(self)
self._action_reset.triggered.connect(self.reset_assit_point)
self._menu.addAction(self._action_reset)
-
- # _translate("Wheel", "Paste"), # 5
self._action_paste = QAction(self)
self._action_paste.triggered.connect(self.clipboard_in)
self._menu.addAction(self._action_paste)
-
- # _translate("Wheel", "Copy RGB"), # 2
- # _translate("Wheel", "Copy HSV"), # 3
- # _translate("Wheel", "Copy Hex Code"), # 4
self._action_copy_rgb = QAction(self)
self._action_copy_rgb.triggered.connect(self.clipboard_all("rgb"))
self._menu.addAction(self._action_copy_rgb)
-
self._action_copy_hsv = QAction(self)
self._action_copy_hsv.triggered.connect(self.clipboard_all("hsv"))
self._menu.addAction(self._action_copy_hsv)
-
self._action_copy_hec = QAction(self)
self._action_copy_hec.triggered.connect(self.clipboard_all("hec"))
self._menu.addAction(self._action_copy_hec)
-
- # _translate("Wheel", "Insert Ref Point (Ctrl+MV)"), # 6
self._action_insert = QAction(self)
self._action_insert.triggered.connect(lambda: self.insert_assit_point((15 * np.random.random() + 15) * np.random.choice([1,-1]), 0.3 * np.random.random() - 0.15, 0))
self._menu.addAction(self._action_insert)
-
- # _translate("Wheel", "Delete Ref Point"), # 7
self._action_delete = QAction(self)
self._action_delete.triggered.connect(self.delete_assit_point)
self._menu.addAction(self._action_delete)
-
- # _translate("Wheel", "Fix Ref Point (DK)"), # 8
- # _translate("Wheel", "Un-Fix Ref Point (DK)"), # 9
self._action_fix_pt = QAction(self)
self._action_fix_pt.triggered.connect(lambda: self.change_assit_point(not self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5]) if self._args.sys_activated_idx >= 0 else None)
self._menu.addAction(self._action_fix_pt)
def show_menu(self):
- """
- Show the right clicked menu.
- """
-
self.update_action_text()
-
- # normal actions delete.
if self._args.sys_activated_assit_idx >= 0:
self._action_delete.setVisible(True)
self._action_fix_pt.setVisible(True)
-
else:
self._action_delete.setVisible(False)
self._action_fix_pt.setVisible(False)
-
self._menu.exec_(QCursor.pos())
- # ---------- ---------- ---------- Shortcut ---------- ---------- ---------- #
-
def update_skey(self):
- """
- Set depot shortcuts.
- """
-
for skey in self._args.shortcut_keymaps[39]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.delete_assit_point)
-
for skey in self._args.shortcut_keymaps[40]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.confirm_delete_assit_point)
-
for skey in self._args.shortcut_keymaps[45]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_all("hec"))
-
for skey in self._args.shortcut_keymaps[46]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(self.clipboard_in)
-
for skey in self._args.shortcut_keymaps[38]:
if skey in self._connected_keymaps:
shortcut = self._connected_keymaps[skey]
shortcut.disconnect()
-
else:
shortcut = QShortcut(QKeySequence(skey), self)
self._connected_keymaps[skey] = shortcut
-
shortcut.activated.connect(lambda: self.insert_assit_point((15 * np.random.random() + 15) * np.random.choice([1,-1]), 0.3 * np.random.random() - 0.15, 0))
- # ---------- ---------- ---------- Translations ---------- ---------- ---------- #
-
def update_action_text(self):
- # _translate("Wheel", "Undo"), # 0
- # _translate("Wheel", "Redo"), # 1
self._action_undo.setText(self._action_descs[0])
self._action_redo.setText(self._action_descs[1])
-
- # _translate("Board", "Reset"), # 10
self._action_reset.setText(self._action_descs[10])
-
- # _translate("Wheel", "Copy RGB"), # 2
- # _translate("Wheel", "Copy HSV"), # 3
- # _translate("Wheel", "Copy Hex Code"), # 4
self._action_copy_rgb.setText(self._action_descs[2])
self._action_copy_hsv.setText(self._action_descs[3])
self._action_copy_hec.setText(self._action_descs[4])
-
- # _translate("Wheel", "Paste"), # 5
self._action_paste.setText(self._action_descs[5])
-
- # _translate("Wheel", "Insert Ref Point (Ctrl+MV)"), # 6
self._action_insert.setText(self._action_descs[6])
-
- # _translate("Wheel", "Delete Ref Point"), # 7
self._action_delete.setText(self._action_descs[7])
-
- # _translate("Wheel", "Fix Ref Point (DK)"), # 8
- # _translate("Wheel", "Un-Fix Ref Point (DK)"), # 9
if self._args.sys_activated_assit_idx >= 0 and self._args.sys_grid_assitlocs[self._args.sys_activated_idx][self._args.sys_activated_assit_idx][5]:
self._action_fix_pt.setText(self._action_descs[8])
-
else:
self._action_fix_pt.setText(self._action_descs[9])
def _func_tr_(self):
_translate = QCoreApplication.translate
-
self._action_descs = (
_translate("Wheel", "Undo"), # 0
_translate("Wheel", "Redo"), # 1
@@ -1165,7 +752,6 @@ def _func_tr_(self):
_translate("Board", "Un-Fix Ref Point (DK)"), # 9
_translate("Wheel", "Reset"), # 10
)
-
self._operation_warns = (
_translate("Info", "Warning"),
_translate("Info", "OK"),
diff --git a/src/main/resources/base/fonts/LXGWWenKai-Bold.ttf b/src/main/resources/base/fonts/LXGWWenKai-Bold.ttf
deleted file mode 100644
index 3944092..0000000
Binary files a/src/main/resources/base/fonts/LXGWWenKai-Bold.ttf and /dev/null differ
diff --git a/src/main/resources/base/fonts/LXGWWenKai-Light.ttf b/src/main/resources/base/fonts/LXGWWenKai-Light.ttf
deleted file mode 100644
index 5bea80f..0000000
Binary files a/src/main/resources/base/fonts/LXGWWenKai-Light.ttf and /dev/null differ
diff --git a/src/main/resources/base/fonts/LXGWWenKai-Regular.ttf b/src/main/resources/base/fonts/LXGWWenKai-Regular.ttf
deleted file mode 100644
index a99443f..0000000
Binary files a/src/main/resources/base/fonts/LXGWWenKai-Regular.ttf and /dev/null differ
diff --git a/src/main/resources/base/fonts/LXGWWenKaiMono-Bold.ttf b/src/main/resources/base/fonts/LXGWWenKaiMono-Bold.ttf
deleted file mode 100644
index 7ba368a..0000000
Binary files a/src/main/resources/base/fonts/LXGWWenKaiMono-Bold.ttf and /dev/null differ
diff --git a/src/main/resources/base/fonts/LXGWWenKaiMono-Light.ttf b/src/main/resources/base/fonts/LXGWWenKaiMono-Light.ttf
deleted file mode 100644
index b10d4d4..0000000
Binary files a/src/main/resources/base/fonts/LXGWWenKaiMono-Light.ttf and /dev/null differ
diff --git a/src/main/resources/base/fonts/LXGWWenKaiMono-Regular.ttf b/src/main/resources/base/fonts/LXGWWenKaiMono-Regular.ttf
deleted file mode 100644
index a76a921..0000000
Binary files a/src/main/resources/base/fonts/LXGWWenKaiMono-Regular.ttf and /dev/null differ
diff --git a/src/main/resources/base/fonts/NotoSans-Black.ttf b/src/main/resources/base/fonts/NotoSans-Black.ttf
new file mode 100644
index 0000000..05771e5
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSans-Black.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSans-Bold.ttf b/src/main/resources/base/fonts/NotoSans-Bold.ttf
new file mode 100644
index 0000000..0d19068
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSans-Bold.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSans-Light.ttf b/src/main/resources/base/fonts/NotoSans-Light.ttf
new file mode 100644
index 0000000..8fde662
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSans-Light.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSans-Medium.ttf b/src/main/resources/base/fonts/NotoSans-Medium.ttf
new file mode 100644
index 0000000..faf167c
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSans-Medium.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSans-Regular.ttf b/src/main/resources/base/fonts/NotoSans-Regular.ttf
new file mode 100644
index 0000000..7552fbe
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSans-Regular.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSansJP-Black.ttf b/src/main/resources/base/fonts/NotoSansJP-Black.ttf
new file mode 100644
index 0000000..a3a382b
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansJP-Black.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSansJP-Bold.ttf b/src/main/resources/base/fonts/NotoSansJP-Bold.ttf
new file mode 100644
index 0000000..384f8eb
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansJP-Bold.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSansJP-Light.ttf b/src/main/resources/base/fonts/NotoSansJP-Light.ttf
new file mode 100644
index 0000000..54f15df
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansJP-Light.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSansJP-Medium.ttf b/src/main/resources/base/fonts/NotoSansJP-Medium.ttf
new file mode 100644
index 0000000..1d89aef
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansJP-Medium.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSansJP-Regular.ttf b/src/main/resources/base/fonts/NotoSansJP-Regular.ttf
new file mode 100644
index 0000000..1583096
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansJP-Regular.ttf differ
diff --git a/src/main/resources/base/fonts/NotoSansSC-Black.otf b/src/main/resources/base/fonts/NotoSansSC-Black.otf
new file mode 100644
index 0000000..7529643
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansSC-Black.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansSC-Bold.otf b/src/main/resources/base/fonts/NotoSansSC-Bold.otf
new file mode 100644
index 0000000..172eb67
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansSC-Bold.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansSC-Light.otf b/src/main/resources/base/fonts/NotoSansSC-Light.otf
new file mode 100644
index 0000000..85ccdf4
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansSC-Light.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansSC-Medium.otf b/src/main/resources/base/fonts/NotoSansSC-Medium.otf
new file mode 100644
index 0000000..0a5bd9e
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansSC-Medium.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansSC-Regular.otf b/src/main/resources/base/fonts/NotoSansSC-Regular.otf
new file mode 100644
index 0000000..d350ffa
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansSC-Regular.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansTC-Black.otf b/src/main/resources/base/fonts/NotoSansTC-Black.otf
new file mode 100644
index 0000000..aff4798
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansTC-Black.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansTC-Bold.otf b/src/main/resources/base/fonts/NotoSansTC-Bold.otf
new file mode 100644
index 0000000..6f0c8be
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansTC-Bold.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansTC-Light.otf b/src/main/resources/base/fonts/NotoSansTC-Light.otf
new file mode 100644
index 0000000..462bf97
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansTC-Light.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansTC-Medium.otf b/src/main/resources/base/fonts/NotoSansTC-Medium.otf
new file mode 100644
index 0000000..a0811eb
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansTC-Medium.otf differ
diff --git a/src/main/resources/base/fonts/NotoSansTC-Regular.otf b/src/main/resources/base/fonts/NotoSansTC-Regular.otf
new file mode 100644
index 0000000..2972477
Binary files /dev/null and b/src/main/resources/base/fonts/NotoSansTC-Regular.otf differ
diff --git a/src/main/resources/base/langs/en.qm b/src/main/resources/base/langs/en.qm
index 7c64856..34b65da 100644
Binary files a/src/main/resources/base/langs/en.qm and b/src/main/resources/base/langs/en.qm differ
diff --git a/src/main/resources/base/langs/ja.qm b/src/main/resources/base/langs/ja.qm
index a3b3d50..fa15650 100644
Binary files a/src/main/resources/base/langs/ja.qm and b/src/main/resources/base/langs/ja.qm differ
diff --git a/src/main/resources/base/langs/zh-Hant.qm b/src/main/resources/base/langs/zh-Hant.qm
index 00be533..e49a99b 100644
Binary files a/src/main/resources/base/langs/zh-Hant.qm and b/src/main/resources/base/langs/zh-Hant.qm differ
diff --git a/src/main/resources/base/langs/zh.qm b/src/main/resources/base/langs/zh.qm
index c4f1fe4..2fc157f 100644
Binary files a/src/main/resources/base/langs/zh.qm and b/src/main/resources/base/langs/zh.qm differ
diff --git a/src/main/resources/base/styles/default.qss b/src/main/resources/base/styles/default.qss
index f4195bc..d61f7ad 100644
--- a/src/main/resources/base/styles/default.qss
+++ b/src/main/resources/base/styles/default.qss
@@ -50,7 +50,7 @@ QMenuBar {
}
QMenuBar::item {
- padding: 1px 9px 1px 9px;
+ padding: 2px 12px 2px 12px;
}
QMenuBar::item:hover {
@@ -87,15 +87,15 @@ QMenu::separator {
QMenu::icon {
border: 0px;
- padding: 6px 6px 6px 6px;
+ padding: 4px 4px 4px 4px;
}
QMenu::indicator {
border: 2px solid $qc_list_over;
- width: 8px;
- height: 8px;
+ width: 12px;
+ height: 12px;
border-radius: 4px;
- margin: 6px 6px 6px 6px;
+ margin: 4px 4px 4px 4px;
}
QMenu::indicator:checked {
@@ -104,7 +104,7 @@ QMenu::indicator:checked {
}
QMenu::item {
- padding: 4px 32px 4px 32px;
+ padding: 4px 36px 4px 36px;
}
QMenu::item:enabled {
@@ -153,13 +153,13 @@ QToolBar {
background-color: $qc_workarea_over;
color: $qc_char;
border: 4px solid $qc_list;
- spacing: 4px;
+ spacing: 6px;
}
QToolBar::item {
background-color: $qc_list_over;
color: $qc_char_over;
- padding: px 0px 0px 0px;
+ padding: 0px 0px 0px 0px;
}
QToolBar::handle {
@@ -175,22 +175,22 @@ QToolButton styles.
QToolButton {
background-color: $qc_workarea_over;
color: $qc_char;
- width: 30px;
- height: 30px;
+ width: 40px;
+ height: 40px;
padding: 3px 3px 3px 3px;
- border: 1px solid $qc_workarea_over;
+ border: 2px solid $qc_workarea_over;
}
QToolButton:hover {
background-color: $qc_list;
color: $qc_char;
- border: 1px solid $qc_list;
+ border: 2px solid $qc_list;
}
QToolButton:pressed {
background-color: $qc_list;
color: $qc_char;
- border: 2px solid $qc_list;
+ border: 4px solid $qc_list;
}
/*
@@ -260,17 +260,16 @@ QPushButton {
background-color: $qc_workarea_over;
color: $qc_char;
padding: 2px 16px 2px 16px;
- border: 3px double $qc_list_over;
- border-radius: 6px;
- height: 24px;
+ border: 2px solid $qc_list_over;
+ border-radius: 8px;
+ height: 36px;
}
QPushButton:hover {
background-color: $qc_list;
color: $qc_char_over;
padding: 2px 16px 2px 16px;
- border: 3px solid $qc_list_over;
- border-radius: 6px;
+ border: 2px solid $qc_list_over;
}
QPushButton:pressed {
@@ -285,7 +284,7 @@ QGroupBox styles.
QGroupBox {
color: $qc_char_over;
border: 2px solid $qc_list_selected;
- border-radius: 4px;
+ border-radius: 6px;
margin-top: 0.5em;
padding-top: 0.5em;
}
@@ -313,10 +312,10 @@ QCheckBox:focus {
}
QCheckBox::indicator {
- border: 3px solid $qc_list_over;
- width: 10px;
- height: 10px;
- border-radius: 4px;
+ border: 2px solid $qc_list_over;
+ width: 12px;
+ height: 12px;
+ border-radius: 6px;
}
QCheckBox::indicator:hover {
@@ -325,7 +324,7 @@ QCheckBox::indicator:hover {
QCheckBox::indicator:checked {
background-color: $qc_list_selected;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
}
/*
@@ -349,9 +348,9 @@ QRadioButton:focus {
}
QRadioButton::indicator {
- border: 3px solid $qc_list_over;
- width: 10px;
- height: 10px;
+ border: 2px solid $qc_list_over;
+ width: 12px;
+ height: 12px;
border-radius: 8px;
}
@@ -361,7 +360,7 @@ QRadioButton::indicator:hover {
QRadioButton::indicator:checked {
background-color: $qc_list_selected;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
}
/*
@@ -519,25 +518,25 @@ QProgressBar styles.
QProgressBar {
background-color: $qc_list;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_list;
}
QProgressBar:disabled {
background-color: $qc_list;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_list;
}
QProgressBar::chunk {
background-color: $qc_list_over;
- border: 3px solid $qc_list;
+ border: 2px solid $qc_list;
color: $qc_list_over;
}
QProgressBar::chunk:disabled {
background-color: $qc_list_over;
- border: 3px solid $qc_list;
+ border: 2px solid $qc_list;
color: $qc_list_over;
}
@@ -550,17 +549,23 @@ QSlider {
color: $qc_char;
}
+QSlider:horizontal {
+ margin: 10px 0px 10px 0px;
+}
+
QSlider::add-page:horizontal {
background-color: $qc_list;
+ height: 7px;
}
QSlider::sub-page:horizontal {
background-color: $qc_list_over;
+ height: 7px;
}
QSlider::groove:horizontal {
background-color: transparent;
- height:6px;
+ height: 7px;
}
QSlider::handle:horizontal {
@@ -579,17 +584,23 @@ QSlider::handle:horizontal:disabled {
background-color: $qc_list;
}
+QSlider:vertical {
+ margin: 0px 10px 0px 10px;
+}
+
QSlider::add-page:vertical {
background-color: $qc_list;
+ width: 7px;
}
QSlider::sub-page:vertical {
background-color: $qc_list_over;
+ width: 7px;
}
QSlider::groove:vertical {
- background-color:transparent;
- width:6px;
+ background-color: transparent;
+ width: 7px;
}
QSlider::handle:vertical {
@@ -613,18 +624,18 @@ QSpinBox styles.
*/
QSpinBox {
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char;
}
QSpinBox:hover {
background-color: $qc_list;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char_over;
}
QSpinBox:focus {
- border: 3px solid $qc_list_selected;
+ border: 2px solid $qc_list_selected;
color: $qc_char_over;
}
@@ -653,22 +664,22 @@ QDoubleSpinBox styles.
*/
QDoubleSpinBox {
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char;
}
QDoubleSpinBox:disabled {
- border: 3px solid $qc_list;
+ border: 2px solid $qc_list;
}
QDoubleSpinBox:hover {
background-color: $qc_list;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char_over;
}
QDoubleSpinBox:focus {
- border: 3px solid $qc_list_selected;
+ border: 2px solid $qc_list_selected;
color: $qc_char_over;
}
@@ -697,18 +708,18 @@ QLineEdit styles.
*/
QLineEdit {
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char;
}
QLineEdit:hover {
background-color: $qc_list;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char_over;
}
QLineEdit:focus {
- border: 3px solid $qc_list_selected;
+ border: 2px solid $qc_list_selected;
color: $qc_char_over;
}
@@ -717,18 +728,18 @@ QTextEdit styles.
*/
QTextEdit {
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char;
}
QTextEdit:hover {
background-color: $qc_list;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char_over;
}
QTextEdit:focus {
- border: 3px solid $qc_list_selected;
+ border: 2px solid $qc_list_selected;
color: $qc_char_over;
}
@@ -737,18 +748,18 @@ QComboBox styles.
*/
QComboBox {
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char;
}
QComboBox:hover {
background-color: $qc_list;
- border: 3px solid $qc_list_over;
+ border: 2px solid $qc_list_over;
color: $qc_char_over;
}
QComboBox:focus {
- border: 3px solid $qc_list_selected;
+ border: 2px solid $qc_list_selected;
color: $qc_char_over;
}