diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 1af7f2d..228da1e 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -15,14 +15,14 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest, windows-latest, macos-12] # python-version: ["3.8", "3.9", "3.10"] python-version: ["3.10"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -45,12 +45,12 @@ jobs: cd .. cd .. - if: ${{ matrix.os != 'windows-latest' }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: the_ant_farm_${{ matrix.python-version }}_${{ matrix.os }} + name: the_ant_farm_${{ matrix.python-version }}_${{ matrix.os }}_${{ github.sha }}_${{ github.run_number }} path: src/TheAntFarm/dist/the_ant_farm - if: ${{ matrix.os == 'windows-latest' }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: the_ant_farm_${{ matrix.python-version }}_${{ matrix.os }}.exe + name: the_ant_farm_${{ matrix.python-version }}_${{ matrix.os }}_${{ github.sha }}_${{ github.run_number }} path: src/TheAntFarm/dist/the_ant_farm.exe diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d785b46 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,97 @@ + +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [0.2.0] - Aug 11, 2024 + +Added first implementation of alignment tab based on manual selection of points in +the loaded layer and positioning of the machin tool using camera. +This allows to create double sided PCB aligning them optically. + + +### Camera Functionality Improvements: +- **Camera Selection and Deselection**: Added the ability to deselect the camera when the application closes and improved camera selection management, including adding a default "NO Camera" option to avoid accidental startups. +- **Camera Zoom**: Linked the camera zoom combobox to update the view and added mouse wheel events to control the zoom. +- **Camera Alignment**: Improved synchronization of alignment buttons, connected camera zoom to the frame manager, and added support for selecting alignment points, including the ability to remove points. + +### Alignment Procedure Enhancements: +- **Alignment Point Management and Visualization**: Introduced a system to manage alignment points, including the removal of points and visual synchronization when alignment is applied. Added signals to update the coordinates of alignment points. +- **Path Optimization Algorithms**: Implemented and optimized a genetic algorithm to optimize the drilling path, also adding other algorithms like "nearest_insertion" and "two_opt". + +### User Interface Improvements: +- **UI Changes**: Made numerous changes to enhance the user experience, such as reorganizing the alignment tab, adding new control elements, and connecting various signals to synchronize the application state. +- **LED Indicators**: Added visual LEDs to signal the status of various processes, such as probing and alignment. +- **GCode File Handling**: Added the ability to load GCode files as a reference for alignment and improved the integration of the alignment system with the main program. + +### Bug Fixes and Optimizations: +- **Minor Fixes**: Resolved various bugs, such as issues with camera image misalignment, minor UI errors, and incorrect conditions. Improved handling of variables and boundary conditions in XY and Z movements. +- **MacOS Compatibility**: Termporarily removed generation of executable for ARM64 processor for MacOS. + +### Other Enhancements: +- **DRC and Camera Offset**: Implemented a validity check for Gerber paths and optimized the use of working positions instead of machine positions to get the camera-tool offset. +- **Integration of New Features**: Added a new `AlignManager` class to handle alignment and introduced a new alignment algorithm. + + +## [0.1.1] - May 13, 2023 + +Modified python-app.yml and added files to generate executables for 3 main OS using +github actions. + +### **Version and Documentation Updates**: + - **Version Bump**: Updated the project version to 0.1.1. + - **Documentation**: Enhanced and moved documentation to the wiki and updated `CommandManager` documentation. + +### **Build Process Enhancements**: + - **Artifact Handling**: Improved artifact naming and handling for different Python versions and operating systems. + - **Path and File Management**: Corrected paths for YAML files, executable runs, and excluded certain files from linting. + - **CI Configuration**: Adjusted the CI pipeline to support specific Python versions, use a matrix strategy, and added conditional artifact uploads. + +### **Compatibility and Dependency Management**: + - **Python Version**: Managed support for different Python versions (added 3.11, later removed due to incompatibility). + - **Shapely Library**: Addressed deprecation warnings and made preventive changes for Shapely >= 2.0. + - **`pyinstaller` Support**: Added spec file and adjustments to support building with `pyinstaller`. + +### **Miscellaneous Changes**: + - **UI Updates**: Made minor changes to how status signals are managed and displayed in the UI. + - **Packaging**: Added `pyproject.toml` for package management using `poetry` (not used at the moment). + + +## [0.1.0] - Oct 07, 2022 + +First issue of The Ant Farm, implemented functionality to generate gcode from TOP, +BOTTOM, DRILL and EDGE gerber/excellon layers. +Implemented Control tab to load gcode and manage CNC controllers using GRBL 1.x. + +### **Initial Setup and Core Functionality**: + - Introduction of new features like UI improvements, gcode generation, and tool change automation. + - Added handling for different file formats, including Gerber and Excellon files, with support for metric and imperial units. + - Improvements to core functionalities like drill file processing, layer management, and gcode visualization. + +### **Bug Fixes and Issue Resolution**: + - Numerous bug fixes addressing issues like loading files without geometries, converting units, and serial port communication. + - Resolved issues related to gcode generation, such as handling empty layers, mirroring, and feedrate errors. + - Fixes for threading issues, error handling, and UI bugs. + +### **Enhancements and Refactoring**: + - Enhanced user interface with better management of settings, color selections, and shortcut keys. + - Refactoring of code to improve structure, including splitting large classes into smaller, more manageable parts. + - Added features like tool change settings, probe offsets, and automated boundary box (ABL) processing. + +### **Documentation and Readability**: + - Added and updated documentation, including comments, docstrings, and the README file. + - Improved code readability by translating comments into English and following coding style guidelines. + +### **Version Control and Compatibility**: + - Managed dependencies and compatibility with different Python versions. + - Set up environment settings for different operating systems, including Windows, Linux, and Mac. + +### **Testing and Optimization**: + - Added tests and debugging tools to improve reliability and performance. + - Implemented optimizations to reduce gcode complexity and improve processing speed. + +### **Final Touches and Releases**: + - Prepared the project for release with a new logo, version tagging, and final code clean-up. + - Updated requirements, resources, and icons, preparing the application for broader use. diff --git a/pyproject.toml b/pyproject.toml index 300832c..2714191 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "TheAntFarm" -version = "0.1.0" +version = "0.1.2" description = "TheAntFarm is an application that simplifies the PCB creation using CNC machines." authors = ["The Ant Team"] license = "MIT" @@ -26,6 +26,8 @@ shiboken2 = "5.15.2.1" vispy = "0.9.4" opencv-python = ">=4.5.1.48" +dynamic = ["version"] + [tool.poetry.dev-dependencies] [build-system] diff --git a/src/TheAntFarm/__init__.py b/src/TheAntFarm/__init__.py index e69de29..7fd229a 100644 --- a/src/TheAntFarm/__init__.py +++ b/src/TheAntFarm/__init__.py @@ -0,0 +1 @@ +__version__ = '0.2.0' diff --git a/src/TheAntFarm/app_resources.qrc b/src/TheAntFarm/app_resources.qrc index 4e33c32..51affda 100644 --- a/src/TheAntFarm/app_resources.qrc +++ b/src/TheAntFarm/app_resources.qrc @@ -1,5 +1,7 @@ + resources/icons/black_alignment_applied.svg + resources/icons/black_apply_align.svg resources/icons/gray-refresh.svg resources/icons/white-upload-file.svg resources/icons/gray-upload-file.svg diff --git a/src/TheAntFarm/app_resources_rc.py b/src/TheAntFarm/app_resources_rc.py index 4dd478a..41dd062 100644 --- a/src/TheAntFarm/app_resources_rc.py +++ b/src/TheAntFarm/app_resources_rc.py @@ -6,323 +6,325 @@ from PySide2 import QtCore qt_resource_data = b"\ -\x00\x00\x13\xa1\ +\x00\x00\x13\xd0\ <\ ?xml version=\x221.\ 0\x22 encoding=\x22UTF\ -8\x22 standalone=\x22\ -no\x22?>\x0a\x0a \x0a \x0a \ -\x0a \ -\x0a\ - image/svg+xml\ -\x0a \ - \x0a \x0a\ - \ -\x0a \x0a\ - \x0a \ -\x0a \x0a <\ -g\x0a id=\x22g\ -3522\x22\x0a t\ -ransform=\x22matrix\ -(1.2994248,0,0,1\ -.2994248,-33.043\ -187,-36.454228)\x22\ ->\x0a \x0a\ - \x0d\x0a\x0d\x0a \x0d\x0a \x0d\x0a \ +\x0d\x0a \ + \x0d\x0a image/svg+\ +xml\x0d\ +\x0a \x0d\x0a \ +\x0d\x0a \x0d\x0a \x0d\x0a \x0d\x0a \x0d\ +\x0a \x0d\x0a \x0d\x0a \x0a \ - \x0a \x0a \x0a\x0a\ -\ +opacity:1\x22\x0d\x0a \ + id=\x22path3\ +839-6-9\x22\x0d\x0a \ + d=\x22m 184.01\ +799,163.48853 -7\ +3.66315,43.3141 \ +-73.662447,-41.7\ +4103 7.23e-4,-85\ +.055106 73.66316\ +4,-43.314093 73.\ +66244,41.741025 \ +z\x22 />\x0d\x0a <\ +path\x0d\x0a \ + id=\x22path2925\x22\x0d\x0a\ + d=\x22m \ +132.54494,175.64\ +374 c -3.1811,-1\ +.09428 -5.88337,\ +-3.39153 -7.3971\ +2,-6.28843 -0.77\ +025,-1.47406 -0.\ +90025,-1.58672 -\ +1.83154,-1.58734\ + -1.58401,-0.001\ + -3.06658,-1.184\ +53 -9.1485,-7.30\ +278 l -5.63823,-\ +5.67192 h -6.104\ + -6.104009 l -0.\ +73772,1.50784 c \ +-1.38722,2.83537\ + -5.01036,5.6373\ +2 -8.494909,6.56\ +952 -5.5306,1.47\ +956 -12.03738,-1\ +.68524 -14.56352\ +,-7.08348 -2.422\ +44,-5.17663 -1.4\ +863,-10.49099 2.\ +56303,-14.55006 \ +4.07662,-4.08644\ + 9.45933,-5.0521\ +5 14.601289,-2.6\ +1961 2.04076,0.9\ +6544 4.88833,3.6\ +6909 5.89645,5.5\ +9846 l 0.8102,1.\ +55058 6.065689,5\ +.7e-4 6.06568,7.\ +7e-4 8.53009,-8.\ +53353 8.5301,-8.\ +53354 v -3.45333\ + -3.45334 h -1.5\ +7913 c -0.86852,\ +0 -1.98947,-0.19\ +472 -2.491,-0.43\ +271 -0.50154,-0.\ +238 -3.77535,-3.\ +3158 -7.27513,-6\ +.83957 -5.208,-5\ +.24368 -6.41964,\ +-6.61167 -6.6738\ +5,-7.53503 -0.18\ +014,-0.6543 -0.3\ +1126,-3.61514 -0\ +.31218,-7.048992\ + l -0.002,-5.920\ +807 -6.98059,6.9\ +68229 c -4.57753\ +9,4.56942 -7.341\ +569,7.11738 -8.0\ +29199,7.40154 -0\ +.85068,0.35153 -\ +2.42534,0.43332 \ +-8.342589,0.4333\ +2 h -7.29399 l -\ +0.66625,1.42245 \ +c -0.79432,1.695\ +92 -2.80719,3.86\ +819 -4.69312,5.0\ +648 -7.69761,4.8\ +8404 -17.93217,0\ +.17538 -19.57279\ +,-9.00495 -1.411\ +96,-7.900866 5.5\ +839,-15.506349 1\ +3.695,-14.888403\ + 4.30242,0.32778\ +1 8.51705,3.0878\ +92 10.4946,6.872\ +787 l 0.78715,1.\ +506564 6.2066,5.\ +6e-4 6.2066,7.8e\ +-4 9.094289,-9.0\ +97528 9.094289,-\ +9.097522 0.006,-\ +5.357233 c 0.005\ +,-4.613664 0.079\ +1,-5.517693 0.53\ +121,-6.513312 0.\ +76871,-1.692655 \ +2.06373,-2.51049\ +3 3.97528,-2.510\ +493 1.91156,0 3.\ +20658,0.817838 3\ +.97529,2.510493 \ +0.49261,1.0847 0\ +.52541,2.174994 \ +0.53123,17.65885\ +8 l 0.006,16.502\ +789 4.58633,4.58\ +001 4.58632,4.58\ +001 h 9.32664 9.\ +32664 l 0.68281,\ +-1.47045 c 1.018\ +44,-2.19324 3.37\ +165,-4.43634 6.0\ +2702,-5.74503 2.\ +21733,-1.0928 2.\ +27734,-1.10482 5\ +.51449,-1.10482 \ +3.22653,0 3.3036\ +8,0.0153 5.46231\ +,1.08214 2.71687\ +,1.34275 4.79893\ +,3.36583 6.0231,\ +5.85249 4.09124,\ +8.31048 -1.14927\ +,17.60542 -10.55\ +133,18.71457 -1.\ +89763,0.22387 -5\ +.02792,-0.42961 \ +-6.93475,-1.4476\ +9 -2.0253,-1.081\ +33 -4.7573,-3.84\ +793 -5.58638,-5.\ +65712 l -0.67857\ +,-1.48073 h -4.6\ +9849 -4.69849 l \ +-0.10278,5.00628\ + c -0.0718,3.495\ +55 -0.21771,5.21\ +906 -0.48363,5.7\ +114 -0.20946,0.3\ +8781 -4.20356,4.\ +54554 -8.87579,9\ +.23941 l -8.4949\ +6,8.53431 3.9870\ +3,3.98703 3.9870\ +3,3.98702 0.4345\ +2,-0.84027 c 2.1\ +5694,-4.17107 6.\ +63542,-6.85669 1\ +1.43407,-6.85669\ + 11.26881,0 17.1\ +205,13.01163 9.6\ +5729,21.47364 -3\ +.24753,3.68214 -\ +9.01957,5.20582 \ +-13.66596,3.6074\ +9 z m 7.0015,-5.\ +45978 c 2.55524,\ +-1.06765 4.36883\ +,-3.88562 4.3688\ +3,-6.78835 0,-6.\ +7432 -8.46386,-9\ +.95725 -12.8199,\ +-4.8682 -3.65179\ +,4.2663 -1.56892\ +,10.65656 3.9410\ +2,12.09112 1.057\ +89,0.27543 3.336\ +18,0.0559 4.5100\ +5,-0.43457 z M 8\ +7.088912,156.948\ +6 c 1.61371,-0.7\ +5478 2.990169,-2\ +.06145 3.724009,\ +-3.53521 0.71766\ +,-1.44126 0.6963\ +1,-4.86591 -0.03\ +96,-6.34908 -2.6\ +98939,-5.4396 -1\ +0.590269,-5.4485\ +9 -13.284579,-0.\ +0151 -0.74308,1.\ +49855 -0.76819,4\ +.91539 -0.0468,6\ +.36421 1.23026,2\ +.47069 3.97808,4\ +.19481 6.68547,4\ +.19481 1.03609,0\ + 2.01958,-0.2190\ +5 2.96147,-0.659\ +6 z m 71.388778,\ +-32.4687 c 1.698\ +03,-0.50427 3.57\ +457,-2.04817 4.4\ +1539,-3.63273 0.\ +48781,-0.91927 0\ +.62103,-1.64945 \ +0.62488,-3.42473\ + 0.004,-1.97152 \ +-0.0954,-2.42697\ + -0.7896,-3.6079\ +5 -1.44567,-2.45\ +943 -4.7627,-4.1\ +4139 -7.32468,-3\ +.7141 -6.35863,1\ +.0605 -8.66041,8\ +.79512 -3.84421,\ +12.91761 2.01845\ +,1.72772 4.3582,\ +2.22214 6.91822,\ +1.4619 z M 67.34\ +5832,111.11387 c\ + 2.82007,-1.2855\ +4 4.37169,-3.701\ +33 4.37169,-6.80\ +647 0,-3.23261 -\ +1.82337,-5.83078\ +6 -4.88386,-6.95\ +9146 -1.43761,-0\ +.53003 -3.84226,\ +-0.43319 -5.2697\ +3,0.21223 -6.119\ +47,2.766846 -5.8\ +7459,11.342636 0\ +.39138,13.706046\ + 1.36362,0.51433\ + 4.09717,0.43692\ + 5.39052,-0.1526\ +6 z\x22\x0d\x0a \ + style=\x22fill:#22\ +293d;fill-opacit\ +y:1;stroke:#2229\ +3d;stroke-width:\ +0.303808;stroke-\ +miterlimit:4;str\ +oke-dasharray:no\ +ne;stroke-opacit\ +y:1\x22 />\x0d\x0a <\ +/g>\x0d\x0a \x0d\x0a \ + \x0d\x0a\x0d\x0a\ \x00\x00\x09\xf6\ <\ ?xml version=\x221.\ @@ -3160,6 +3162,139 @@ \x0a\x0d\x0a\x0d\x0a\ +\x00\x00\x03k\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22iso\ +-8859-1\x22?>\x0d\x0a\x0d\x0a\x0d\x0a\ +\x0d\x0a\ +\x0d\x0a\x09\x0d\x0a\x0d\x0a\ +\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a<\ +g>\x0d\x0a\x0d\x0a\x0d\x0a<\ +/g>\x0d\x0a\x0d\x0a\x0d\x0a\ +\x0d\x0a\x0d\x0a\x0d\x0a\ +\x0d\x0a\x0d\x0a\x0d\ +\x0a\x0d\x0a\x0d\x0a\x0d\ +\x0a\x0d\x0a\x0d\x0a\ +\x0d\x0a\x0d\x0a\ +\x00\x00\x04\x97\ +\x00\ +\x00\x0f\xe0x\x9c\xedW]o\xdb6\x14}/\xd0\xff\ + (/\x1b\x06\x91\xa2$\xcb\x96c\xa7\xd8\x10d\x18\ +0`@\xdbm\x8f\x01-26\x1b\x894H\xfa\xab\ +\xbf~\x97\xa2dK\x8e\xdd\x05\x1d\xb6\xbdTH$R\ +<\xf7\x9e{yxij\xf6n_W\xc1\x96k#\ +\x94\x9c\x87\x04\xc5a\xc0e\xa9\x98\x90\xcby\xf8\xfb\xc7\ +\x87h\x12\x06\xc6R\xc9h\xa5$\x9f\x87R\x85\xef\xee\ +\xde\xbe\x99\x99\xed\xf2\xed\x9b\x00.\xb0\x97f*\xe4\xb3\ +)\xe9\x1a\x00+k\xd7S\x8cw\xbb\x1d\xea^\x22\xa5\ +\x97X\xd2\x9a\x9b5-\xb9\xc1\xdd\xfb\xb0\xefA\xb3\xa7\ +\x81\xf1.m\xccHQ\x148Np\x92D\x80\x88\xcc\ +AZ\xba\x8f\xa4\xb9\xe9\x1b_2L\xe28\xc6\x10\xe5\ +\x80d_\x01\xf7U\x9aft\x80\x97\x86\x1c\xd1F}\ +\x16hA\x05\xd7j\xb3\xe4\xe8I\x0f\x90eyr\xcb\ +\x17Hs\xa36\xba\xf4\xa9\x97%\x1e`\x0dL\xef\x1a\ +\xfe{\xae\xfd\x0b\xe4\x8d\x9e\xc0\x88#\xc9-\xbe\xffx\ +\x7f\x1c\x8cb\xc4,\x1b8b'\xd2\xf5FW\x0d\x19\ ++1\xafx\xcd\xa55\x98 \xd21\x0b6\x0fa6\ +H\xdb\xed\x9cN\x99*\x9d20\xc8%{\x5c\xd0\xf2\ +yG5C\xa7\x89\xdb\x0a\xbe\xfbI\xed\xe7a\x1c\xc4\ +A\xee\xfe\xce]\x1cWO\x8c\xd2\xa4\x1d|\xfc\xf0\xc7\ +\xcf\x0f\xa2\xe2\x8f\x8fOp\xf7\x0c\xaab {\xc51\ +--\xe0\x0d\xa6\x95X\xcaG\xb5\xf8d\xfa|\xfd\xb5\ +\xe8_\x1d\xc0u\x97\xf7\xa9\xd9\xad\xa2>\x7f\xf6\x228\ +\xc8oA\x0d\xb0\xe3\x95\xaa9fT\xca\x03F\xcf\x8c\ +c\xb3\xa2\x9acQ\xbaH\x1e*j!b\xec\xe2\xa3\ +\x8bS\x88\x8d\xb7;w\x9b\x1d=\xbad\x98\x9b\x15\xcf\ +\xe4\xa7\xd6q\x84\xdd\x8b\x85\xd2\x8c\xebRUJ\xcf\xc3\ +\x9b\xbc\xb9\x8e\x83\xc7\xb0\xd7t\xc9!\x06\xa6v\xf30\ +y9\xbc\x13\x12\x86\xa2^\xeeA\xe0L:\xb7O\xcd\ +u\xd5n\xc5\xc5re\xe7a^L^b>+U\ +\xcf\xc3\x11\x1a\x8d\x93\x82\xe4\xe3\xabN\xf6}r\x9f\x95\ +\x82\x12\x16\xf6\xd0\x97\xa7gWn\xb4\x86\x95\x17U\xf4\ +\xc0\xf5`\xc1\xf5A\xe06\x9b \x92\x90bti\x18\ +\x9c'\x19\x8a\x9b\xebjh;\xc1\xec\x0a\xa2\x88\x93\xec\ +\xf2\xd4\x1e\x03\x8d[W\xde\x17\xf6j\xae\xa9]\xf5\xf5\ +s}2NN:\x18{\xa8\x5cUX\xad\x9ey\x04\ +\x1b\x03\xff\xa4\x84\x9cB\xedKv\xdbh0\xbd\xf1n\ +o=f\xda*r\xdb3\x81`Z\x8b\xf6e\x13\xf5\ +t\x82F$Mo\xa12\xaa\xa9\x84]\xf5Hj5\ +\x95\x06\xaa\x1f\xc4\xa9\xa9\xd5b\xff\x1dT\xf08\xcb\x03\ +W{m3J\x08JI\x1aD\xa4@\x13\xf2\xfd\xd1\ +\x16\x92\xa8\xb3\x18\x15$\x09\xd2\x1c\x1ed\x95\xc4h\x12\ +'%A\xa3x\x0c\xf6\x09\x1a'\x04\xbc$$k\xdb\ +\xcd}\xdb\xc2\x1c\x01\x00\xa3\x1e \xea\xc1VQ\x8b\x8b\ +\x1cl\x12\xc4~\xd0\xc3\xa3\x1e|\xdb\x01\xe3\xc83;\ +D\xdaw\xe5\xdb\x9f\xff^\x0eR\xbcN\x0e7\x91\x91\ +\xdeT|\xca\xb7\x5c*vM\xa0A\xf7K\x02e(\ +\x19\xe5\xb9\x17\xe8\xe6l!~\xd3hX2\xf9\x7fR\ +2\x05\xca&\xf9\xe4\x95%\x13\x8f2\xd2\xca\xd14!\ +\x99\x22\x8b\xb3\xee9\xd4\x83\x80f\xa3\x22p\xfbQ^\ +\xac\x92\x14\x91\x09\x01=r\x98\xbe Eq\x9a\x80\x97\ +t\x94\xa4m\xa7\xb9\x83 \x1e\xe7(\xf2I\xd4 \xfc\ +P\xd4\x83\x81\x1e\x1e\x06\x80|\x5c8A\xbc\xb97\xe8\ +:\xcdc\xdba\xe3\x0e\xeci[P\xd0\xc7\xbe\xaav\ +&\xff[\xed\x8c\xb34kk\xe7\xecG\xea\x9bX5\ +\xb7\x94QK}Rw\xfe1\x83\x93\xed\xf4\xfd\xfdC\ +\x97\xe9]\xd7\x98\x95\xe5\xf4O\xa5\x9f\xbb~o\x08\x06\ +Y9usI\xed\xe9\x1d\x00D\x0d?~\xee\xe0\xfb\ +\x03\x9c\x11g\xf8\x02\xe8\xcc\x87=\xacy\xdfC\x10\xb8\ +p\xba\x03\xec\xc5\x03&+k\xe1\xcc\xf0\x07\x0b2\xff\ +\xe2\x18\xc3\x93\x0b\xdc'\x80\x0c*Qri^\xc3Q\ +jN\xad\xd8\xc2\x19\xa7\xae\xe1\xf4\xd5\xd0\xb5\xd6\x06\x02\ +X@\x9b\xa9\x9a\x0a\x89\xaf\xd1A>\x0d\xce\xac\xb8\x1e\ +LK\xbf\xe3\x82\xfaq\x09\xe7\x94aH>(\xbaP\ +\x1b{\x8cH\xad\xe1k\xa8\x12k\xaam\x13M84\ +\xb9\x1bv\x9b\xe9\x14\xb6\xe2\xe7\x8e\xef~;\xf9i4\ +\xb9\x80\x1a\x86\x88/\xc5\xd8\xcf\x14_N\xf5\xb4v\xf0\ +\xd9\xe2\x19\xac\xaa__j\xf22\xf9\xaf\x92\xe3L\xfc\ +5\xd7\xb0V\xccW\x8a\x0f\xdfy\xef\xf9Z+\xb6i\ +\xce\xe3_Xd\xff\x98\xe7^\xc06&\x16\x9b\x7f\x9d\ +\x87k\xb1m\x06\x9c8\xe6\x22U\xa3\xdd\x99D\xdd^\ +\x81\x07\x9b\x85\xdfUp\x7f[q_\xe7\xb8\xf9<\x87\ +\xd6_\xbfA:\xdc\ \x00\x00\x0d\x5c\ <\ ?xml version=\x221.\ @@ -3376,63 +3511,6 @@ inkscape:conne\ ctor-curvature=\x22\ 0\x22 />\ -\x00\x00\x03k\ -<\ -?xml version=\x221.\ -0\x22 encoding=\x22iso\ --8859-1\x22?>\x0d\x0a\x0d\x0a\x0d\x0a\ -\x0d\x0a\ -\x0d\x0a\x09\x0d\x0a\x0d\x0a\ -\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a<\ -g>\x0d\x0a\x0d\x0a\x0d\x0a<\ -/g>\x0d\x0a\x0d\x0a\x0d\x0a\ -\x0d\x0a\x0d\x0a\x0d\x0a\ -\x0d\x0a\x0d\x0a\x0d\ -\x0a\x0d\x0a\x0d\x0a\x0d\ -\x0a\x0d\x0a\x0d\x0a\ -\x0d\x0a\x0d\x0a\ \x00\x00\x0c\xb0\ <\ ?xml version=\x221.\ @@ -3793,6 +3871,178 @@ >\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a\x0d\x0a<\ /svg>\x0d\x0a\ +\x00\x00\x0a\x95\ +<\ +?xml version=\x221.\ +0\x22 encoding=\x22UTF\ +-8\x22 standalone=\x22\ +no\x22?>\x0d\x0a\x0d\x0a \ +\x0d\x0a \x0d\x0a\ + \x0d\x0a \x0d\x0a \x0d\x0a \x0d\x0a image/s\ +vg+xml\x0d\x0a \x0d\x0a \ + \x0d\x0a\ + \x0d\x0a \ + \x0d\x0a\ + Openclipar\ +t\x0d\x0a \ + \x0d\x0a \x0d\x0a \ + \ +\x0d\x0a \ + \x0d\x0a \ + \x0d\x0a \ + \x0d\x0a \ + \x0d\x0a <\ +cc:permits\x0d\x0a \ + rdf:resou\ +rce=\x22http://crea\ +tivecommons.org/\ +ns#DerivativeWor\ +ks\x22 />\x0d\x0a \x0d\x0a \ + \x0d\x0a <\ +/metadata>\x0d\x0a\x0d\x0a\ \x00\x00\x09\xfb\ <\ ?xml version=\x221.\ @@ -9099,17 +9349,22 @@ \x00w\ \x00h\x00i\x00t\x00e\x00-\x00u\x00n\x00l\x00o\x00c\x00k\x00-\x00p\x00a\x00d\x00l\ \x00o\x00c\x00k\x00.\x00s\x00v\x00g\ -\x00\x15\ -\x08\x95\x91\xc7\ -\x00w\ -\x00h\x00i\x00t\x00e\x00_\x00n\x00o\x00r\x00t\x00h\x00_\x00a\x00r\x00r\x00o\x00w\ -\x00.\x00s\x00v\x00g\ \x00\x19\ \x01\xee\x1eg\ \x00p\ \x00l\x00a\x00y\x00-\x00b\x00u\x00t\x00t\x00o\x00n\x00-\x00a\x00r\x00r\x00o\x00w\ \x00h\x00e\x00a\x00d\x00.\x00s\x00v\x00g\ \x00\x15\ +\x0fY\xd2g\ +\x00b\ +\x00l\x00a\x00c\x00k\x00_\x00a\x00p\x00p\x00l\x00y\x00_\x00a\x00l\x00i\x00g\x00n\ +\x00.\x00s\x00v\x00g\ +\x00\x15\ +\x08\x95\x91\xc7\ +\x00w\ +\x00h\x00i\x00t\x00e\x00_\x00n\x00o\x00r\x00t\x00h\x00_\x00a\x00r\x00r\x00o\x00w\ +\x00.\x00s\x00v\x00g\ +\x00\x15\ \x0c,c\x07\ \x00w\ \x00h\x00i\x00t\x00e\x00-\x00u\x00p\x00l\x00o\x00a\x00d\x00-\x00f\x00i\x00l\x00e\ @@ -9123,6 +9378,11 @@ \x00u\ \x00n\x00l\x00o\x00c\x00k\x00-\x00p\x00a\x00d\x00l\x00o\x00c\x00k\x00.\x00s\x00v\ \x00g\ +\x00\x1b\ +\x09\x9fV\xe7\ +\x00b\ +\x00l\x00a\x00c\x00k\x00_\x00a\x00l\x00i\x00g\x00n\x00m\x00e\x00n\x00t\x00_\x00a\ +\x00p\x00p\x00l\x00i\x00e\x00d\x00.\x00s\x00v\x00g\ \x00\x1a\ \x08\xda\xae\x87\ \x00b\ @@ -9275,110 +9535,114 @@ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00(\x00\x02\x00\x00\x00\x01\x00\x00\x006\ +\x00\x00\x00(\x00\x02\x00\x00\x00\x01\x00\x00\x008\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x18\x00\x02\x00\x00\x001\x00\x00\x00\x05\ +\x00\x00\x00\x18\x00\x02\x00\x00\x003\x00\x00\x00\x05\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x06\x12\x00\x00\x00\x00\x00\x01\x00\x01,\xed\ +\x00\x00\x06~\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01i^\ \x00\x00\x01\x82\x93\xf7\xad\xac\ -\x00\x00\x06B\x00\x00\x00\x00\x00\x01\x00\x01<\x00\ +\x00\x00\x06\xae\x00\x00\x00\x00\x00\x01\x00\x01Kc\ \x00\x00\x01\x82\x93\xf7\xad\xbc\ -\x00\x00\x01|\x00\x00\x00\x00\x00\x01\x00\x00e\xe0\ +\x00\x00\x01|\x00\x00\x00\x00\x00\x01\x00\x00f\x0f\ \x00\x00\x01\x82\x93\xf7\xad\xbc\ -\x00\x00\x03 \x00\x00\x00\x00\x00\x01\x00\x00\xad\xa5\ +\x00\x00\x03 \x00\x00\x00\x00\x00\x01\x00\x00\xad\xd4\ \x00\x00\x01\x82\x93\xf7\xad\xbc\ -\x00\x00\x00\x94\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x9f\ +\x00\x00\x00\x94\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xce\ \x00\x00\x01\x82\x93\xf7\xad\xcb\ -\x00\x00\x07\xd8\x00\x00\x00\x00\x00\x01\x00\x01\x98\x8a\ +\x00\x00\x03\xd2\x00\x01\x00\x00\x00\x01\x00\x00\xc6N\ +\x00\x00\x01\x8f\x02\xa2\xc6\xf7\ +\x00\x00\x08D\x00\x00\x00\x00\x00\x01\x00\x01\xa7\xed\ \x00\x00\x01\x82\x93\xf7\xad\xbc\ \x00\x00\x006\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x83\xb0\xe5\xa9Z\ +\x00\x00\x01\x91A\xb5|O\ " def qInitResources(): diff --git a/src/TheAntFarm/combobox_filter_enter.py b/src/TheAntFarm/combobox_filter_enter.py new file mode 100644 index 0000000..151ed1d --- /dev/null +++ b/src/TheAntFarm/combobox_filter_enter.py @@ -0,0 +1,15 @@ +from PySide2.QtWidgets import QComboBox +from PySide2 import QtCore + + +class ComboBoxFilterEnter(QComboBox): + """Custom combobox class that handles Enter key events.""" + + key_event_cb = QtCore.Signal(int, name='key_event') + + def keyPressEvent(self, event): + if event.key() == QtCore.Qt.Key_Enter or event.key() == QtCore.Qt.Key_Return: + self.key_event_cb.emit(event.key()) + event.accept() + else: + super(ComboBoxFilterEnter, self).keyPressEvent(event) diff --git a/src/TheAntFarm/controller/controller_align.py b/src/TheAntFarm/controller/controller_align.py index 1f914cb..08ccadb 100644 --- a/src/TheAntFarm/controller/controller_align.py +++ b/src/TheAntFarm/controller/controller_align.py @@ -1,25 +1,98 @@ +import os.path + from PySide2.QtCore import QObject +from PySide2 import QtMultimedia import qimage2ndarray +from shape_core.pcb_manager import PcbObj +from shape_core.gcode_drill_converter import DrillGcodeConverter from double_side_manager import DoubleSideManager import logging +import traceback logger = logging.getLogger(__name__) class AlignController(QObject): + + EXCELLON_EXTENSIONS = (".xln", ".drl") + def __init__(self, settings): super(AlignController, self).__init__() self.settings = settings + self.pcb = PcbObj() + # TODO: parametrize drill diameter for gcode conversion + dgc_cfg = { + "default_gcode_drill_size": 0.7 + } + self.dgc = DrillGcodeConverter(cfg=dgc_cfg) + self.double_side_manager = DoubleSideManager() self.threshold_value = 0 + self.flipping_view = [False, False, False] + + self.align_data = [] + + def load_new_align_layer(self, layer, layer_path): + try: + exc_tags = self.pcb.EXN_KEYS + if layer in exc_tags: + ext = os.path.splitext(layer_path)[1] + if ext.lower() in self.EXCELLON_EXTENSIONS: + self.pcb.load_excellon(layer_path, layer) + loaded_layer = self.pcb.get_excellon_layer(layer) + if not loaded_layer[0]: + loaded_layer = None + else: + self.dgc.load_gcode(layer_path) + self.dgc.convert() + loaded_layer = self.dgc.get_drill_layer() + if not loaded_layer[0]: + loaded_layer = None + if loaded_layer is not None: + self.align_data = [] + return [loaded_layer, True] + + except (AttributeError, ValueError, ZeroDivisionError, IndexError) as e: + logging.error(e, exc_info=True) + except Exception: + logger.error("Uncaught exception: %s", traceback.format_exc()) + + return [None, None] + + def remove_align_points(self, selected_rows): + selected_rows.sort() + for r in selected_rows[::-1]: + if len(self.align_data) > r: + del self.align_data[r] + else: + logger.error("Invalid Alignment Points Row") + return self.align_data + + def flip_align_layer_horizontally(self, flipped): + self.flipping_view[0] = flipped + + def flip_align_layer_vertically(self, flipped): + self.flipping_view[1] = flipped def update_threshold_value(self, new_threshold): self.threshold_value = new_threshold - def camera_new_frame(self): + def get_camera_list(self): + return self.double_side_manager.list_cameras_indexes() + + def update_camera_selected(self, index): + return self.double_side_manager.update_camera(index) + + def camera_new_frame(self, zoom=1): frame = self.double_side_manager.get_webcam_frame() - logger.debug(str(self.threshold_value)) - frame = self.double_side_manager.detect_holes(frame, self.threshold_value) - image = qimage2ndarray.array2qimage(frame) + image = None + if frame is not None: + frame = self.double_side_manager.detect_holes(frame, self.threshold_value, zoom_f=zoom) + image = qimage2ndarray.array2qimage(frame) return image + + def add_new_align_point(self, geom_point, working_position_point): + if geom_point is not None and working_position_point is not None: + self.align_data.append((geom_point, working_position_point)) + return self.align_data diff --git a/src/TheAntFarm/controller/controller_control.py b/src/TheAntFarm/controller/controller_control.py index 0bba1eb..0985f97 100644 --- a/src/TheAntFarm/controller/controller_control.py +++ b/src/TheAntFarm/controller/controller_control.py @@ -6,7 +6,7 @@ import random import numpy as np from collections import OrderedDict, deque -from shape_core.gcode_manager import GCoder, GCodeParser, GCodeLeveler +from shape_core.gcode_manager import GCoder, GCodeParser, GCodeLeveler, GCodeAlignment logger = logging.getLogger(__name__) @@ -39,6 +39,7 @@ def __init__(self, settings): self.abl_updated = False self.prb_val = deque([[-1.0, -1.0, -1.0], [-1.0, -1.0, -1.0]], maxlen=2) self.abl_val = [] + self.align_data = [] self.abl_steps = () self.abl_cmd_ls = [] self.prb_num_todo = 0 @@ -54,6 +55,29 @@ def __init__(self, settings): def get_probe_value(self): return self.prb_val[0] + def set_align_data(self, align_data): + if isinstance(align_data, list) or isinstance(align_data, tuple): + self.align_data = align_data + print("Applied Alignment DATA") + + def get_align_data(self): + print("GET ALIGN DATA") + # WARNING INJECTING FAKE DATA FOR TESTING PURPOSE + if not self.align_data and False: + print("INJECT FAKE DATA") + # FAKE DATA + fake_align_data = [ + [(-2.032, 18.110), (-3.860, 13.900)], + [(-8.230, 1.854), (-12.660, -1.100)], + [(-24.562, 8.026), (-27.660, 7.6)], + [(-18.415, 24.384), (-18.960, 22.600)], + ] + self.align_data = fake_align_data + return fake_align_data + else: + print("RETURN VALID DATA") + return self.align_data + def get_abl_value(self): return self.abl_val @@ -279,17 +303,31 @@ def get_gcode_tag_and_v(self, gcode_path): tag = self.gcodes_od[gcode_path]["tag"] return tag, v + def apply_alignment(self, gcode_path): + print("Apply Alignment") + gcp = self.get_gcode_gcp(gcode_path) + align = GCodeAlignment(gcp.gc) + align.update_align_info(self.align_data.copy()) + align.apply_align() + + def remove_alignment(self, gcode_path): + gcp = self.get_gcode_gcp(gcode_path) + if gcp.gc.aligned_vectors: + gcp.gc.aligned_vectors = [] + return True + else: + return False + def apply_abl(self, gcode_path): print("Apply ABL") gcp = self.get_gcode_gcp(gcode_path) abl = GCodeLeveler(gcp.gc) abl_val = self.abl_val.copy() - last_probe = abl_val.pop() - abl.get_grid_data(abl_val, self.abl_steps, last_probe, self.wco_a) + if abl_val != [] or True: + last_probe = abl_val.pop() + abl.get_grid_data(abl_val, self.abl_steps, last_probe, self.wco_a) abl.interp_grid_data() abl.apply_abl() - # print("Leveled") - # print(gcp.gc.modified_vectors) def remove_abl(self, gcode_path): gcp = self.get_gcode_gcp(gcode_path) diff --git a/src/TheAntFarm/controller/controller_manager.py b/src/TheAntFarm/controller/controller_manager.py index bf9eb7d..21b1858 100644 --- a/src/TheAntFarm/controller/controller_manager.py +++ b/src/TheAntFarm/controller/controller_manager.py @@ -1,3 +1,4 @@ +import os from PySide2.QtCore import Slot, QObject, Signal, QTimer from PySide2.QtGui import QPixmap import re @@ -15,13 +16,17 @@ class ControllerWorker(QObject): update_layer_s = Signal(Od, str, str, bool) # Signal to update layer visualization + update_align_layer_s = Signal(Od, str, str, bool) # Signal to update align layer visualization + update_align_layer_view_s = Signal(list) # Signal to update align layer visualization (flipping) update_path_s = Signal(str, list) # Signal to update path visualization update_camera_image_s = Signal(QPixmap) # Signal to update Camera Image + update_camera_list_s = Signal(list) # Signal to update Camera list detected update_status_s = Signal(Od) # Signal to update controller status update_console_text_s = Signal(str) # Signal to send text to the console textEdit serial_send_s = Signal(bytes) # Signal to send text to the serial serial_tx_available_s = Signal() # Signal to send text to the serial - + update_align_points_s = Signal(list) # Signal to update the list of alignment points + touched_probe_s = Signal() # Signal the probe touched update_probe_s = Signal(list) # Signal to update probe value send_abl_s = Signal(tuple, tuple) update_abl_s = Signal(list) # Signal to update Auto-Bed-Levelling value @@ -46,6 +51,8 @@ def __init__(self, serial_rx_queue, serial_tx_queue, settings): self.serialTxQueue = serial_tx_queue self.settings = settings + self.connected = False # Flag to know if the controller is connected + self.view_controller = ViewController(self.settings) self.control_controller = ControlController(self.settings) self.align_controller = AlignController(self.settings) @@ -65,6 +72,7 @@ def __init__(self, serial_rx_queue, serial_tx_queue, settings): self.dro_status_updated = False self.abl_apply_active = True + self.align_apply_active = True self.prb_activated = False self.abl_activated = False self.prb_updated = False @@ -97,8 +105,11 @@ def __init__(self, serial_rx_queue, serial_tx_queue, settings): self.send_soft_reset = True + self.camera_zoom = 1 + @Slot(bool) def on_controller_connection(self, connected): + self.connected = connected if connected: self.buffered_size = 0 self.poll_timer.start() @@ -178,6 +189,7 @@ def parse_rx_queue(self): [ack_prb_flag, ack_abl_flag, send_next, other_cmd_flag] = \ self.control_controller.process_probe_and_abl() if ack_prb_flag: + self.touched_probe_s.emit() self.ack_probe() if ack_abl_flag: self.ack_auto_bed_levelling() @@ -361,27 +373,53 @@ def set_abl_active(self, abl_active=True): self.abl_apply_active = abl_active self.select_active_gcode(self.active_gcode_path) + def set_align_active(self, align_active=True, align_data=()): + self.control_controller.set_align_data(align_data) + self.align_apply_active = align_active + self.select_active_gcode(self.active_gcode_path) + def vectorize_new_gcode_file(self, gcode_path): self.control_controller.load_gcode_file({}, gcode_path) self.gcode_vectorized_s.emit(gcode_path) def select_active_gcode(self, gcode_path): - self.active_gcode_path = gcode_path - redraw = False - visible = True - abl_val = self.control_controller.get_abl_value() - logger.debug("ABL_val " + str(abl_val)) - logger.debug("ABL_active " + str(self.abl_apply_active)) - if abl_val != [] and self.abl_apply_active: - logger.debug("Apply ABL") - self.control_controller.apply_abl(gcode_path) - redraw = True + if os.path.isfile(gcode_path): + self.active_gcode_path = gcode_path + redraw = False + visible = True + + abl_val = self.control_controller.get_abl_value() + logger.debug("ABL_val " + str(abl_val)) + logger.debug("ABL_active " + str(self.abl_apply_active)) + + align_data = self.control_controller.get_align_data() + logger.debug("Align_val " + str(align_data)) + logger.debug("Align_active " + str(self.align_apply_active)) + + if align_data != [] and self.align_apply_active: + logger.debug("Apply Alignment") + self.control_controller.apply_alignment(gcode_path) + redraw_align = True + else: + logger.debug("Remove Alignment") + redraw_align = self.control_controller.remove_alignment(gcode_path) + + if abl_val != [] and self.abl_apply_active: + # print("FORCE FAKE ABL") + # if self.abl_apply_active: + logger.debug("Apply ABL") + self.control_controller.apply_abl(gcode_path) + redraw_abl = True + else: + logger.debug("Remove ABL") + redraw_abl = self.control_controller.remove_abl(gcode_path) + redraw = redraw_abl or redraw_align + logger.debug("ABL Done") + (tag, v) = self.control_controller.get_gcode_tag_and_v(gcode_path) + logger.debug("Update Gcode View: " + str(redraw)) + self.update_gcode_s.emit(tag, v, visible, redraw) else: - logger.debug("Remove ABL") - redraw = self.control_controller.remove_abl(gcode_path) - logger.debug("ABL Done") - (tag, v) = self.control_controller.get_gcode_tag_and_v(gcode_path) - self.update_gcode_s.emit(tag, v, visible, redraw) + logger.warning("No GCode Data Available. Please select a valid gcode file.") def get_gcode_data(self, gcode_path): return self.control_controller.get_gcode_tag_and_v(gcode_path) @@ -483,10 +521,79 @@ def start_tool_change(self): # ***************** ALIGN related functions. ***************** # + @Slot(str, str) + def load_new_align_layer(self, layer, layer_path): + [loaded_layer, exc_flag] = self.align_controller.load_new_align_layer(layer, layer_path) + if loaded_layer is not None: + self.update_align_layer_s.emit(loaded_layer, layer, layer_path, exc_flag) + else: + logger.warning("Invalid file data. No geometries found in file: " + str(layer_path)) + self.update_align_layer_s.emit(None, layer, "", False) + + @Slot(bool) + def flip_align_layer_horizontally(self, flipped): + self.align_controller.flip_align_layer_horizontally(flipped) + # todo: emit signal here to update align layer + self.update_align_layer_view_s.emit(self.align_controller.flipping_view) + + @Slot(bool) + def flip_align_layer_vertically(self, flipped): + self.align_controller.flip_align_layer_vertically(flipped) + # todo: emit signal here to update align layer + self.update_align_layer_view_s.emit(self.align_controller.flipping_view) + + @Slot(list, tuple) + def add_new_align_point(self, geometry_point, offset_flag): + if self.connected: + status = self.get_status_report() + if status: + if "wpos" in status.keys(): + working_position_coords = status["wpos"] + working_position_point = [working_position_coords[0], working_position_coords[1]] + if offset_flag: + ox = self.settings.machine_settings.tool_camera_offset_x + oy = self.settings.machine_settings.tool_camera_offset_y + offset_info = (ox, oy) + working_position_point[0] -= offset_info[0] + working_position_point[1] -= offset_info[1] + flipping_info = self.align_controller.flipping_view + if flipping_info[0]: + geometry_point[0] *= -1.0 + if flipping_info[1]: + geometry_point[1] *= -1.0 + align_data = self.align_controller.add_new_align_point(geometry_point, working_position_point) + self.update_align_points_s.emit(align_data) + else: + logger.warning("Invalid Working Position Information") + else: + logger.warning("Invalid Machine Status Information") + else: + logger.warning("Machine Disconnected") + + @Slot(list) + def remove_align_points(self, selected_rows): + align_data = self.align_controller.remove_align_points(selected_rows) + self.update_align_points_s.emit(align_data) + def on_camera_timeout(self): if self.align_active: - image = self.align_controller.camera_new_frame() - self.update_camera_image_s.emit(QPixmap.fromImage(image)) + image = self.align_controller.camera_new_frame(self.camera_zoom) + if image: + self.update_camera_image_s.emit(QPixmap.fromImage(image)) + else: + self.update_camera_image_s.emit(QPixmap()) # empty image + + def refresh_camera_list(self): + cam_list = self.align_controller.get_camera_list() + self.update_camera_list_s.emit(cam_list) + + def update_camera_selected(self, index): + # Take in account that index 0 indicates NO CAMERA + self.align_controller.update_camera_selected(index-1) + + @Slot(int) + def update_camera_zoom_value(self, zoom_value): + self.camera_zoom = zoom_value @Slot(bool) def set_align_is_active(self, align_is_active): diff --git a/src/TheAntFarm/double_side_manager.py b/src/TheAntFarm/double_side_manager.py index d57ef1e..8185309 100644 --- a/src/TheAntFarm/double_side_manager.py +++ b/src/TheAntFarm/double_side_manager.py @@ -1,4 +1,4 @@ - +from PySide2 import QtMultimedia import cv2 import numpy as np @@ -6,12 +6,20 @@ class DoubleSideManager: def __init__(self): - self.detected_holes = [] - # grab webcam - self.cap = cv2.VideoCapture(4, cv2.CAP_DSHOW) - self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) - self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) + self.cap = None + self.holes_detector = self.init_holes_detector() + + @staticmethod + def list_cameras_indexes(): + index = 0 + arr = [] + info = QtMultimedia.QCameraInfo() + for cameraDevice in info.availableCameras(): + arr.append(cameraDevice.description()) + # print(cameraDevice.description()) + + return arr @staticmethod def rotate_image(image, angle): @@ -20,22 +28,57 @@ def rotate_image(image, angle): result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR) return result + def update_camera(self, index): + if index >= 0: + self.cap = cv2.VideoCapture(index, cv2.CAP_DSHOW) + self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) + self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) + else: + if isinstance(self.cap, cv2.VideoCapture): + self.cap.release() + def get_webcam_frame(self): - ret, frame = self.cap.read() - frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) - # frame = self.rotate_image(frame, 0) + frame = None + if self.cap: + ret, frame = self.cap.read() + if ret: + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + # TODO: add rotation angle in the align settings + frame = self.rotate_image(frame, 180) return frame @staticmethod - def detect_holes(frame, thr1=125): - image = cv2.cvtColor(frame.copy(), cv2.COLOR_RGB2GRAY) - image = cv2.GaussianBlur(image, (15, 15), 0) - # image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) - # image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 25, 2) - # _, image = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY) - _, image = cv2.threshold(image, thr1, 255, cv2.THRESH_BINARY) + def detect_holes(frame_in, thr1=125, zoom_f=2): + + width = frame_in.shape[1] + height = frame_in.shape[0] + + width_z = width/zoom_f + height_z = height/zoom_f + + crop_x = int((width - width_z)/2) + crop_y = int((height - height_z)/2) + cropped = frame_in[crop_y:height-crop_y, crop_x:width-crop_x] + frame = cv2.resize(cropped, None, fx=zoom_f, fy=zoom_f) + # frame[:, :, 0] = 0 + # frame[:, :, 2] = 0 + + image_gray = cv2.cvtColor(frame.copy(), cv2.COLOR_RGB2GRAY) + image_gray[np.where(image_gray > thr1)] = 255 + + + # image = cv2.GaussianBlur(image_gray, (15, 15), 0) + # image = cv2.adaptiveThreshold(image_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) + # image = cv2.adaptiveThreshold(image_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 25, 2) + # _, image = cv2.threshold(image_gray, 200, 255, cv2.THRESH_BINARY) + + + ret, image = cv2.threshold(image_gray, thr1, 255, cv2.THRESH_BINARY) + # imagebn = image.copy() - image = cv2.Canny(image, 50, 120) + + # image = cv2.Canny(image, 50, 120) + # frame = cv2.cvtColor(imagebn, cv2.COLOR_GRAY2RGB) # circles = cv2.HoughCircles(image, cv2.HOUGH_GRADIENT, 22, minDist=1, maxRadius=50) @@ -49,22 +92,32 @@ def detect_holes(frame, thr1=125): # hx = x[i] # hy = y[i] # cv2.circle(frame, (hx, hy), 3, (255, 255, 255), -1) + # image = image_gray + frame_out = frame if True: - cnts, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + black_holes = cv2.HoughCircles(image, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, + maxRadius=0) + + black_holes = None + if black_holes is not None: + black_circles = np.round(black_holes[0, :]).astype("int") + for (x, y, r) in black_circles: + cv2.circle(frame_out, (x, y), r, (255, 0, 255), 2) + cnts, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # loop over the contours for c in cnts: # compute the center of the contour M = cv2.moments(c) (cx, cy), radius = cv2.minEnclosingCircle(c) - if M["m00"] != 0.0 and radius < 10: + if M["m00"] != 0.0 and radius < 10 and radius > 3: cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) # draw the contour and center of the shape on the image - cv2.drawContours(frame, [c], -1, (255, 255, 255), 1) - cv2.circle(frame, (cX, cY), 3, (255, 0, 0), -1) + cv2.drawContours(frame_out, [c], -1, (255, 255, 255), 1) + cv2.circle(frame_out, (cX, cY), 3, (255, 0, 0), -1) # Green color in BGR color = (0, 0, 255) @@ -77,9 +130,68 @@ def detect_holes(frame, thr1=125): whalf = int(width/2) start_point = (whalf, 0) end_point = (whalf, height) - frame = cv2.line(frame, start_point, end_point, color, thickness) + + frame_out = cv2.line(frame_out, start_point, end_point, color, thickness) start_point = (0, hhalf) end_point = (width, hhalf) - frame = cv2.line(frame, start_point, end_point, color, thickness) + frame_out = cv2.line(frame_out, start_point, end_point, color, thickness) + + return frame_out + + def detect_holes_test(self, frame_in, thr1=125): + + zoom_f = 2 + width = frame_in.shape[1] + height = frame_in.shape[0] + crop_x = int(width / (2 * zoom_f)) + crop_y = int(height / (2 * zoom_f)) + cropped = frame_in[crop_y:3*crop_y, crop_x:3*crop_x] + frame = cv2.resize(cropped, None, fx=zoom_f, fy=zoom_f) + + overlay = frame.copy() + keypoints = self.holes_detector.detect(frame) + for k in keypoints: + cv2.circle(overlay, (int(k.pt[0]), int(k.pt[1])), int(k.size / 2), (0, 0, 255), -1) + cv2.line(overlay, (int(k.pt[0]) - 20, int(k.pt[1])), (int(k.pt[0]) + 20, int(k.pt[1])), (0, 0, 0), 3) + cv2.line(overlay, (int(k.pt[0]), int(k.pt[1]) - 20), (int(k.pt[0]), int(k.pt[1]) + 20), (0, 0, 0), 3) + + opacity = 0.5 + cv2.addWeighted(overlay, opacity, frame, 1 - opacity, 0, frame) + + # Uncomment to resize to fit output window if needed + + # cv2.imshow("Output", frame) return frame + + @staticmethod + def init_holes_detector(): + + # Setup BlobDetector + detector = cv2.SimpleBlobDetector_create() + params = cv2.SimpleBlobDetector_Params() + + # Filter by Area. + params.filterByArea = True + params.minArea = 2 + params.maxArea = 200 + + # Filter by Circularity + params.filterByCircularity = True + params.minCircularity = 0.3 + + # Filter by Convexity + params.filterByConvexity = False + params.minConvexity = 0.87 + + # Filter by Inertia + params.filterByInertia = True + params.minInertiaRatio = 0.8 + + # Distance Between Blobs + params.minDistBetweenBlobs = 3 + + # Create a detector with the parameters + detector = cv2.SimpleBlobDetector_create(params) + return detector + diff --git a/src/TheAntFarm/qcamera_label.py b/src/TheAntFarm/qcamera_label.py new file mode 100644 index 0000000..96e39a8 --- /dev/null +++ b/src/TheAntFarm/qcamera_label.py @@ -0,0 +1,18 @@ +from PySide2.QtWidgets import QLabel +from PySide2.QtGui import QWheelEvent +from PySide2.QtCore import Signal + + +class QCameraLabel(QLabel): + mouse_wheel_up_or_down_s = Signal(int) + + def __init__(self, parent): + super(QCameraLabel, self).__init__(parent) + + def wheelEvent(self, event: QWheelEvent): + if event.angleDelta().x() > 0 or event.angleDelta().y() > 0: + self.mouse_wheel_up_or_down_s.emit(1) + elif event.angleDelta().x() < 0 or event.angleDelta().y() < 0: + self.mouse_wheel_up_or_down_s.emit(-1) + else: + pass # todo: this event should never be catched, an error could be raised diff --git a/src/TheAntFarm/qledlabel.py b/src/TheAntFarm/qledlabel.py new file mode 100644 index 0000000..a3bf02e --- /dev/null +++ b/src/TheAntFarm/qledlabel.py @@ -0,0 +1,41 @@ +from PySide2.QtWidgets import QLabel +from PySide2.QtGui import QResizeEvent + + +class QLedLabel(QLabel): + + grey_ss = "color: white;background-color: qlineargradient(spread:pad, x1:0.145, " \ + "y1:0.16, x2:1, y2:1, stop:0 rgba(200, 200, 200, 120), stop:1 rgba(220, 220, 220, 255));" + green_ss = "color: white;background-color: qlineargradient(spread:pad, x1:0.145, y1:0.16, " \ + "x2:1, y2:1, stop:0 rgba(20, 252, 7, 255), stop:1 rgba(25, 134, 5, 255));" + red_ss = "color: white;background-color: qlineargradient(spread:pad, x1:0.145, y1:0.16" \ + ", x2:0.92, y2:0.988636, stop:0 rgba(255, 12, 12, 255), stop:0.869347 rgba(103, 0, 0, 255));" + orange_ss = "color: white;background-color: qlineargradient(spread:pad, x1:0.232, y1:0.272, " \ + "x2:0.98, y2:0.959773, stop:0 rgba(255, 113, 4, 255), stop:1 rgba(91, 41, 7, 255));" + blue_ss = "color: white;background-color: qlineargradient(spread:pad, x1:0.04, y1:0.0565909, " \ + "x2:0.799, y2:0.795, stop:0 rgba(203, 220, 255, 255), stop:0.41206 rgba(0, 115, 255, 255), stop:1 rgba(" \ + "0, 49, 109, 255));" + yellow_ss = "color: white;background-color: qlineargradient(spread:pad, x1:0.04, y1:0.0565909, " \ + "x2:0.799, y2:0.795, stop:0 rgba(255, 255, 0, 255), stop:1 rgba(155, 155, 0, 255));" + + led_colors = {"grey": grey_ss, "green": green_ss, "red": red_ss, "orange": orange_ss, "blue": blue_ss, + "yellow": yellow_ss} + + def __init__(self, parent): + super(QLedLabel, self).__init__(parent) + self.setMinimumSize(self.sizeHint()) + self.actual_color = "grey" + self.set_led_color(self.actual_color) + + def set_led_color(self, state_color): + """Set color of led with correct border-radius. + Hypothesis: minimum height and width of the led are equals.""" + if state_color in self.led_colors: + self.actual_color = state_color + state_ss = "QLabel{ " + self.led_colors[state_color] + "border-radius: " + str(self.minimumHeight()/2) + \ + "px;}" + self.setStyleSheet(state_ss) + + def resizeEvent(self, event: QResizeEvent) -> None: + """On resize event make sure the border-radius resizes accordingly. """ + self.set_led_color(self.actual_color) diff --git a/src/TheAntFarm/resources/icons/black_alignment_applied.svg b/src/TheAntFarm/resources/icons/black_alignment_applied.svg new file mode 100644 index 0000000..d153d64 --- /dev/null +++ b/src/TheAntFarm/resources/icons/black_alignment_applied.svg @@ -0,0 +1,71 @@ + + + + + + + + + image/svg+xml + + + + + Openclipart + + + + + + + + + + + + diff --git a/src/TheAntFarm/resources/icons/black_apply_align.svg b/src/TheAntFarm/resources/icons/black_apply_align.svg new file mode 100644 index 0000000..c3aa9f7 --- /dev/null +++ b/src/TheAntFarm/resources/icons/black_apply_align.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + + + + + + + + + diff --git a/src/TheAntFarm/resources/logo/the_ant_farm_logo.svg b/src/TheAntFarm/resources/logo/the_ant_farm_logo.svg index 2bf0706..e4d5c1f 100644 --- a/src/TheAntFarm/resources/logo/the_ant_farm_logo.svg +++ b/src/TheAntFarm/resources/logo/the_ant_farm_logo.svg @@ -33,7 +33,7 @@ id="g3522" transform="matrix(1.2994248,0,0,1.2994248,-33.043187,-36.454228)"> 0: + zgs = None + if len(points[0]) == 3: + xgs, ygs, zgs = list(zip(*points)) + else: + xgs, ygs = list(zip(*points)) + + gps = np.vstack([xgs, ygs]).T + nxgs, nygs = self.tps_coeff.compute_points_transform(gps) + + if len(points[0]) == 3: + new_points_coord = list(zip(nxgs, nygs, zgs)) + else: + new_points_coord = list(zip(nxgs, nygs)) + return new_points_coord + else: + return None + + diff --git a/src/TheAntFarm/shape_core/gcode_drill_converter.py b/src/TheAntFarm/shape_core/gcode_drill_converter.py new file mode 100644 index 0000000..2ca15ea --- /dev/null +++ b/src/TheAntFarm/shape_core/gcode_drill_converter.py @@ -0,0 +1,93 @@ + +import os +import math +import numpy as np + +from .gcode_manager import GCodeParser +from gerber.excellon import ExcellonFile, ExcellonStatement +from .geometry_manager import Geom, merge_polygons + + +class DrillGcodeConverter: + def __init__(self, cfg): + + self.gcode_path = "" + self.cfg = cfg + self.parser = GCodeParser(None) + + def load_gcode(self, gcode_path): + self.gcode_path = gcode_path + + def convert(self): + + if self.gcode_path: + if os.path.isfile(self.gcode_path): + self.parser.load_gcode_file(self.gcode_path) + self.parser.interp() + self.parser.vectorize() + else: + print("Invalid GCode Path") + + def get_drill_layer(self): + + layer = None + if self.parser is not None: + if self.parser.gc is not None: + if self.parser.gc.original_vectors is not None: + ov = self.parser.gc.original_vectors + coords = np.array([v.coords for v in ov if v.type == v.WORKING]) + z_min = np.min(coords, axis=0)[2] + drill_coords = coords[np.where(np.isclose(coords[:, 2], z_min))[0], :] + + mp = [] + for i in range(drill_coords.shape[0]): + dd = self.cfg["default_gcode_drill_size"] + center_coords = drill_coords[i, :].tolist() + circle_coords = self.get_all_circle_coords(center_coords, + radius=dd, + n_points=40) + gd = { + "points": circle_coords, + "closed": True, + "polarity": "dark", + "complex": False + } + + g = Geom(gd) + if g.closed: + mp.append(g) + + layer = merge_polygons(mp) + print(layer) + + else: + print("No Vectorized GCode") + else: + print("No Loaded GCode") + else: + print("No Active GCode Parser") + + return layer + + # https://gis.stackexchange.com/questions/394955/generating-approximate-polygon-for-circle-with-given-radius-and-centre-without + @staticmethod + # This function gets just one pair of coordinates based on the angle theta + def get_circle_coord(theta, x_center, y_center, z_center, radius): + x = radius * math.cos(theta) + x_center + y = radius * math.sin(theta) + y_center + return x, y, z_center + + # This function gets all the pairs of coordinates + def get_all_circle_coords(self, center_coords, radius, n_points): + x_center, y_center, z_center = center_coords + thetas = [i/n_points * math.tau for i in range(n_points)] + circle_coords = [self.get_circle_coord(theta, x_center, y_center, z_center, radius) for theta in thetas] + return circle_coords + + + + + + + + diff --git a/src/TheAntFarm/shape_core/gcode_manager.py b/src/TheAntFarm/shape_core/gcode_manager.py index 4d43f4c..e7b7aa2 100644 --- a/src/TheAntFarm/shape_core/gcode_manager.py +++ b/src/TheAntFarm/shape_core/gcode_manager.py @@ -7,8 +7,10 @@ from datetime import datetime import scipy.interpolate as spi from shapely.geometry import LineString + from .macros_manager import Macros from .commands_manager import CommandManager +from .align_manager import AlignManager class GCoder: @@ -442,11 +444,12 @@ def add_job_info(self): gc += "\n" self.gcode.append(gc) - def gcode_comment(self, txt): + @staticmethod + def gcode_comment(txt): c = "" lines = txt.split('\n') - for l in lines: - c += "(" + l + ")\n" + for ln in lines: + c += "(" + ln + ")\n" return c def insert_comment(self, txt): @@ -604,7 +607,10 @@ def __repr__(self): def copy(self): cnp = GcodePoint() - cnp.coords = self.coords.copy() + if isinstance(self.coords, tuple): + cnp.coords = list(self.coords).copy() + else: + cnp.coords = self.coords.copy() cnp.line = self.line cnp.sub_line = self.sub_line cnp.type = self.type @@ -638,8 +644,37 @@ def __init__(self, lines): self.modified_lines = [] self.gcll = [] self.original_vectors = [] + self.aligned_vectors = [] self.modified_vectors = [] self.bb = None + self.aligned_bb = None + + def get_gcode_original_vectors_copy(self): + print("GCODEX") + govc = [] + for p in self.original_vectors: + nwp = p.copy() + govc.append(nwp) + return govc + + def get_bbox(self, type=None): + if type is None: + if self.aligned_vectors: + return self.aligned_bb + else: + return self.bb + elif type == "original": + return self.bb + elif type == "modified": + if self.aligned_vectors: + return self.aligned_bb + else: + return self.bb + elif type == "aligned": + if self.aligned_vectors: + return self.aligned_bb + else: + return self.bb class GCodeParser: @@ -707,6 +742,9 @@ def interp(self, single_line=None): if splitted: if splitted[0].upper().startswith("G"): # second command + # TODO: issue with munich gerber gcode. check + print("splitted") + print(splitted) cmd = splitted.pop(0) ct = cmd[0] cd = [int(x) for x in cmd[1::].split(".")] @@ -732,8 +770,12 @@ def recode_gcode(self): # - Modified Loaded gcv = self.gc.modified_vectors else: - # - Original Loaded - gcv = self.gc.original_vectors + if self.gc.aligned_vectors: + # - Aligned Loaded + gcv = self.gc.aligned_vectors + else: + # - Original Loaded + gcv = self.gc.original_vectors gcl = self.gc.gcll if gcv or gcl: gcv_len = len(gcv) @@ -820,14 +862,62 @@ def get_gcode(self): def get_gcode_original_vectors(self): return self.gc.original_vectors + def get_gcode_original_vectors_copy(self): + govc = [] + for p in self.gc.original_vectors: + nwp = p.copy() + govc.append(nwp) + return govc + def get_gcode_vectors(self): if self.gc.modified_vectors: return self.gc.modified_vectors else: - return self.gc.original_vectors + if self.gc.aligned_vectors: + return self.gc.aligned_vectors + else: + return self.gc.original_vectors def get_bbox(self): - return self.gc.bb + return self.gc.get_bbox() + + +class GCodeAlignment: + def __init__(self, gc): + self.gc = gc + self.am = AlignManager() + + def update_align_info(self, align_point_data): + self.am.load_sampled_points(align_point_data) + + def apply_align(self): + print("GCode Alignment Start") + align_flag = True + if self.gc is not None and self.am.is_sampled_point_loaded(): + print("Sampled Point Loaded") + coords = [p.coords.copy() for p in self.gc.original_vectors] + new_coords = self.am.compute_points_transform(coords) + avl = self.gc.get_gcode_original_vectors_copy() + bb_max = [-1e6, -1e6, -1e6] + bb_min = [1e6, 1e6, 1e6] + for i, p in enumerate(avl): + nc = np.array(new_coords[i]) + for z, e in enumerate(nc): + bb_max[z] = max(bb_max[z], nc[z]) + bb_min[z] = min(bb_min[z], nc[z]) + p.coords = nc + + self.gc.aligned_vectors = avl + self.gc.aligned_bb = tuple(bb_min + bb_max) + align_flag = True + else: + print("Sampled Point NOT Loaded") + self.gc.aligned_vectors = [] + self.gc.aligned_bb = None + align_flag = False + print("GCode Alignment Stop") + print(align_flag) + return align_flag class GCodeLeveler: @@ -862,7 +952,7 @@ def get_grid_lines(self): def get_dummy_grid_data(self): grid_steps = 10 if self.gc is not None: - bb = self.gc.bb + bb = self.gc.get_bbox() if bb is not None: x_min = bb[0] y_min = bb[1] @@ -925,7 +1015,15 @@ def apply_abl(self): pre_pc = None min_step = min(self.grid_step) print("Min Step ", min_step) - for p in self.gc.original_vectors: + + if self.gc.aligned_vectors: + print("Apply ABL: Loaded Aligned Vectors") + data = self.gc.aligned_vectors + else: + print("Apply ABL: Loaded Originals Vectors") + data = self.gc.original_vectors + + for p in data: np_l = [] nwp = p.copy() delta = self.ig(nwp.coords[0], nwp.coords[1]) @@ -934,7 +1032,7 @@ def apply_abl(self): pc = np.array(nwp.coords[:2]) seg_len = np.linalg.norm(pc - pre_pc) sub_line = 0 - if seg_len <= min_step and seg_len > 0.1: + if min_step >= seg_len > 0.1: i_l = self.get_grid_intersection(pc, pre_pc) if i_l: for i in i_l: diff --git a/src/TheAntFarm/shape_core/geometry_manager.py b/src/TheAntFarm/shape_core/geometry_manager.py index 7aa00f7..e12974c 100644 --- a/src/TheAntFarm/shape_core/geometry_manager.py +++ b/src/TheAntFarm/shape_core/geometry_manager.py @@ -1,5 +1,6 @@ import time import pyclipper as pc +import shapely.geometry import shapely.geometry as shg from shapely.ops import unary_union @@ -482,6 +483,21 @@ def get_bbox_area_sh(geom): return a +def is_overlaping_multiple_polygons(polygon, polygon_list, shapely_poly=False): + # evaluate if polygon overlap one or more polygons in polygon_list + + if shapely_poly: + diff_polys = polygon_list.difference(polygon) + else: + sh_poly = polygon.geom + sh_poly_list = [p.geom for p in polygon_list] + sh_mpoly = shapely.geometry.MultiPolygon(sh_poly_list) + diff_polys = sh_mpoly.difference(sh_poly) + + return len(diff_polys.geoms) < len(polygon_list.geoms) - 1 + + + class Geom: def __init__(self, gdata, complex=False): diff --git a/src/TheAntFarm/shape_core/path_manager.py b/src/TheAntFarm/shape_core/path_manager.py index de1edd6..e1bf5bd 100644 --- a/src/TheAntFarm/shape_core/path_manager.py +++ b/src/TheAntFarm/shape_core/path_manager.py @@ -1,9 +1,12 @@ # import time + +import shapely.geometry from shapely.geometry import Polygon, LineString, MultiLineString, Point, MultiPoint from shapely.ops import substring from collections import OrderedDict -from .geometry_manager import merge_polygons_path, offset_polygon, offset_polygon_holes, get_bbox_area_sh, fill_holes_sh, get_poly_diameter +from .geometry_manager import (merge_polygons_path, offset_polygon, offset_polygon_holes, + get_bbox_area_sh, fill_holes_sh, get_poly_diameter, is_overlaping_multiple_polygons) from .path_optimizer import Optimizer import numpy as np @@ -274,8 +277,20 @@ def execute_gerber(self): if og is not None: og_list.append(og) + pre_len = len(og_list) og_list = merge_polygons_path(og_list) + invalid_path_ids = [] + # og_list contains the first path so at this point is possible to evaluate if is a valid path + if len(og_list) < pre_len: + # the path is invalid, some gerber features will not be milled correctly + prev_sh_poly = shapely.geometry.MultiPolygon(prev_poly) + for i, g in enumerate(og_list): + check = is_overlaping_multiple_polygons(g, prev_sh_poly, shapely_poly=True) + if check: + # path surround multiple polygon so it isn't a valid path + invalid_path_ids.append(i) + # for the next steps, starting from the previous path, enlarge it by the tool radius # make bollean or on it and then reduce it by the tool radius # at that point it is enlarged by the * (1 - ) @@ -286,20 +301,27 @@ def execute_gerber(self): t1 = time.time() print("Path Generation Done in " + str(t1-t0) + " sec") + print("DRC Check Output: " + str(len(invalid_path_ids)) + " invalid paths " + str(invalid_path_ids)) og_list = self.check_min_area(og_list) # extract the linestring from paths polygons path = [] - for g in og_list: + path_counter = 0 + invalid_paths = [] + for j, g in enumerate(og_list): ex_path = g.exterior if ex_path.geom_type == "LinearRing" or ex_path.type == "LineString": path.append(ex_path) + if j in invalid_path_ids: + invalid_paths.append(path_counter) + path_counter += 1 for i in g.interiors: if ex_path.geom_type == "LinearRing" or ex_path.type == "LineString": path.append(i) + path_counter += 1 t_d = self.cfg['tool_diameter'] - self.path = [((t_d, "gerber"), path)] + self.path = [((t_d, "gerber"), path, invalid_paths)] def check_min_area(self, og_list): big_poly = [] @@ -320,7 +342,6 @@ def check_min_area(self, og_list): big_poly.append(p) print("REMOVED: " + str(old_poly - new_poly)) - return big_poly def execute_pocketing(self): @@ -344,7 +365,7 @@ def execute_pocketing(self): milled_list.append(False) # for the next steps, starting from the previous path, enlarge it by the tool radius - # make bollean or on it and then reduce it by the tool radius + # make boolean-or on it and then reduce it by the tool radius # at that point it is enlarged by the * (1 - ) # todo: check the formula @@ -409,8 +430,16 @@ def execute_drill(self, not_to_drill=None): for bit_k in drill_per_bit.keys(): bit_points = drill_per_bit[bit_k] if 'optimize' in self.cfg.keys(): - if self.cfg['optimize']: + if isinstance(self.cfg['optimize'], int): opt = Optimizer(bit_points) + availlable_opt_types = opt.get_optimization_types() + if 0 <= self.cfg['optimize'] < len(availlable_opt_types): + opt_type = availlable_opt_types[self.cfg['optimize']] + opt.set_optimization_type(opt_type) + + # opt = Optimizer(bit_points, optimizer_type="genetic") + # opt = Optimizer(bit_points, optimizer_type="two_opt") + optimized_bit_points = opt.get_optimized_path() drill_per_bit[bit_k] = optimized_bit_points #print("Bit " + str(bit_k) + " " + str(optimized_bit_points)) @@ -423,7 +452,7 @@ def execute_drill(self, not_to_drill=None): paths.append(((k, "drill"), [LineString(drill_per_bit[k])])) # if holes have already been performed by the pocketing procedure, - # the drilling path will be append to the pocketing one + # the drilling path will be appended to the pocketing one if not_to_drill is not None: if any(not_to_drill) and self.path is not None: diff --git a/src/TheAntFarm/shape_core/path_optimizer.py b/src/TheAntFarm/shape_core/path_optimizer.py index 8bc2b3f..a2ea5ef 100644 --- a/src/TheAntFarm/shape_core/path_optimizer.py +++ b/src/TheAntFarm/shape_core/path_optimizer.py @@ -1,110 +1,175 @@ # from: https://github.com/ezstoltz/genetic-algorithm # import numpy as np, random, operator, pandas as pd, matplotlib.pyplot as plt +import sys import numpy as np +from scipy.spatial import distance +from operator import itemgetter +from scipy.sparse.csgraph import shortest_path import random import operator from shapely.geometry import LineString, Point #import matplotlib.pyplot as plt -class City: - def __init__(self, x, y): - self.x = x - self.y = y - - def distance(self, city): - xDis = abs(self.x - city.x) - yDis = abs(self.y - city.y) - distance = np.sqrt((xDis ** 2) + (yDis ** 2)) - return distance +class Optimizer: + + OPTIMIZATION_TYPES = ("nearest_insertion", "two_opt", "genetic") + + def __init__(self, coords, optimizer_type="nearest_insertion"): + self.v = len(coords) + self.coords = coords + self.distances = distance.cdist(coords, coords, 'euclidean') + self.optimizer_type = optimizer_type + + def set_optimization_type(self, opt_type): + if opt_type in self.OPTIMIZATION_TYPES: + self.optimizer_type = opt_type + return True + else: + return False + + def get_optimization_type(self): + return self.optimizer_type + + def get_optimization_types(self): + return self.OPTIMIZATION_TYPES + + def calculate_path_distance(self, path): + total_distance = np.sum(self.distances[path[:-1], path[1:]]) + return total_distance + + def nearest_insertion(self, points): + num_points = len(points) + unvisited = set(range(num_points)) + + first_point_matrix = distance.cdist([(0., 0.)], points, 'euclidean') + first_point_index = np.argmin(first_point_matrix) + + path = [first_point_index] + unvisited.remove(first_point_index) + + while unvisited: + min_distance = float('inf') + nearest_point = None + + for current_point in path: + for candidate in unvisited: + d = self.distances[current_point, candidate] + if d < min_distance: + min_distance = d + nearest_point = candidate + next_point = current_point + + insert_index = path.index(next_point) + 1 + path.insert(insert_index, nearest_point) + unvisited.remove(nearest_point) + + return path + + def two_opt(self, path): + new_distance = self.calculate_path_distance(path) + points = self.coords + best_path = path + improved = True + while improved: + improved = False + for i in range(1, len(points) - 2): + for j in range(i + 1, len(points)): + if j - i == 1: + continue + new_path = path[:] + new_path[i:j] = path[i:j][::-1] + new_distance = self.calculate_path_distance(new_path) + if new_distance < self.calculate_path_distance(best_path): + best_path = new_path + improved = True + path = best_path + # print("Final Distance: ", new_distance) + return best_path + + def get_optimized_path(self): + path_ids = list(range(len(self.coords))) + + start_distance = self.calculate_path_distance(path_ids) + + print("Selected OPT type:", self.optimizer_type) - def coords(self): - return (self.x, self.y) + print("Initial Distance: ", start_distance) - def __repr__(self): - return "(" + str(self.x) + "," + str(self.y) + ")" + if self.optimizer_type == "genetic": + path_ids = self.nearest_insertion(self.coords) + go = GeneticOptimizer(self.coords) + path_ids = go.get_optimized_path(cityList=path_ids) + + if self.optimizer_type == "two_opt": + path_ids = self.two_opt(path_ids) + + if self.optimizer_type == "nearest_insertion": + path_ids = self.nearest_insertion(self.coords) + + final_distance = self.calculate_path_distance(path_ids) + print("Final Distance: ", final_distance) + + return np.array(self.coords)[path_ids].tolist() + + +class Cities: + + def __init__(self, coords): + self.coords = coords + self.distances = distance.cdist(coords, coords, 'euclidean') + + def length(self, path0, path1): + return np.sum(self.distances[path0, path1]) class Fitness: - def __init__(self, route): + def __init__(self, route, cities): self.route = route + self.cities = cities self.distance = 0 self.fitness = 0.0 - + def routeDistance(self): if self.distance == 0: - pathDistance = 0 - for i in range(0, len(self.route)): - fromCity = self.route[i] - toCity = None - if i + 1 < len(self.route): - toCity = self.route[i + 1] - else: - toCity = self.route[0] - pathDistance += fromCity.distance(toCity) - self.distance = pathDistance + route0 = self.route + route1 = np.roll(self.route, -1) + self.distance = self.cities.length(route0, route1) return self.distance - + def routeFitness(self): if self.fitness == 0: self.fitness = 1 / float(self.routeDistance()) return self.fitness -class Optimizer: +class GeneticOptimizer: def __init__(self, points_coord): self.points_coord = points_coord self.population = [] + self.cities = Cities(points_coord) @staticmethod def createRoute(cityList): - route = random.sample(cityList, len(cityList)) + route = cityList.copy() + random.shuffle(route) return route def initialPopulation(self, popSize, cityList): - population = [] - for i in range(0, popSize): + population = [cityList] + for i in range(0, popSize-1): population.append(self.createRoute(cityList)) - return population - - @staticmethod - def check_pop_intersection(population): - if len(population): - routes = [] - c = population[0] - pp = c.coords() - nc = None - for i in range(1, len(population)): - nc = population[i] - p = nc.coords() - routes.append(LineString([pp, p])) - pp = p[:] - if nc is not None: - routes.append(LineString([pp, c.coords()])) - - flags = [False for z in range(len(routes))] - step = 1 - for i in range(len(routes)): - for j in range(i + 2, len(routes) - step): - a = routes[i] - b = routes[j] - if a.intersects(b): - flags[i] = True - flags[j] = True - step = 0 - return flags - else: - return [False for z in range(len(population))] + return np.array(population) def rankRoutes(self, population): fitnessResults = {} for i in range(0, len(population)): - fitnessResults[i] = Fitness(population[i]).routeFitness() + # print("Population:", population[i]) + fitnessResults[i] = Fitness(population[i], self.cities).routeFitness() return sorted(fitnessResults.items(), key=operator.itemgetter(1), reverse=True) def selection(self, popRanked, eliteSize): - selectionResults = [] n = np.array(popRanked) cs = n[1, :].cumsum() @@ -120,10 +185,7 @@ def selection(self, popRanked, eliteSize): return selectionResults def matingPool(self, population, selectionResults): - matingpool = [] - for i in range(0, len(selectionResults)): - index = selectionResults[i] - matingpool.append(population[index]) + matingpool = population[selectionResults] return matingpool def breed(self, parent1, parent2): @@ -148,15 +210,14 @@ def breed(self, parent1, parent2): def breedPopulation(self, matingpool, eliteSize): children = [] length = len(matingpool) - eliteSize - pool = random.sample(matingpool, len(matingpool)) - - for i in range(0, eliteSize): - children.append(matingpool[i]) + pool = matingpool.copy() + random.shuffle(matingpool) + children = matingpool[range(0, eliteSize)].tolist() for i in range(0, length): child = self.breed(pool[i], pool[len(matingpool)-i-1]) children.append(child) - return children + return np.array(children) def mutate(self, individual, mutationRate): for swapped in range(len(individual)): @@ -176,7 +237,7 @@ def mutatePopulation(self, population, mutationRate): for ind in range(0, len(population)): mutatedInd = self.mutate(population[ind], mutationRate) mutatedPop.append(mutatedInd) - return mutatedPop + return np.array(mutatedPop) def nextGeneration(self, currentGen, eliteSize, mutationRate): popRanked = self.rankRoutes(currentGen) @@ -188,7 +249,7 @@ def nextGeneration(self, currentGen, eliteSize, mutationRate): def geneticAlgorithm(self, population, popSize, eliteSize, mutationRate, generations): pop = self.initialPopulation(popSize, population) - print("Initial distance: " + str(1 / self.rankRoutes(pop)[0][1])) + # print("Initial distance: " + str(1 / self.rankRoutes(pop)[0][1])) x = int(generations/10) c = 0 @@ -202,7 +263,7 @@ def geneticAlgorithm(self, population, popSize, eliteSize, mutationRate, generat else: c += 1 - print("Final distance: " + str(1 / self.rankRoutes(pop)[0][1])) + # print("Final distance: " + str(1 / self.rankRoutes(pop)[0][1])) bestRouteIndex = self.rankRoutes(pop)[0][0] bestRoute = pop[bestRouteIndex] return bestRoute @@ -211,49 +272,18 @@ def geneticAlgorithm(self, population, popSize, eliteSize, mutationRate, generat def rotate(l, n): return l[n:] + l[:n] - def get_optimized_path(self): - points_coord = self.points_coord - cityList = [] - for p in points_coord: - cityList.append(City(x=p[0], y=p[1])) + def get_optimized_path(self, cityList=None): + points_coord = np.array(self.points_coord) + if cityList is None: + cityList = np.array(range(0, len(points_coord))) bestRoute = self.geneticAlgorithm(population=cityList, popSize=400, eliteSize=50, mutationRate=0.02, generations=800) - optimized_coords = [] - - for c in bestRoute: - optimized_coords.append((c.x, c.y)) - - # the path is ordered so that it starts from the point closest to 0.0 - - min_id = 0 - min_d = Point(optimized_coords[0]).distance(Point((0.0, 0.0))) - for i in range(len(optimized_coords)): - d = Point(optimized_coords[i]).distance(Point((0.0, 0.0))) - if d < min_d: - min_id = i - min_d = d - - pre_id = min_id - 1 - post_id = min_id + 1 - if min_id == len(optimized_coords) - 1: - post_id = 0 - - pre_d = Point(optimized_coords[pre_id]).distance(Point((0.0, 0.0))) - post_d = Point(optimized_coords[post_id]).distance(Point((0.0, 0.0))) - - if pre_d < post_d: - noc = self.rotate(optimized_coords, min_id) - else: - noc = self.rotate(optimized_coords, post_id) - - optimized_coords = noc - x = [] - y = [] - for c in optimized_coords: - x.append(c[0]) - y.append(c[1]) + first_point_matrix = distance.cdist([(0., 0.)], points_coord[bestRoute], 'euclidean') + first_point_index = np.argmin(first_point_matrix) + # optimized_coords = np.roll(points_coord[bestRoute], -first_point_index) + optimized_ids = np.roll(bestRoute, -first_point_index) - return optimized_coords + return optimized_ids if __name__ == "__main__": diff --git a/src/TheAntFarm/shape_core/visual_manager.py b/src/TheAntFarm/shape_core/visual_manager.py index f20f806..51afdae 100644 --- a/src/TheAntFarm/shape_core/visual_manager.py +++ b/src/TheAntFarm/shape_core/visual_manager.py @@ -11,6 +11,13 @@ from collections import OrderedDict import string import random +from shapely.geometry import Point +import shapely as sh +import logging + +logger = logging.getLogger(__name__) + +print(sh.__version__) class GLUTess: @@ -118,21 +125,32 @@ def define_contour(contour): class VisualLayer: DELTA = 1 - TOP_ORDER = {'drill': 1, 'profile': 2, 'top': 4, 'bottom': 5, 'nc_top': 3, 'nc_bottom': 6} - BTM_ORDER = {'drill': 1, 'profile': 2, 'top': 5, 'bottom': 4, 'nc_top': 6, 'nc_bottom': 3} + TOP_ORDER = {'selected': 1, 'drill': 2, 'profile': 3, 'top': 5, 'bottom': 6, 'nc_top': 4, 'nc_bottom': 7} + BTM_ORDER = {'selected': 1, 'drill': 2, 'profile': 3, 'top': 6, 'bottom': 5, 'nc_top': 7, 'nc_bottom': 4} POINTER_RADIUS = 0.5 POINTER_TAG = "POINTER" POINTER_COLOR = "orange" POINTER_SEGMENTS = 20 + SELECTED_TAG = "selected" - def __init__(self, canvas): + def __init__(self, canvas, selectable=False): self.canvas = canvas self.canvas.view.camera = PanZoomCamera(aspect=1) self.translucent_filter = Alpha() self.meshes = OrderedDict({}) self.paths = OrderedDict({}) - self.view = 0 + self.meshes_geom = OrderedDict({}) + self.paths_geom = OrderedDict({}) + + # self.view = 0 + self.orientation = 0 self.pointer_tag = "" + self.selectable = selectable + + self.selected_object = None + + if selectable: + self.canvas.events.mouse_double_click.connect(self.on_mouse_double_click) def compute_pointer(self, coords): segments = self.POINTER_SEGMENTS @@ -151,7 +169,7 @@ def create_pointer(self, coords): chars = string.ascii_uppercase + string.digits tag = self.POINTER_TAG + "_" + "".join(random.choice(chars) for _ in range(4)) self.pointer_tag = tag - self.create_line(tag, [pointer_coords], color=self.POINTER_COLOR, order=0, width=0.1) + self.create_line(tag, [pointer_coords], colors=self.POINTER_COLOR, order=0, width=0.1) def update_pointer(self, coords): if self.pointer_tag: @@ -194,7 +212,41 @@ def bottom_view(self): self.canvas._draw_order.clear() self.canvas.update() + def flip_camera(self, flipped): + self.canvas.view.camera.up = "+z" + self.canvas.view.camera.flip = (flipped) + + for m in self.meshes.keys(): + self.meshes[m].order = self.TOP_ORDER[m] + + self.canvas._draw_order.clear() + self.canvas.update() + def on_mouse_double_click(self, event): + if event.button == 1: # left click + self.remove_layer(self.SELECTED_TAG) + self.canvas.view.interactive = False + tr = self.canvas.scene.node_transform(self.canvas.view.scene) + pos = tr.map(event.pos) + self.canvas.view.interactive = True + + # get selected polygon using shapely + point = Point(pos) + for gk in self.meshes_geom.keys(): + if gk != self.SELECTED_TAG: + geom_list = self.meshes_geom[gk].copy() + contain_flag = False + shape = None + while geom_list and not contain_flag: + shape = geom_list.pop() + contain_flag = shape.geom.contains(point) + + # ToDo: to parametrize color of selection + if contain_flag: + self.add_layer(tag=self.SELECTED_TAG, geom_list=[shape], color="yellow", holes=False, auto_range=False) + break + + def on_mouse_click(self, event): self.orientation = 0 if self.orientation == 1 else 1 self.flip_view(orientation=self.orientation) @@ -230,6 +282,7 @@ def remove_layer(self, tag): # self.canvas.events.draw.disconnect(to_remove.on_draw) to_remove.parent = None del self.meshes[tag] + del self.meshes_geom[tag] def remove_path(self, tag): if tag in self.paths.keys(): @@ -238,9 +291,12 @@ def remove_path(self, tag): # self.canvas.events.draw.disconnect(to_remove.on_draw) to_remove.parent = None del p - del self.paths[tag] + if tag in self.paths.keys(): + del self.paths[tag] + if tag in self.paths_geom.keys(): + del self.paths_geom[tag] - def add_layer(self, tag, geom_list, color=None, holes=False): + def add_layer(self, tag, geom_list, color=None, holes=False, auto_range=True): ldata = [[], []] triangulizer = GLUTess() order = 0 @@ -259,21 +315,44 @@ def add_layer(self, tag, geom_list, color=None, holes=False): # ldata[0] += tri_off # ldata[1] += pts[:] #order = 0 - self.create_mesh(tag, ldata, color, order) + self.create_mesh(tag, ldata, color, order, auto_range=auto_range) + self.meshes_geom[tag] = geom_list + + def get_selected_centroid(self): + if self.SELECTED_TAG in self.meshes_geom.keys(): + sel_geom_list = self.meshes_geom[self.SELECTED_TAG] + if len(sel_geom_list) > 0: + centroid = list(sel_geom_list[0].geom.centroid.xy) + centroid = [centroid[0][0], centroid[1][0]] + return centroid + else: + logger.warning("No Active Selection found. Please select a Drill Position from the Alignment View") + else: + logger.warning("No Drill Information Loaded. Please Load a GCODE or EXCELLON file in the Alignment View") + return None - def add_path(self, tag, geom_list, color=None): + def add_path(self, tag, geom_list, color=None, warning_color='red'): # todo: add zbuffer controll if geom_list: ldata = [] order = 0 for d in geom_list: gl = d[1] - for g in gl: + special_gl_ids = [] + if len(d) > 2: + special_gl_ids = d[2] + colors = [] + for i, g in enumerate(gl): if g.geom_type == "LineString": ldata.append(list(g.coords)) if g.geom_type == "LinearRing": ldata.append(list(g.coords)) - self.create_line(tag, ldata, color, order) + if i in special_gl_ids: + colors.append(warning_color) + else: + colors.append(color) + self.create_line(tag, ldata, colors, order) + self.paths_geom[tag] = geom_list else: print("Cannot Visualize an Empty Path") @@ -306,6 +385,7 @@ def add_gcode(self, tag, gcode_list, color=('white', 'orange')): for color in gcode_paths.keys(): self.create_line(tag, gcode_paths[color], color, order) + self.paths_geom[tag] = gcode_list else: print("Cannot Visualize an Empty GCode") @@ -321,7 +401,46 @@ def add_triploy(self, tri, pts): self.canvas.freeze() visuals.XYZAxis(parent=self.canvas.view.scene) - def create_line(self, tag, ldata, color=None, order=0, width=0.1): + def create_line(self, tag, ldata, colors=None, order=0, width=0.1): + # modded to manage path of different colors + self.canvas.unfreeze() + if colors is not None: + if not isinstance(colors, list): + colors_list = [colors for i in range(len(ldata))] + else: + colors_list = colors + else: + colors_list = None + logger.error("Path Colors List not Set") + + p = -1 + for i, l in enumerate(ldata): + connect = [] + coords = [] + p += 1 + c = l[0] + coords.append(c) + for j in range(1, len(l)): + c = l[j] + coords.append(c) + connect.append((p, p+1)) + p += 1 + #print(coords) + coords = np.array(coords) + connect = np.array(connect) + + line = visuals.Line(pos=coords, connect=connect, width=width, color=colors_list[i], parent=self.canvas.view, antialias=True) + line.order = order + if tag in list(self.paths.keys()): + self.paths[tag] += [line] + else: + self.paths[tag] = [line] + self.canvas.view.add(line) + p = -1 + self.canvas.view.camera.set_range() + self.canvas.freeze() + + def create_line_old(self, tag, ldata, color=None, order=0, width=0.1): self.canvas.unfreeze() connect = [] coords = [] @@ -348,10 +467,10 @@ def create_line(self, tag, ldata, color=None, order=0, width=0.1): self.canvas.view.camera.set_range() self.canvas.freeze() - def create_mesh(self, tag, ldata, color=None, order=0): + def create_mesh(self, tag, ldata, color=None, order=0, auto_range=True): self.canvas.unfreeze() - mesh = visuals.Mesh(parent=self.canvas.view.scene) + mesh = visuals.Mesh(parent=self.canvas.view) # mesh = visuals.Mesh(shading='flat', parent=self.canvas.view.scene) # mesh.unfreeze() # mesh.filter = self.translucent_filter @@ -375,7 +494,8 @@ def create_mesh(self, tag, ldata, color=None, order=0): self.meshes[tag] = mesh self.canvas.view.add(mesh) - self.canvas.view.camera.set_range() + if auto_range: + self.canvas.view.camera.set_range() self.canvas.freeze() #visuals.XYZAxis(parent=self.canvas.view.scene) diff --git a/src/TheAntFarm/style_manager.py b/src/TheAntFarm/style_manager.py index f0bf1f6..d867300 100644 --- a/src/TheAntFarm/style_manager.py +++ b/src/TheAntFarm/style_manager.py @@ -10,7 +10,7 @@ def __init__(self, app_ptr): self.app_ptr = app_ptr self.native_styles = QStyleFactory.keys() self.default_palette = QPalette() - self.default_style = "Fusion" # None + self.default_style = "Fusion" self.dark_palette_action = None def list_styles(self): @@ -113,6 +113,18 @@ def set_radio_btn_style_sheet(): "height: 7px;}" return radio_btn_ss + @staticmethod + def set_button_color(bg_color="dark_gray", color="white"): + push_btn_ss = "QPushButton { background-color: " + bg_color + ";color: " + color + \ + "; border: : 3px solid; font-weight: bold;}" + return push_btn_ss + + @staticmethod + def set_tool_button_color(bg_color="dark_gray", color="white"): + tool_btn_ss = "QToolButton { background-color: " + bg_color + ";color: " + color + \ + "; border: : 3px solid; font-weight: bold;}" + return tool_btn_ss + if __name__ == "__main__": pass diff --git a/src/TheAntFarm/the_ant_farm.py b/src/TheAntFarm/the_ant_farm.py index 409362e..3f5c329 100644 --- a/src/TheAntFarm/the_ant_farm.py +++ b/src/TheAntFarm/the_ant_farm.py @@ -42,7 +42,7 @@ def config_os(): else: print("Linux Env") os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = os.path.join(pys2_path, "plugins", "platforms") - os.environ["QT_QPA_PLATFORM"] = "xcb" + os.environ["QT_QPA_PLATFORM"] = "wayland;xcb" class MainWindow(QMainWindow, Ui_MainWindow): @@ -90,6 +90,7 @@ def closeEvent(self, event): self.ui_manager.save_all_settings() print("Settings Saved") print("Stopping Threads") + self.ui.camera_list_cb.setCurrentIndex(0) # Select NO CAMERA before closing self.serialWo.close_port() self.serial_thread.quit() self.control_thread.quit() diff --git a/src/TheAntFarm/the_ant_farm.ui b/src/TheAntFarm/the_ant_farm.ui index b69cb15..09b71b9 100644 --- a/src/TheAntFarm/the_ant_farm.ui +++ b/src/TheAntFarm/the_ant_farm.ui @@ -27,7 +27,7 @@ - :/resources/resources/logo/the_ant_farm_logo.svg:/resources/resources/logo/the_ant_logo.png + :/resources/resources/logo/the_ant_farm_logo.svg:/resources/resources/logo/the_ant_farm_logo.svg @@ -52,7 +52,7 @@ QTabWidget::Rounded - 0 + 2 false @@ -90,7 +90,7 @@ QTabWidget::Rounded - 0 + 1 @@ -1314,7 +1314,7 @@ - Optimization + Algorithm @@ -1354,13 +1354,6 @@ - - - - - - - @@ -1469,6 +1462,25 @@ + + + + + Nearest Insertion (fast) + + + + + 2-opt (optimal) + + + + + Genetic + + + + @@ -1944,7 +1956,7 @@ - 0 + 1 @@ -2027,6 +2039,12 @@ + + 10 + + + 10 + @@ -2772,7 +2790,7 @@ - + 0 @@ -2910,12 +2928,12 @@ - + 0 - + 0 @@ -2949,7 +2967,7 @@ - + 0 @@ -2983,7 +3001,7 @@ - + 0 @@ -3017,7 +3035,7 @@ - + 0 @@ -3051,7 +3069,7 @@ - + 0 @@ -3215,7 +3233,7 @@ - + 0 @@ -3379,7 +3397,7 @@ - + 0 @@ -3490,9 +3508,9 @@ - + - + QLayout::SetDefaultConstraint @@ -3557,7 +3575,7 @@ - + 0 @@ -3571,7 +3589,7 @@ 0 - + 0 @@ -3600,7 +3618,7 @@ - + 0 @@ -3629,7 +3647,7 @@ - + 0 @@ -3658,7 +3676,7 @@ - + 0 @@ -3687,7 +3705,7 @@ - + 0 @@ -3745,7 +3763,7 @@ - + 0 @@ -3774,7 +3792,7 @@ - + 0 @@ -3803,7 +3821,7 @@ - + 0 @@ -3834,7 +3852,7 @@ - + @@ -4131,7 +4149,7 @@ - + @@ -4473,7 +4491,20 @@ - + + + + 0 + 0 + + + + true + + + true + + @@ -4664,11 +4695,80 @@ - - - 0 - - + + + + + 0 + + + + + + + + 0 + 0 + + + + + 30 + 30 + + + + Probe in idle + + + + + + + + + + + 0 + 0 + + + + + 30 + 30 + + + + ABL not applied + + + + + + + + + + + 30 + 30 + + + + ... + + + + :/resources/resources/icons/black_apply_align.svg + :/resources/resources/icons/black_alignment_applied.svg:/resources/resources/icons/black_apply_align.svg + + + true + + + + @@ -5538,187 +5638,2103 @@ - - - - - - - - - - - - - 255 - - - Qt::Vertical - - - - - - - - Settings/Preferences - - - - - - true - - - 0 - - - - Application Settings - - - - - - - - TOP LAYER COLOR - - - - - - - BOTTOM LAYER COLOR - - - - - - - - 150 - 0 - - - - QFrame::WinPanel - - - - - - - - - - DRILL LAYER COLOR - - - - - - - NC TOP LAYER COLOR - - - - - - - - 150 - 0 - - + + + + + + + - QFrame::WinPanel - - - - - - - - - - PROFILE LAYER COLOR + QFrame::StyledPanel - - - - - - NC BOTTOM LAYER COLOR + + QFrame::Raised + + + + + + 0 + 0 + + + + + 200 + 150 + + + + + 480 + 480 + + + + + + + + + + + + + TOOL POSITION + + + true + + + Qt::ToolButtonTextOnly + + + + + + + + + + Camera Selection + + + + + + + Zoom + + + + + + + ... + + + + + + + + + - - - - - 150 - 0 - - - - QFrame::WinPanel - - - + + + + Qt::Vertical - - - - - + - 150 - 0 + 20 + 20 - - QFrame::WinPanel - - - - - + - - - - - 150 - 0 - - + + - QFrame::WinPanel + QFrame::StyledPanel - - - - - - - - - - 150 - 0 - + + QFrame::Plain - - QFrame::WinPanel + + 1 - - + + 1 - - - - + + + + + QLayout::SetFixedSize + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 0 + 24 + + + + + 100 + 16777215 + + + + Z+ + + + + :/resources/resources/icons/white_north_arrow.svg:/resources/resources/icons/white_north_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 24 + + + + + 100 + 16777215 + + + + Z- + + + + :/resources/resources/icons/white_south_arrow.svg:/resources/resources/icons/white_south_arrow.svg + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + X- Y+ + + + + :/resources/resources/icons/white_north_west_arrow.svg:/resources/resources/icons/white_north_west_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + X+ Y- + + + + :/resources/resources/icons/white_south_east_arrow.svg:/resources/resources/icons/white_south_east_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + X- + + + + :/resources/resources/icons/white_west_arrow.svg:/resources/resources/icons/white_west_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + X- Y- + + + + :/resources/resources/icons/white_south_west_arrow.svg:/resources/resources/icons/white_south_west_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + Y+ + + + + :/resources/resources/icons/white_north_arrow.svg:/resources/resources/icons/white_north_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + Center + + + + :/resources/resources/icons/white_circle.svg:/resources/resources/icons/white_circle.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + Y- + + + + :/resources/resources/icons/white_south_arrow.svg:/resources/resources/icons/white_south_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + X+ Y+ + + + + :/resources/resources/icons/white_north_east_arrow.svg:/resources/resources/icons/white_north_east_arrow.svg + + + + + + + + 0 + 0 + + + + + 0 + 22 + + + + + 50 + 16777215 + + + + X+ + + + + :/resources/resources/icons/white_east_arrow.svg:/resources/resources/icons/white_east_arrow.svg + + + + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 23 + + + + + 75 + true + + + + Z step [mm] + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 75 + 20 + + + + + 75 + 16777215 + + + + + 75 + true + + + + 3 + + + + 100.0 + + + + + 10.0 + + + + + 5.0 + + + + + 1.0 + + + + + 0.5 + + + + + 0.1 + + + + + 0.05 + + + + + 0.01 + + + + + + + + + + + + + 70 + 20 + + + + + 70 + 16777215 + + + + + 75 + true + + + + Qt::AlignCenter + + + QAbstractSpinBox::NoButtons + + + 0.010000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + + 50 + 16777215 + + + + + 8 + 75 + true + + + + x10 + + + false + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + + 50 + 16777215 + + + + + 75 + true + + + + ÷10 + + + false + + + + + + + + 0 + 0 + + + + + 70 + 23 + + + + + 70 + 16777215 + + + + + 75 + true + + + + -1.0 + + + true + + + + + + + + 0 + 0 + + + + + 70 + 23 + + + + + 70 + 16777215 + + + + + 75 + true + + + + +1.0 + + + true + + + + + + + + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 23 + + + + XY step [mm] + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 75 + 0 + + + + + 75 + 23 + + + + 3 + + + + 100.0 + + + + + 10.0 + + + + + 5.0 + + + + + 1.0 + + + + + 0.5 + + + + + 0.1 + + + + + 0.05 + + + + + 0.01 + + + + + + + + + + + + + 0 + 0 + + + + + 70 + 20 + + + + + 70 + 23 + + + + + 75 + true + + + + +1.0 + + + true + + + + + + + + 0 + 0 + + + + + 50 + 23 + + + + + 50 + 23 + + + + + 75 + true + + + + ÷10 + + + false + + + + + + + + 0 + 0 + + + + + 70 + 23 + + + + + 70 + 23 + + + + + 75 + true + + + + Qt::AlignCenter + + + QAbstractSpinBox::NoButtons + + + 0.010000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 0 + + + + + 50 + 23 + + + + + 50 + 23 + + + + + 8 + 75 + true + + + + x10 + + + false + + + + + + + + 0 + 0 + + + + + 70 + 23 + + + + + 70 + 23 + + + + + 75 + true + + + + -1.0 + + + true + + + + + + + + + + + 1 + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 2 + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + + 75 + true + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + Z + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + 0.0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + + 75 + true + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + X + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + 0.0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + 0.0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + + 75 + true + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + WPos + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + 0.0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + + 75 + true + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + MPos + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + 0.0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + + 75 + true + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + Axis: + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + + 75 + true + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + Y + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 12 + + + + + 16777215 + 13 + + + + Qt::LeftToRight + + + QFrame::NoFrame + + + QFrame::Plain + + + 0.0 + + + Qt::AlignCenter + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 26 + + + + + + + + + + + + + + + + + + 0 + 20 + + + + + 16777215 + 20 + + + + FLIP HOR + + + true + + + Qt::ToolButtonTextOnly + + + + + + + + 0 + 20 + + + + + 16777215 + 20 + + + + FLIP VER + + + true + + + Qt::ToolButtonTextOnly + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 20 + + + + + 16777215 + 20 + + + + ... + + + + + + + + + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + + 500 + 16777215 + + + + QAbstractScrollArea::AdjustToContents + + + 4 + + + false + + + 100 + + + + + + + + + + + + + + 50 + 50 + + + + + 14 + 75 + true + + + + Reload gcode files generated. + + + + + + + + :/resources/resources/icons/gray-refresh.svg:/resources/resources/icons/gray-refresh.svg + + + Qt::ToolButtonTextOnly + + + + + + + + 0 + 0 + + + + + 50 + 50 + + + + + 14 + 75 + true + + + + Load gcode files. + + + - + + + Ctrl+G + + + Qt::ToolButtonTextOnly + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 50 + + + + Apply Alignment + + + Remove gcode files. + + + ... + + + + :/resources/resources/icons/black_apply_align.svg + :/resources/resources/icons/black_alignment_applied.svg:/resources/resources/icons/black_apply_align.svg + + + true + + + Qt::ToolButtonIconOnly + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 20 + + + + Error/STD_Deviation + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 20 + + + + No value available + + + Qt::AlignCenter + + + + + + + + + + + + + + + + Settings/Preferences + + + + + + true + + + 2 + + + + Application Settings + + + + + + + + TOP LAYER COLOR + + + + + + + BOTTOM LAYER COLOR + + + + + + + + 150 + 0 + + + + QFrame::WinPanel + + + + + + + + + + DRILL LAYER COLOR + + + + + + + NC TOP LAYER COLOR + + + + + + + + 150 + 0 + + + + QFrame::WinPanel + + + + + + + + + + PROFILE LAYER COLOR + + + + + + + NC BOTTOM LAYER COLOR + + + + + + + + 150 + 0 + + + + QFrame::WinPanel + + + + + + + + + + + 150 + 0 + + + + QFrame::WinPanel + + + + + + + + + + + 150 + 0 + + + + QFrame::WinPanel + + + + + + + + + + + 150 + 0 + + + + QFrame::WinPanel + + + + + + + + @@ -5726,21 +7742,335 @@ - - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 210 + 0 + + + + + 300 + 20 + + + + + 12 + 75 + true + + + + LAYER COLORS + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + + + + + Jobs/Machine Settings + + + + + + QLayout::SetFixedSize + + + + + + 0 + 0 + + + + + 150 + 20 + + + + + 150 + 20 + + + + + 75 + true + + + + + + + X (top-down mirror) + + + + + + + + 0 + 0 + + + + + 150 + 20 + + + + + 150 + 20 + + + + + 75 + true + + + + + + + Y (left-right mirror) + + + + + + + + 0 + 0 + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + + 75 + true + + + + + + + Mirroring axis + + + + + + + + 0 + 0 + + + + + 120 + 20 + + + + + + + + + + + + 0 + 0 + + + + + 120 + 20 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 130 + 20 + + + + + + + + + + + 0 + 0 + + + + + 12 + 75 + true + + + + PROBE SETTINGS + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 10 + + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + 12 + 75 + true + + + + TOOL CHANGE + + + + + Qt::Vertical 20 - 40 + 10 - - + + 0 @@ -5762,21 +8092,30 @@ 12 + 75 + true - LAYER COLORS + JOBS COMMON SETTINGS - - Qt::AlignCenter + + + + + + Qt::Horizontal - - + + Qt::Horizontal + + QSizePolicy::Expanding + 40 @@ -5785,153 +8124,281 @@ - - - - Qt::Horizontal - - - - - - - - Jobs/Machine Settings - - - - - + + + 2 - - QLayout::SetFixedSize - - - - - Qt::Horizontal + + + + + 252 + 0 + + + + + 252 + 16777215 + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + QAbstractSpinBox::UpDownArrows + + + 100000.000000000000000 + + + 1.000000000000000 + + + + + + + + 0 + 0 + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + + 75 + true + + + + + + + Z FEEDRATE - - + + 0 0 + + + 130 + 0 + + + + + 130 + 16777215 + + - 12 + 75 + true + + + - PROBE SETTINGS + XY FEEDRATE - - + + + + + 0 + 0 + + + + + 252 + 0 + + + + + 252 + 16777215 + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + QAbstractSpinBox::UpDownArrows + + + 100000.000000000000000 + + + 1.000000000000000 + + + + + + + + 252 + 0 + + + + + 252 + 16777215 + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + QAbstractSpinBox::UpDownArrows + + + 100000.000000000000000 + + + 1.000000000000000 + + + + + + + + 0 + 0 + + + + + 130 + 0 + + + + + 130 + 16777215 + + + + + 75 + true + + + + + + + PROBE FEEDRATE + + + + + Qt::Horizontal - + + QSizePolicy::Fixed + + + + 200 + 20 + + + - - - - 0 + + + + Qt::Horizontal - - 2 + + QSizePolicy::Fixed - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 180 - 20 - - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - - 150 - 16777215 - - - - Hold On Probe - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - - 150 - 16777215 - - - - Z=0 After Probe - - - - + + + 200 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 200 + 20 + + + - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - 2 @@ -5944,7 +8411,7 @@ - QLayout::SetFixedSize + QLayout::SetDefaultConstraint 2 @@ -6520,7 +8987,7 @@ - QLayout::SetFixedSize + QLayout::SetDefaultConstraint @@ -6667,243 +9134,114 @@ 0 0 - - - - 130 - 20 - - - - - 130 - 16777215 - - - - - 75 - true - - - - - - - Tool Change MPos - - - - - - - - 0 - 0 - - - - - 150 - 20 - - - - - 180 - 20 - - - - - 75 - true - - - - - - - Get Tool Change Position - - - - - - - - - - - - - Qt::Horizontal - - - - - - - QLayout::SetFixedSize - - - - - - 0 - 0 - - - - - 150 - 20 - - - - - 150 - 20 - - - - - 75 - true - - - - - - - X (top-down mirror) - - - - - - - - 0 - 0 - - - - - 150 - 20 - - - - - 150 - 20 - - - - - 75 - true - - - - - - - Y (left-right mirror) - - - - - - - - 0 - 0 - - - - - 130 - 0 - - - - - 130 - 16777215 - - - - - 75 - true - - - - - - - Mirroring axis - - - - - - - - 0 - 0 - - - - - 120 - 20 - - - - - - - - - - - - 0 - 0 - - - - - 120 - 20 - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 130 - 20 - - - + + + + 130 + 20 + + + + + 130 + 16777215 + + + + + 75 + true + + + + + + + Tool Change MPos + + + + + + + + 0 + 0 + + + + + 150 + 20 + + + + + 180 + 20 + + + + + 75 + true + + + + + + + Get Tool Change Position + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + @@ -6911,426 +9249,481 @@ - - - + + + 2 - - - - - 252 - 0 - - - - - 252 - 16777215 - - - - - 75 - true - - - - - - - Qt::AlignCenter - - - QAbstractSpinBox::UpDownArrows - - - 100000.000000000000000 - - - 1.000000000000000 - - - - - - - - 0 - 0 - - - - - 130 - 0 - - - - - 130 - 16777215 - - - - - 75 - true - - - - - - - Z FEEDRATE - - - - - - - - 0 - 0 - - - - - 130 - 0 - - - - - 130 - 16777215 - - - - - 75 - true - - - - - - - XY FEEDRATE - - - - - - - - 0 - 0 - - - - - 252 - 0 - - - - - 252 - 16777215 - - - - - 75 - true - - - - - - - Qt::AlignCenter - - - QAbstractSpinBox::UpDownArrows - - - 100000.000000000000000 + + QLayout::SetFixedSize + + + + + 0 - - 1.000000000000000 + + 2 - + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 180 + 20 + + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + + 150 + 16777215 + + + + Hold On Probe + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + + 150 + 16777215 + + + + Z=0 After Probe + + + + - - - - - 252 - 0 - - - - - 252 - 16777215 - - - - - 75 - true - - - - - - - Qt::AlignCenter - - - QAbstractSpinBox::UpDownArrows - - - 100000.000000000000000 - - - 1.000000000000000 + + + + + + + 12 + 75 + true + + + + FEEDRATES [mm/min] + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + Alignment Settings + + + + + + + + Qt::Horizontal - - - - - 0 - 0 - - - - - 130 - 0 - - - - - 130 - 16777215 - - + + + 12 75 true - - - - PROBE FEEDRATE + ALIGNMENT DRILL SETTINGS - - + + Qt::Horizontal - - QSizePolicy::Fixed + + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + + 130 + 16777215 + + + + + 75 + true + + + + + + + Alignment Drill diameter [mm] + + + + + + + + 0 + 0 + + + + + 252 + 0 + + + + + 252 + 16777215 + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + QAbstractSpinBox::UpDownArrows + + + 100000.000000000000000 + + + 1.000000000000000 + + + + + + + + + Qt::Vertical - 200 - 20 + 20 + 40 - - + + Qt::Horizontal - - QSizePolicy::Fixed + + + + + + + 12 + 75 + true + - - - 200 - 20 - + + CAMERA/TOOL OFFSET - + - - + + Qt::Horizontal - - QSizePolicy::Fixed + + + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 0 + + + + + 130 + 20 + + + + + 130 + 16777215 + + + + + 75 + true + + + + + + + Tool-Camera Offset + + + + + + + + 0 + 0 + + + + + 80 + 20 + + + + + 80 + 16777215 + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + QAbstractSpinBox::NoButtons + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + + 0 + 0 + + + + + 150 + 20 + + + + + 180 + 20 + + + + + 75 + true + + + + + + + Get Tool Camera Offset + + + + + + + + 0 + 0 + + + + + 80 + 20 + + + + + 80 + 16777215 + + + + + 75 + true + + + + + + + Qt::AlignCenter + + + QAbstractSpinBox::NoButtons + + + -1000.000000000000000 + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + + + Qt::Vertical - 200 - 20 + 20 + 40 - - - - Qt::Horizontal - - - - - - - - 12 - - - - FEEDRATES [mm/min] - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 210 - 0 - - - - - 300 - 20 - - - - - 12 - - - - JOBS COMMON SETTINGS - - - - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - - 20 - 10 - - - - - - - - - 0 - 0 - - - - - 12 - - - - TOOL CHANGE - - - - - - - Qt::Horizontal - - - - - + + Qt::Horizontal - - QSizePolicy::Expanding - - 40 + 623 20 - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -7555,7 +9948,7 @@ - + :/resources/resources/logo/the_ant_logo.png:/resources/resources/logo/the_ant_logo.png @@ -7588,6 +9981,21 @@ QOpenGLWidget
vispy_qt_widget
+ + ComboBoxFilterEnter + QComboBox +
combobox_filter_enter
+
+ + QLedLabel + QLabel +
qledlabel
+
+ + QCameraLabel + QLabel +
qcamera_label.h
+
main_tab_widget @@ -7671,7 +10079,6 @@ nc_bottom_z_feed_rate_dsb nc_bottom_generate_pb logging_plain_te - verticalSlider diff --git a/src/TheAntFarm/ui_manager/ui_about.py b/src/TheAntFarm/ui_manager/ui_about.py index 1a985e0..88c804b 100644 --- a/src/TheAntFarm/ui_manager/ui_about.py +++ b/src/TheAntFarm/ui_manager/ui_about.py @@ -10,7 +10,7 @@ def __init__(self, main_win, app_settings): self.app_settings = app_settings def show_about_info(self): - qp_map = QPixmap(u":/resources/resources/logo/the_ant_logo.png") + qp_map = QPixmap(u":/resources/resources/logo/the_ant_farm_logo.svg") about_dlg = QDialog(parent=self.main_win) about_dlg.setModal(True) about_dlg.setWindowTitle("About The Ant Farm") diff --git a/src/TheAntFarm/ui_manager/ui_align_tab.py b/src/TheAntFarm/ui_manager/ui_align_tab.py index 3530865..87dc453 100644 --- a/src/TheAntFarm/ui_manager/ui_align_tab.py +++ b/src/TheAntFarm/ui_manager/ui_align_tab.py @@ -1,37 +1,245 @@ -from PySide2.QtCore import Signal, Slot, QObject +from PySide2.QtCore import Signal, Slot, QObject, Qt from PySide2.QtGui import QPixmap +from PySide2.QtWidgets import QLabel, QFileDialog, QHeaderView +from collections import OrderedDict as Od +from style_manager import StyleManager +from qcamera_label import QCameraLabel import logging +import math +import os logger = logging.getLogger(__name__) class UiAlignTab(QObject): """Class dedicated to UI <--> Control interactions on Align Tab. """ + load_align_layer_s = Signal(str, str) align_active_s = Signal(bool) + align_apply_s = Signal(bool, list) update_threshold_s = Signal(int) + request_new_alignment_point_coords_s = Signal(list, bool) + remove_point_rows = Signal(list) + update_zoom_value_s = Signal(int) - def __init__(self, ui, control_worker): + MIN_ALIGNMENT_POINTS_NUMBER = 4 + + def __init__(self, main_win, control_worker, vis_align_layer, app_settings): super(UiAlignTab, self).__init__() - self.ui = ui + self.main_win = main_win + self.ui = self.main_win.ui self.controlWo = control_worker + self.vis_align_layer = vis_align_layer + self.app_settings = app_settings + + self.layer_colors = self.app_settings.layer_color + + align_extensions = "Excellon (*.xln *.XLN *.drl *.DRL)" + + align_points_tw_horizontal_headers = self.ui.align_points_tw.horizontalHeader() + align_points_tw_horizontal_headers.setSectionResizeMode(0, QHeaderView.Stretch) + align_points_tw_horizontal_headers.setSectionResizeMode(1, QHeaderView.Stretch) + align_points_tw_horizontal_headers.setSectionResizeMode(2, QHeaderView.Stretch) + align_points_tw_horizontal_headers.setSectionResizeMode(3, QHeaderView.Stretch) # Align TAB related controls. + self.load_align_layer_s.connect(self.controlWo.load_new_align_layer) + self.controlWo.update_align_layer_s.connect(self.visualize_new_align_layer) + self.controlWo.update_align_layer_view_s.connect(self.flip_align_layer) self.ui.main_tab_widget.currentChanged.connect(self.check_align_is_active) self.align_active_s.connect(self.controlWo.set_align_is_active) - self.ui.verticalSlider.valueChanged.connect(self.update_threshold) + self.align_apply_s.connect(self.controlWo.set_align_active) + # self.ui.apply_alignment_tb.clicked.connect(self.apply_align) + self.ui.apply_alignment_tb.clicked.connect( + lambda: self.set_alignment_tb_check(self.ui.apply_alignment_tb.isChecked())) + self.ui.apply_alignment_tb_2.clicked.connect( + lambda: self.set_alignment_tb_check(self.ui.apply_alignment_tb_2.isChecked())) + self.ui.add_point_tb.clicked.connect(self.request_new_point) + self.ui.remove_point_tb.clicked.connect(self.remove_point) self.update_threshold_s.connect(self.controlWo.update_threshold_value) + self.ui.load_align_layer_tb.clicked.connect( + lambda: self.load_align_file("Load Align File", align_extensions)) + + self.ui.flip_horizontally_tb.setChecked(self.app_settings.flip_horizontal_selected) + self.ui.flip_horizontally_tb.clicked.connect( + lambda: self.controlWo.flip_align_layer_horizontally(self.ui.flip_horizontally_tb.isChecked())) + self.ui.flip_vertically_tb.setChecked(self.app_settings.flip_vertical_selected) + self.ui.flip_vertically_tb.clicked.connect( + lambda: self.controlWo.flip_align_layer_vertically(self.ui.flip_vertically_tb.isChecked())) + self.request_new_alignment_point_coords_s.connect(self.controlWo.add_new_align_point) + self.remove_point_rows.connect(self.controlWo.remove_align_points) + + self.ui.tool_or_camera_tb.setChecked(self.app_settings.camera_selected_or_tool) + self.update_tool_or_camera() + self.ui.tool_or_camera_tb.clicked.connect(self.update_tool_or_camera) self.controlWo.update_camera_image_s.connect(self.update_camera_image) + self.controlWo.update_camera_list_s.connect(self.update_camera_list) + self.ui.camera_list_cb.currentIndexChanged.connect(lambda: self.controlWo.update_camera_selected( + self.ui.camera_list_cb.currentIndex())) + self.controlWo.refresh_camera_list() + + self.controlWo.update_align_points_s.connect(self.update_alignment_points_list) + self.camera_zoom_cb_init() + self.ui.camera_zoom_cb.currentIndexChanged.connect(lambda: self.update_zoom_value( + int(self.ui.camera_zoom_cb.currentText()[:-1]))) + + self.ui.camera_la.mouse_wheel_up_or_down_s.connect(self.update_camera_zoom) + self.update_zoom_value_s.connect(self.controlWo.update_camera_zoom_value) + + def camera_zoom_cb_init(self): + self.ui.camera_zoom_cb.clear() + self.ui.camera_zoom_cb.addItems(["1x", "2x", "3x", "4x", "5x"]) + self.ui.camera_zoom_cb.setCurrentIndex(0) + + @Slot(int) + def update_camera_zoom(self, increment): + zoom_cb_index = self.ui.camera_zoom_cb.currentIndex() + zoom_cb_max = self.ui.camera_zoom_cb.count() + new_cb_index = zoom_cb_index + increment + if 0 <= new_cb_index < zoom_cb_max: + self.ui.camera_zoom_cb.setCurrentIndex(new_cb_index) + current_zoom = int(self.ui.camera_zoom_cb.currentText()[:-1]) + self.update_zoom_value(current_zoom) + + def update_zoom_value(self, current_zoom_value): + self.update_zoom_value_s.emit(current_zoom_value) + + def remove_point(self): + sel_model = self.ui.align_points_tw.selectionModel() + sel_rows = sel_model.selectedRows() + row_indexes = [x.row() for x in sel_rows] + self.remove_point_rows.emit(row_indexes) @Slot(QPixmap) def update_camera_image(self, pixmap): - self.ui.label_2.setPixmap(pixmap) + if not pixmap.isNull(): + scaled_frame = pixmap.scaled(self.ui.camera_la.width(), 1000, Qt.KeepAspectRatio, Qt.SmoothTransformation) + self.ui.camera_la.setPixmap(scaled_frame) + # self.ui.camera_la.setPixmap(pixmap) + + def update_tool_or_camera(self): + if self.ui.tool_or_camera_tb.isChecked(): + self.ui.tool_or_camera_tb.setText("CAMERA_POSITION") + self.app_settings.camera_selected_or_tool = True + else: + self.ui.tool_or_camera_tb.setText("TOOL_POSITION") + self.app_settings.camera_selected_or_tool = False def check_align_is_active(self): self.align_active_s.emit(self.ui.main_tab_widget.currentWidget().objectName() == "align_tab") - def update_threshold(self): - self.update_threshold_s.emit(self.ui.verticalSlider.value()) + @Slot(list) + def update_camera_list(self, camera_list): + self.ui.camera_list_cb.addItem("No CAMERA") + for cam in camera_list: + self.ui.camera_list_cb.addItem(str(cam)) + + def update_ui_alignment_applied(self, alignment_applied_flag, num_points): + if alignment_applied_flag: + self.ui.apply_alignment_tb.setStyleSheet(StyleManager.set_tool_button_color(bg_color="blue", + color="black")) + self.ui.apply_alignment_tb_2.setStyleSheet(StyleManager.set_tool_button_color(bg_color="blue", + color="black")) + elif num_points >= self.MIN_ALIGNMENT_POINTS_NUMBER: + self.ui.apply_alignment_tb.setStyleSheet(StyleManager.set_tool_button_color(bg_color="yellow", + color="black")) + self.ui.apply_alignment_tb_2.setStyleSheet(StyleManager.set_tool_button_color(bg_color="yellow", + color="black")) + else: + self.ui.apply_alignment_tb.setStyleSheet(StyleManager.set_tool_button_color(bg_color="QColor(53, 53, 53)", + color="white")) + self.ui.apply_alignment_tb_2.setStyleSheet(StyleManager.set_tool_button_color(bg_color="QColor(53, 53, 53)", + color="white")) + + def set_alignment_tb_check(self, alignment_check_status): + self.ui.apply_alignment_tb.clicked.disconnect() + self.ui.apply_alignment_tb_2.clicked.disconnect() + + self.ui.apply_alignment_tb.setChecked(alignment_check_status) # sync check status of the aliment tb + self.ui.apply_alignment_tb_2.setChecked(alignment_check_status) # sync check status of the aliment tb + + self.ui.apply_alignment_tb.clicked.connect( + lambda: self.set_alignment_tb_check(self.ui.apply_alignment_tb.isChecked())) + self.ui.apply_alignment_tb_2.clicked.connect( + lambda: self.set_alignment_tb_check(self.ui.apply_alignment_tb_2.isChecked())) + + self.apply_align() + + def apply_align(self): + alignment_points = list() + num_rows = self.ui.align_points_tw.rowCount() + alignment_tb_check_status = self.ui.apply_alignment_tb.isChecked() + align_to_be_applied_flag = alignment_tb_check_status and (num_rows >= self.MIN_ALIGNMENT_POINTS_NUMBER) + # Grab alignment points only if apply alignment button is checked + if align_to_be_applied_flag: + self.update_ui_alignment_applied(True, num_rows) + for r in range(0, num_rows): + x_base = float(self.ui.align_points_tw.cellWidget(r, 0).text()) + y_base = float(self.ui.align_points_tw.cellWidget(r, 1).text()) + x_offs = float(self.ui.align_points_tw.cellWidget(r, 2).text()) + y_offs = float(self.ui.align_points_tw.cellWidget(r, 3).text()) + points_l = [(x_base, y_base), (x_offs, y_offs)] + alignment_points.append(points_l) + else: + self.update_ui_alignment_applied(False, num_rows) + self.align_apply_s.emit(align_to_be_applied_flag, alignment_points) + + @staticmethod + def compute_offset_point(x_in, y_in, offset_in, angle_in): + x_out = offset_in + (x_in * math.cos(math.radians(angle_in)) - + (y_in * math.sin(math.radians(angle_in)))) + y_out = offset_in + ((x_in * math.sin(math.radians(angle_in))) + + (y_in * math.cos(math.radians(angle_in)))) + return x_out, y_out + + def request_new_point(self): + selection_centroid = self.vis_align_layer.get_selected_centroid() + + self.request_new_alignment_point_coords_s.emit(selection_centroid, self.app_settings.camera_selected_or_tool) + + @Slot(list) + def update_alignment_points_list(self, alignment_coords_l): + + self.ui.align_points_tw.setRowCount(0) # Remove all elements + num_rows = 0 + + for r in alignment_coords_l: + self.ui.align_points_tw.insertRow(num_rows) + self.ui.align_points_tw.setCellWidget(num_rows, 0, QLabel("{:.3f}".format(r[0][0]))) + self.ui.align_points_tw.setCellWidget(num_rows, 1, QLabel("{:.3f}".format(r[0][1]))) + self.ui.align_points_tw.setCellWidget(num_rows, 2, QLabel("{:.3f}".format(r[1][0]))) + self.ui.align_points_tw.setCellWidget(num_rows, 3, QLabel("{:.3f}".format(r[1][1]))) + num_rows += 1 + + self.apply_align() + + def load_align_file(self, load_text="Load Align File", extensions=""): + layer = "drill" + filters = extensions + ";;All files (*.*)" + kwargs = {} + if "PYCHARM_HOSTED" in os.environ: + logger.debug("pycharm hosted") + kwargs['options'] = QFileDialog.DontUseNativeDialog + load_file_path = QFileDialog.getOpenFileName(self.main_win, load_text, self.app_settings.layer_last_dir, + filters, **kwargs) + + if load_file_path[0]: + self.vis_align_layer.remove_layer(layer) + self.vis_align_layer.remove_path(layer) + self.app_settings.layer_last_dir = os.path.dirname(load_file_path[0]) + logger.info("Loading Align " + load_file_path[0]) + self.load_align_layer_s.emit(layer, load_file_path[0]) + + @Slot(Od, str, str, bool) + def visualize_new_align_layer(self, loaded_layer, layer_tag, layer_path, holes): + if loaded_layer is None or layer_path == "": + self.ui.status_bar.showMessage("WARNING: user tried to load an empty layer.", 3000) + else: + self.vis_align_layer.add_layer(layer_tag, loaded_layer[0], self.layer_colors[layer_tag], holes) + + @Slot(list) + def flip_align_layer(self, flip_info): + self.vis_align_layer.flip_camera(flip_info) if __name__ == "__main__": diff --git a/src/TheAntFarm/ui_manager/ui_control_tab.py b/src/TheAntFarm/ui_manager/ui_control_tab.py index 0c512c1..f65b9c1 100644 --- a/src/TheAntFarm/ui_manager/ui_control_tab.py +++ b/src/TheAntFarm/ui_manager/ui_control_tab.py @@ -61,6 +61,7 @@ def __init__(self, ui, control_worker, serial_worker, ctrl_layer, settings): self.ui_serial_close_s.connect(self.serialWo.close_port) self.controlWo.reset_controller_status_s.connect(self.controlWo.reset_dro_status_updated) self.controlWo.update_status_s.connect(self.update_status) + self.controlWo.touched_probe_s.connect(self.touched_probe) self.controlWo.update_probe_s.connect(self.update_probe) self.controlWo.send_abl_s.connect(self.controlWo.cmd_auto_bed_levelling) self.controlWo.update_bbox_s.connect(self.update_bbox) @@ -87,8 +88,9 @@ def __init__(self, ui, control_worker, serial_worker, ctrl_layer, settings): self.ui.open_gcode_tb.clicked.connect(self.open_gcode_files) - self.ui.send_te.setPlaceholderText('input here') - self.ui.send_te.hide() + combobox_ss = "QComboBox::drop-down {border-width: 0px;} QComboBox::down-arrow {image: url(noimg); border-width: 0px;}" + self.ui.send_cb.setStyleSheet(combobox_ss) + self.ui.send_cb.hide() self.ui.send_pb.hide() # Set x and y bbox step initial values. @@ -99,7 +101,7 @@ def __init__(self, ui, control_worker, serial_worker, ctrl_layer, settings): self.ui.connect_pb.clicked.connect(self.handle_connect_button) self.ui.clear_terminal_pb.clicked.connect(self.handle_clear_terminal) self.ui.send_pb.clicked.connect(self.send_input) - self.ui.send_te.returnPressed.connect(self.send_input) + self.ui.send_cb.key_event_cb.connect(self.send_input) self.ui.soft_reset_tb.clicked.connect(self.handle_soft_reset) self.ui.unlock_tb.clicked.connect(self.handle_unlock) self.ui.homing_tb.clicked.connect(self.handle_homing) @@ -109,25 +111,46 @@ def __init__(self, ui, control_worker, serial_worker, ctrl_layer, settings): self.ui.zero_y_pb.clicked.connect(self.handle_y_0) self.ui.zero_z_pb.clicked.connect(self.handle_z_0) self.ui.center_tb.clicked.connect(self.handle_center_jog) - self.ui.xMinusButton.clicked.connect(self.handle_x_minus) - self.ui.xPlusButton.clicked.connect(self.handle_x_plus) - self.ui.yMinusButton.clicked.connect(self.handle_y_minus) - self.ui.yPlusButton.clicked.connect(self.handle_y_plus) - self.ui.xYPlusButton.clicked.connect(self.handle_xy_plus) - self.ui.xYPlusMinuButton.clicked.connect(self.handle_x_plus_y_minus) - self.ui.xYMinusButton.clicked.connect(self.handle_xy_minus) - self.ui.xYMinusPlusButton.clicked.connect(self.handle_x_minus_y_plus) + self.ui.x_minus_pb.clicked.connect(self.handle_x_minus) + self.ui.x_plus_pb.clicked.connect(self.handle_x_plus) + self.ui.y_minus_pb.clicked.connect(self.handle_y_minus) + self.ui.y_plus_pb.clicked.connect(self.handle_y_plus) + self.ui.x_plus_y_plus_pb.clicked.connect(self.handle_xy_plus) + self.ui.x_plus_y_minus_pb.clicked.connect(self.handle_x_plus_y_minus) + self.ui.x_minus_y_minus_pb.clicked.connect(self.handle_xy_minus) + self.ui.x_minus_y_plus_pb.clicked.connect(self.handle_x_minus_y_plus) self.ui.z_minus_pb.clicked.connect(self.handle_z_minus) self.ui.z_plus_pb.clicked.connect(self.handle_z_plus) - self.ui.xy_plus_1_pb.clicked.connect(self.handle_xy_plus_1) - self.ui.xy_minus_1_pb.clicked.connect(self.handle_xy_minus_1) - self.ui.xy_div_10_pb.clicked.connect(self.handle_xy_div_10) - self.ui.xy_mul_10_pb.clicked.connect(self.handle_xy_mul_10) - self.ui.z_plus_1_pb.clicked.connect(self.handle_z_plus_1) - self.ui.z_minus_1_pb.clicked.connect(self.handle_z_minus_1) - self.ui.z_div_10_pb.clicked.connect(self.handle_z_div_10) - self.ui.z_mul_10_pb.clicked.connect(self.handle_z_mul_10) + self.ui.center_tb_2.clicked.connect(self.handle_center_jog) + self.ui.x_minus_pb_2.clicked.connect(self.handle_x_minus) + self.ui.x_plus_pb_2.clicked.connect(self.handle_x_plus) + self.ui.y_minus_pb_2.clicked.connect(self.handle_y_minus) + self.ui.y_plus_pb_2.clicked.connect(self.handle_y_plus) + self.ui.x_plus_y_plus_pb_2.clicked.connect(self.handle_xy_plus) + self.ui.x_plus_y_minus_pb_2.clicked.connect(self.handle_x_plus_y_minus) + self.ui.x_minus_y_minus_pb_2.clicked.connect(self.handle_xy_minus) + self.ui.x_minus_y_plus_pb_2.clicked.connect(self.handle_x_minus_y_plus) + self.ui.z_minus_pb_2.clicked.connect(self.handle_z_minus) + self.ui.z_plus_pb_2.clicked.connect(self.handle_z_plus) + + self.ui.xy_plus_1_pb.clicked.connect(lambda: self.handle_xy_plus_1(self.ui.xy_step_val_dsb)) + self.ui.xy_minus_1_pb.clicked.connect(lambda: self.handle_xy_minus_1(self.ui.xy_step_val_dsb)) + self.ui.xy_div_10_pb.clicked.connect(lambda: self.handle_xy_div_10(self.ui.xy_step_val_dsb)) + self.ui.xy_mul_10_pb.clicked.connect(lambda: self.handle_xy_mul_10(self.ui.xy_step_val_dsb)) + self.ui.z_plus_1_pb.clicked.connect(lambda: self.handle_z_plus_1(self.ui.z_step_val_dsb)) + self.ui.z_minus_1_pb.clicked.connect(lambda: self.handle_z_minus_1(self.ui.z_step_val_dsb)) + self.ui.z_div_10_pb.clicked.connect(lambda: self.handle_z_div_10(self.ui.z_step_val_dsb)) + self.ui.z_mul_10_pb.clicked.connect(lambda: self.handle_z_mul_10(self.ui.z_step_val_dsb)) + + self.ui.xy_plus_1_pb_2.clicked.connect(lambda: self.handle_xy_plus_1(self.ui.xy_step_val_dsb_2)) + self.ui.xy_minus_1_pb_2.clicked.connect(lambda: self.handle_xy_minus_1(self.ui.xy_step_val_dsb_2)) + self.ui.xy_div_10_pb_2.clicked.connect(lambda: self.handle_xy_div_10(self.ui.xy_step_val_dsb_2)) + self.ui.xy_mul_10_pb_2.clicked.connect(lambda: self.handle_xy_mul_10(self.ui.xy_step_val_dsb_2)) + self.ui.z_plus_1_pb_2.clicked.connect(lambda: self.handle_z_plus_1(self.ui.z_step_val_dsb_2)) + self.ui.z_minus_1_pb_2.clicked.connect(lambda: self.handle_z_minus_1(self.ui.z_step_val_dsb_2)) + self.ui.z_div_10_pb_2.clicked.connect(lambda: self.handle_z_div_10(self.ui.z_step_val_dsb_2)) + self.ui.z_mul_10_pb_2.clicked.connect(lambda: self.handle_z_mul_10(self.ui.z_step_val_dsb_2)) self.ui.probe_pb.clicked.connect(self.handle_probe_cmd) self.ui.ABL_pb.clicked.connect(self.handle_auto_bed_levelling) @@ -141,6 +164,7 @@ def __init__(self, ui, control_worker, serial_worker, ctrl_layer, settings): self.ui.y_max_dsb.valueChanged.connect(self.update_bbox_y_steps) self.ui.y_num_step_sb.valueChanged.connect(self.update_bbox_y_num_steps) + self.enable_control_jog_elements(False) self.ui.soft_reset_tb.setEnabled(False) self.ui.unlock_tb.setEnabled(False) self.ui.homing_tb.setEnabled(False) @@ -193,7 +217,32 @@ def __init__(self, ui, control_worker, serial_worker, ctrl_layer, settings): self.ui.z_min_dsb.valueChanged.connect(self.handle_z_min_changed) self.ui.z_max_dsb.valueChanged.connect(self.handle_z_max_changed) - def deselect_all_gcode_row(self, index): + def enable_control_jog_elements(self, enable_flag=True): + """ + Enable or disable ui elements of the control jog and related. + + Parameters + ---------- + enable_flag enable ui elements if true + """ + self.ui.x_minus_y_plus_pb.setEnabled(enable_flag) + self.ui.x_plus_y_minus_pb.setEnabled(enable_flag) + self.ui.x_minus_y_minus_pb.setEnabled(enable_flag) + self.ui.x_plus_y_plus_pb.setEnabled(enable_flag) + self.ui.x_minus_pb.setEnabled(enable_flag) + self.ui.x_plus_pb.setEnabled(enable_flag) + self.ui.y_minus_pb.setEnabled(enable_flag) + self.ui.y_plus_pb.setEnabled(enable_flag) + self.ui.center_tb.setEnabled(enable_flag) + self.ui.z_plus_pb.setEnabled(enable_flag) + self.ui.z_minus_pb.setEnabled(enable_flag) + self.ui.probe_pb.setEnabled(enable_flag) + self.ui.zero_x_pb.setEnabled(enable_flag) + self.ui.zero_y_pb.setEnabled(enable_flag) + self.ui.zero_z_pb.setEnabled(enable_flag) + self.ui.zero_xy_pb.setEnabled(enable_flag) + + def deselect_all_gcode_row(self): self.ui.gcode_tw.setSelectionMode(QAbstractItemView.MultiSelection) self.ui.gcode_tw.setSelectionBehavior(QAbstractItemView.SelectRows) self.ui.gcode_tw.clearSelection() @@ -215,18 +264,29 @@ def select_gcode_row(self, index): def init_xy_jog_step_value(self): """ Initialize XY step and value ui fields. """ self.ui.xy_step_cb.setCurrentIndex(self.machine_settings.xy_step_idx) + self.ui.xy_step_cb_2.setCurrentIndex(self.machine_settings.xy_step_idx) self.xy_update_step() + self.xy_update_step_2() self.ui.xy_step_val_dsb.setValue(self.machine_settings.xy_step_value) self.ui.xy_step_cb.currentTextChanged.connect(self.xy_update_step) - self.ui.xy_step_val_dsb.valueChanged.connect(self.xy_update_value) + self.ui.xy_step_val_dsb.valueChanged.connect(lambda: self.xy_update_value(self.ui.xy_step_val_dsb)) + + self.ui.xy_step_val_dsb_2.setValue(self.machine_settings.xy_step_value) + self.ui.xy_step_cb_2.currentTextChanged.connect(self.xy_update_step_2) + self.ui.xy_step_val_dsb_2.valueChanged.connect(lambda: self.xy_update_value(self.ui.xy_step_val_dsb_2)) def init_z_jog_step_value(self): """ Initialize Z step and value ui fields. """ self.ui.z_step_cb.setCurrentIndex(self.machine_settings.z_step_idx) + self.ui.z_step_cb_2.setCurrentIndex(self.machine_settings.z_step_idx) self.z_update_step() + self.z_update_step_2() self.ui.z_step_val_dsb.setValue(self.machine_settings.z_step_value) + self.ui.z_step_val_dsb_2.setValue(self.machine_settings.z_step_value) self.ui.z_step_cb.currentTextChanged.connect(self.z_update_step) - self.ui.z_step_val_dsb.valueChanged.connect(self.z_update_value) + self.ui.z_step_cb_2.currentTextChanged.connect(self.z_update_step_2) + self.ui.z_step_val_dsb.valueChanged.connect(lambda: self.z_update_value(self.ui.z_step_val_dsb)) + self.ui.z_step_val_dsb_2.valueChanged.connect(lambda: self.z_update_value(self.ui.z_step_val_dsb_2)) def init_serial_port_cb(self): """ Initialize the serial ports' ui elements. """ @@ -236,7 +296,7 @@ def init_serial_port_cb(self): def update_status(self, status_od): status_text = status_od["state"] if "pins" in status_od.keys(): - status_text += " " + status_od["pins"] + status_text += "\n" + status_od["pins"] self.ui.status_l.setText(status_text) self.update_status_colors(status_od["state"]) self.update_status_buttons(status_od["state"]) @@ -246,6 +306,14 @@ def update_status(self, status_od): self.ui.wpos_x_l.setText('{:.3f}'.format(status_od["wpos"][0])) self.ui.wpos_y_l.setText('{:.3f}'.format(status_od["wpos"][1])) self.ui.wpos_z_l.setText('{:.3f}'.format(status_od["wpos"][2])) + + self.ui.mpos_x_l_2.setText('{:.3f}'.format(status_od["mpos"][0])) + self.ui.mpos_y_l_2.setText('{:.3f}'.format(status_od["mpos"][1])) + self.ui.mpos_z_l_2.setText('{:.3f}'.format(status_od["mpos"][2])) + self.ui.wpos_x_l_2.setText('{:.3f}'.format(status_od["wpos"][0])) + self.ui.wpos_y_l_2.setText('{:.3f}'.format(status_od["wpos"][1])) + self.ui.wpos_z_l_2.setText('{:.3f}'.format(status_od["wpos"][2])) + self.ctrl_layer.update_pointer(coords=status_od["wpos"]) def update_status_buttons(self, status): @@ -522,9 +590,13 @@ def is_gcode_rb_selected(self): return True return False + @Slot() + def touched_probe(self): + self.ui.probe_led_la.set_led_color("green") + @Slot(list) def update_probe(self, probe_l): - pass + self.ui.probe_led_la.set_led_color("grey") @Slot(str) def update_console_text(self, new_text): @@ -533,9 +605,18 @@ def update_console_text(self, new_text): def send_input(self): """Send input to the serial port.""" - # self.serialTxQu.put(self.ui.send_te.text() + "\n") - self.ui_serial_send_s.emit(self.ui.send_te.text() + "\n") - self.ui.send_te.clear() + ct_cb = self.ui.send_cb.currentText() + + if not ct_cb == "": + if self.ui.send_cb.count() == 0: + self.ui.send_cb.addItem(ct_cb) + else: + self.ui.send_cb.setItemText(self.ui.send_cb.count()-1, ct_cb) + + self.ui.send_cb.addItem("") + self.ui.send_cb.setCurrentIndex(self.ui.send_cb.count()-1) + + self.ui_serial_send_s.emit(ct_cb + "\n") @Slot(list, list) def get_ports_and_bauds(self, port_names, baudrates): @@ -596,7 +677,7 @@ def act_on_connection(self, connection_status): self.ui.serial_ports_cb.hide() self.ui.serial_baud_cb.hide() self.ui.refresh_pb.hide() - self.ui.send_te.show() + self.ui.send_cb.show() self.ui.send_pb.show() self.ui.soft_reset_tb.setEnabled(True) self.ui.unlock_tb.setEnabled(True) @@ -604,10 +685,11 @@ def act_on_connection(self, connection_status): self.ui.tool_change_tb.setEnabled(True) if self.is_gcode_rb_selected(): self.ui.play_tb.setEnabled(True) + self.enable_control_jog_elements(True) self.controller_connected_s.emit(True) self.ctrl_layer.create_pointer(coords=(0, 0, 0)) - self.ui.get_tool_probe_pb.setEnabled(True) + self.ui.probe_led_la.set_led_color("grey") self.ui.get_tool_change_pb.setEnabled(True) def act_on_disconnection(self): @@ -617,7 +699,7 @@ def act_on_disconnection(self): self.ui.serial_ports_cb.show() self.ui.serial_baud_cb.show() self.ui.refresh_pb.show() - self.ui.send_te.hide() + self.ui.send_cb.hide() self.ui.send_pb.hide() self.ui.status_l.setText("Not Connected") self.update_status_colors("Not Connected") @@ -628,10 +710,11 @@ def act_on_disconnection(self): self.ui.stop_tb.setEnabled(False) self.ui.pause_resume_tb.setEnabled(False) self.ui.tool_change_tb.setEnabled(False) + self.enable_control_jog_elements(False) self.controller_connected_s.emit(False) self.ctrl_layer.remove_pointer() - self.ui.get_tool_probe_pb.setEnabled(False) + self.ui.probe_led_la.set_led_color("grey") self.ui.get_tool_change_pb.setEnabled(False) def handle_clear_terminal(self): @@ -681,17 +764,33 @@ def handle_center_jog(self): self.ui_send_cmd_s.emit("goto", (0.0, 0.0, None)) def z_update_step(self): - self.machine_settings.z_step_idx = self.ui.z_step_cb.currentIndex() + current_index = self.ui.z_step_cb.currentIndex() + self.machine_settings.z_step_idx = current_index new_step_str = self.ui.z_step_cb.currentText() new_step_fl = float(new_step_str) # try-except for the cast? No, because cb is not editable, up to now. self.ui.z_step_val_dsb.setSingleStep(new_step_fl) self.ui.z_plus_1_pb.setText("+" + new_step_str) self.ui.z_minus_1_pb.setText("-" + new_step_str) - @Slot() - def z_update_value(self): + self.ui.z_step_cb_2.setCurrentIndex(current_index) # This shall trigger the update of the other dro control + + def z_update_step_2(self): + current_index = self.ui.z_step_cb_2.currentIndex() + self.machine_settings.z_step_idx = current_index + new_step_str = self.ui.z_step_cb_2.currentText() + new_step_fl = float(new_step_str) # try-except for the cast? No, because cb is not editable, up to now. + + self.ui.z_step_val_dsb_2.setSingleStep(new_step_fl) + self.ui.z_plus_1_pb_2.setText("+" + new_step_str) + self.ui.z_minus_1_pb_2.setText("-" + new_step_str) + + self.ui.z_step_cb.setCurrentIndex(current_index) # This shall trigger the update of the other dro control + + @Slot(float) + def z_update_value(self, dsb): """ Update current value of Z STEP in the machine settings. """ - self.machine_settings.z_step_value = self.ui.z_step_val_dsb.value() + self.machine_settings.z_step_value = dsb.value() + self.update_all_z_dsb_value(dsb.value()) def handle_x_minus(self): logger.debug("X_minus Command") @@ -744,49 +843,98 @@ def handle_z_plus(self): self.ui_send_cmd_s.emit("jog", (None, None, z_plus_val)) def xy_update_step(self): - self.machine_settings.xy_step_idx = self.ui.xy_step_cb.currentIndex() + current_index = self.ui.xy_step_cb.currentIndex() + self.machine_settings.xy_step_idx = current_index new_step_str = self.ui.xy_step_cb.currentText() new_step_fl = float(new_step_str) # try-except for the cast? No, because cb is not editable, up to now. self.ui.xy_step_val_dsb.setSingleStep(new_step_fl) self.ui.xy_plus_1_pb.setText("+" + new_step_str) self.ui.xy_minus_1_pb.setText("-" + new_step_str) - @Slot() - def xy_update_value(self): + self.ui.xy_step_cb_2.setCurrentIndex(current_index) # This shall trigger the update of the other dro control + + def xy_update_step_2(self): + current_index = self.ui.xy_step_cb_2.currentIndex() + self.machine_settings.xy_step_idx = current_index + new_step_str = self.ui.xy_step_cb_2.currentText() + new_step_fl = float(new_step_str) # try-except for the cast? No, because cb is not editable, up to now. + + self.ui.xy_step_val_dsb_2.setSingleStep(new_step_fl) + self.ui.xy_plus_1_pb_2.setText("+" + new_step_str) + self.ui.xy_minus_1_pb_2.setText("-" + new_step_str) + + self.ui.xy_step_cb.setCurrentIndex(current_index) # This shall trigger the update of the other dro control + + def xy_update_value(self, dsb): """ Update current value of XY STEP in the machine settings. """ - self.machine_settings.xy_step_value = self.ui.xy_step_val_dsb.value() + self.machine_settings.xy_step_value = dsb.value() + self.update_all_xy_dsb_value(dsb.value()) - def handle_xy_plus_1(self): - xy_val = self.ui.xy_step_val_dsb.value() + self.ui.xy_step_val_dsb.singleStep() - self.ui.xy_step_val_dsb.setValue(xy_val) + def update_all_xy_dsb_value(self, new_xy_value): + self.ui.xy_step_val_dsb.setValue(new_xy_value) + self.ui.xy_step_val_dsb_2.setValue(new_xy_value) - def handle_xy_minus_1(self): - xy_val = self.ui.xy_step_val_dsb.value() - self.ui.xy_step_val_dsb.singleStep() - self.ui.xy_step_val_dsb.setValue(xy_val) + def handle_xy_plus_1(self, dsb): + new_xy_value = round(dsb.value() + dsb.singleStep(), 2) + if new_xy_value <= dsb.maximum(): + self.update_all_xy_dsb_value(new_xy_value) + else: + logger.warning(f"Cannot set value higher than maximum: {dsb.maximum()}") - def handle_xy_div_10(self): - xy_value = self.ui.xy_step_val_dsb.value() - self.ui.xy_step_val_dsb.setValue(round(xy_value/10.0, 2)) + def handle_xy_minus_1(self, dsb): + new_xy_value = round(dsb.value() - dsb.singleStep(), 2) + if new_xy_value >= dsb.minimum(): + self.update_all_xy_dsb_value(new_xy_value) + else: + logger.warning(f"Cannot set value less than minimum: {dsb.minimum()}") - def handle_xy_mul_10(self): - xy_value = self.ui.xy_step_val_dsb.value() - self.ui.xy_step_val_dsb.setValue(xy_value*10.0) + def handle_xy_div_10(self, dsb): + xy_value = dsb.value() + new_xy_value = round(xy_value / 10.0, 2) + if new_xy_value >= dsb.minimum(): + self.update_all_xy_dsb_value(new_xy_value) + else: + logger.warning(f"Cannot set value less than minimum: {dsb.minimum()}") - def handle_z_plus_1(self): - z_val = self.ui.z_step_val_dsb.value() + self.ui.z_step_val_dsb.singleStep() - self.ui.z_step_val_dsb.setValue(z_val) + def handle_xy_mul_10(self, dsb): + xy_value = dsb.value() + new_xy_value = round(xy_value * 10.0, 2) + if new_xy_value <= dsb.maximum(): + self.update_all_xy_dsb_value(new_xy_value) + else: + logger.warning(f"Cannot set value higher than maximum: {dsb.maximum()}") - def handle_z_minus_1(self): - z_val = self.ui.z_step_val_dsb.value() - self.ui.z_step_val_dsb.singleStep() - self.ui.z_step_val_dsb.setValue(z_val) + def update_all_z_dsb_value(self, new_z_value): + self.ui.z_step_val_dsb.setValue(new_z_value) + self.ui.z_step_val_dsb_2.setValue(new_z_value) - def handle_z_div_10(self): - z_value = self.ui.z_step_val_dsb.value() - self.ui.z_step_val_dsb.setValue(round(z_value/10.0, 2)) + def handle_z_plus_1(self, dsb): + new_z_value = round(dsb.value() + dsb.singleStep(), 2) + if new_z_value <= dsb.maximum(): + self.update_all_z_dsb_value(new_z_value) + else: + logger.warning(f"Cannot set value higher than maximum: {dsb.maximum()}") - def handle_z_mul_10(self): - z_value = self.ui.z_step_val_dsb.value() - self.ui.z_step_val_dsb.setValue(z_value*10.0) + def handle_z_minus_1(self, dsb): + new_z_value = round(dsb.value() - dsb.singleStep(), 2) + if new_z_value >= dsb.minimum(): + self.update_all_z_dsb_value(new_z_value) + else: + logger.warning(f"Cannot set value less than minimum: {dsb.minimum()}") + + def handle_z_div_10(self, dsb): + new_z_value = round(dsb.value() / 10.0, 2) + if new_z_value >= dsb.minimum(): + self.update_all_z_dsb_value(new_z_value) + else: + logger.warning(f"Cannot set value less than minimum: {dsb.minimum()}") + + def handle_z_mul_10(self, dsb): + new_z_value = round(dsb.value() * 10.0, 2) + if new_z_value <= dsb.maximum(): + self.update_all_z_dsb_value(new_z_value) + else: + logger.warning(f"Cannot set value higher than maximum: {dsb.maximum()}") def handle_z_min_changed(self): self.machine_settings.probe_z_min = self.ui.z_min_dsb.value() @@ -796,7 +944,7 @@ def handle_z_max_changed(self): def handle_probe_cmd(self): logger.debug("Probe Command") - # todo: fake parameters just to test probe + self.ui.probe_led_la.set_led_color("yellow") probe_z_min = self.ui.z_min_dsb.value() self.controlWo.cmd_probe(probe_z_min) @@ -808,7 +956,7 @@ def handle_auto_bed_levelling(self): @Slot(float) def update_progress_bar(self, prog_percentage): logger.debug(prog_percentage) - self.ui.progressBar.setValue(prog_percentage) + self.ui.progress_bar.setValue(prog_percentage) @Slot() def update_bbox_x_num_steps(self): diff --git a/src/TheAntFarm/ui_manager/ui_create_job_tab_manager.py b/src/TheAntFarm/ui_manager/ui_create_job_tab_manager.py index 8b13b08..01fa9e1 100644 --- a/src/TheAntFarm/ui_manager/ui_create_job_tab_manager.py +++ b/src/TheAntFarm/ui_manager/ui_create_job_tab_manager.py @@ -183,10 +183,7 @@ def set_settings_per_drill(self): self.ui.drill_xy_feed_rate_dsb.setValue(settings_drill["xy_feedrate"]) self.ui.drill_z_feed_rate_dsb.setValue(settings_drill["z_feedrate"]) - if settings_drill["optimize"]: - self.ui.drill_optimization_chb.setCheckState(Qt.Checked) - else: - self.ui.drill_optimization_chb.setCheckState(Qt.Unchecked) + self.ui.drill_algo_choice_cb.setCurrentIndex(settings_drill["optimize"]) if settings_drill["mirror"]: self.ui.drill_mirror_chb.setCheckState(Qt.Checked) @@ -295,7 +292,7 @@ def get_settings_per_drill(self): settings_drill["spindle"] = self.ui.drill_spindle_speed_dsb.value() settings_drill["xy_feedrate"] = self.ui.drill_xy_feed_rate_dsb.value() settings_drill["z_feedrate"] = self.ui.drill_z_feed_rate_dsb.value() - settings_drill["optimize"] = self.ui.drill_optimization_chb.isChecked() + settings_drill["optimize"] = self.ui.drill_algo_choice_cb.currentIndex() settings_drill["mirror"] = self.ui.drill_mirror_chb.isChecked() logging.debug(settings_drill) return settings_drill diff --git a/src/TheAntFarm/ui_manager/ui_manager.py b/src/TheAntFarm/ui_manager/ui_manager.py index 015339a..01756de 100644 --- a/src/TheAntFarm/ui_manager/ui_manager.py +++ b/src/TheAntFarm/ui_manager/ui_manager.py @@ -39,6 +39,7 @@ def __init__(self, main_win, ui, control_worker, serial_worker, settings): self.vis_layer = VisualLayer(self.ui.viewCanvasWidget) self.ctrl_layer = VisualLayer(self.ui.controlCanvasWidget) + self.vis_align_layer = VisualLayer(self.ui.alignCanvasWidget, selectable=True) # UI Sub-Managers self.ui_load_layer_m = UiViewLoadLayerTab(main_win, control_worker, self.vis_layer, self.L_TAGS, self.L_NAMES, @@ -46,9 +47,9 @@ def __init__(self, main_win, ui, control_worker, serial_worker, settings): self.ui_create_job_m = UiCreateJobLayerTab(ui, control_worker, self.vis_layer, self.L_TAGS, self.L_NAMES, self.settings.jobs_settings) self.ui_control_tab_m = UiControlTab(ui, control_worker, serial_worker, self.ctrl_layer, self.settings) - self.ui_align_tab_m = UiAlignTab(ui, control_worker) + self.ui_align_tab_m = UiAlignTab(main_win, control_worker, self.vis_align_layer, self.settings.app_settings) self.ui_settings_tab_m = UiSettingsPreferencesTab(ui, control_worker, self.settings) - self.ui_about_m = UiAbout(main_win=main_win, app_settings=self.settings.app_settings) + self.ui_about_m = UiAbout(main_win, app_settings=self.settings.app_settings) self.ui.actionAbout.triggered.connect(self.ui_about_m.show_about_info) self.ui_settings_tab_m.save_all_settings_s.connect(self.save_all_settings) diff --git a/src/TheAntFarm/ui_manager/ui_settings_preferences.py b/src/TheAntFarm/ui_manager/ui_settings_preferences.py index ffab78b..66266ff 100644 --- a/src/TheAntFarm/ui_manager/ui_settings_preferences.py +++ b/src/TheAntFarm/ui_manager/ui_settings_preferences.py @@ -36,6 +36,7 @@ def __init__(self, ui, control_worker, settings): self.get_tool_change_flag = False self.get_tool_probe_flag = False + self.get_tool_camera_offset_flag = False self.reset_tool_probe_initial_enables() @@ -46,6 +47,7 @@ def __init__(self, ui, control_worker, settings): self.ui.get_tool_change_pb.clicked.connect(self.ask_tool_change_position) self.load_gcoder_cfg_s.connect(self.control_wo.update_gerber_cfg) self.ui.save_settings_preferences_pb.clicked.connect(self.save_settings_preferences) + self.ui.get_tool_camera_offset_pb.clicked.connect(self.ask_tool_camera_offset) self.ui_tool_probe_set_enabling(enable=False) self.ui_tool_change_set_enabling(enable=False) @@ -70,6 +72,9 @@ def __init__(self, ui, control_worker, settings): self.ui.feedrate_probe_dsb.valueChanged.connect(self.set_focus_lost) self.ui.x_mirror_rb.clicked.connect(self.set_focus_lost) self.ui.y_mirror_rb.clicked.connect(self.set_focus_lost) + self.ui.alignment_drill_diameter_dsb.valueChanged.connect(self.set_focus_lost) + self.ui.x_tool_camera_offset_dsb.valueChanged.connect(self.set_focus_lost) + self.ui.y_tool_camera_offset_dsb.valueChanged.connect(self.set_focus_lost) self.ui.restore_settings_preferences_pb.clicked.connect(self.restore_initial_settings) self.reset_application_settings() @@ -131,6 +136,10 @@ def reset_tool_machine_initial_settings(self): self.ui.feedrate_z_dsb.setValue(self.machine_settings.feedrate_z) self.ui.feedrate_probe_dsb.setValue(self.machine_settings.feedrate_probe) + self.ui.alignment_drill_diameter_dsb.setValue(self.machine_settings.alignment_drill_diameter) + self.ui.x_tool_camera_offset_dsb.setValue(self.machine_settings.tool_camera_offset_x) + self.ui.y_tool_camera_offset_dsb.setValue(self.machine_settings.tool_camera_offset_y) + def restore_initial_settings(self): """Restore initial settings in ui fields. """ self.reset_application_settings() @@ -196,6 +205,9 @@ def get_and_manage_status_report(self, actual_status_report): elif self.get_tool_change_flag: self.get_tool_change_flag = False self.get_tool_change_position(actual_status_report) + elif self.get_tool_camera_offset_flag: + self.get_tool_camera_offset_flag = False + self.get_tool_camera_offset(actual_status_report) def ask_tool_probe_position(self): """ Set get_tool_probe_flag at true and ask controller status report. """ @@ -207,6 +219,11 @@ def ask_tool_change_position(self): self.get_tool_change_flag = True self.ask_status_report() + def ask_tool_camera_offset(self): + """ Set get_tool_camera_offset_flag at true and ask controller status report. """ + self.get_tool_camera_offset_flag = True + self.ask_status_report() + def get_tool_probe_position(self, actual_status_report): """ Get tool offset mpos and wpos and update corresponding ui fields. """ wpos_flag = self.ui.tool_probe_wm_pos_chb.isChecked() @@ -230,12 +247,18 @@ def get_tool_change_position(self, actual_status_report): self.load_gcoder_cfg_s.emit() + def get_tool_camera_offset(self, actual_status_report): + tool_camera_offset_wpos = actual_status_report["wpos"] + self.ui.x_tool_camera_offset_dsb.setValue(tool_camera_offset_wpos[0]) + self.ui.y_tool_camera_offset_dsb.setValue(tool_camera_offset_wpos[1]) + def save_settings_preferences(self): """Save settings preferences from UI to settings.""" if self.ui.x_mirror_rb.isChecked(): self.jobs_settings.jobs_settings_od["common"]["mirroring_axis"] = "x" elif self.ui.y_mirror_rb.isChecked(): self.jobs_settings.jobs_settings_od["common"]["mirroring_axis"] = "y" + self.machine_settings.tool_probe_rel_flag = self.ui.tool_probe_wm_pos_chb.isChecked() self.machine_settings.tool_probe_offset_x_mpos = self.ui.tool_probe_x_mpos_dsb.value() @@ -258,6 +281,10 @@ def save_settings_preferences(self): self.machine_settings.feedrate_z = self.ui.feedrate_z_dsb.value() self.machine_settings.feedrate_probe = self.ui.feedrate_probe_dsb.value() + self.machine_settings.alignment_drill_diameter = self.ui.alignment_drill_diameter_dsb.value() + self.machine_settings.tool_camera_offset_x = self.ui.x_tool_camera_offset_dsb.value() + self.machine_settings.tool_camera_offset_y = self.ui.y_tool_camera_offset_dsb.value() + self.app_settings.layer_color["top"] = self.ui.top_layer_color_la.palette().background().color().name() self.app_settings.layer_color["bottom"] = self.ui.bottom_layer_color_la.palette().background().color().name() self.app_settings.layer_color["profile"] = self.ui.profile_layer_color_la.palette().background().color().name() diff --git a/src/TheAntFarm/ui_the_ant_farm.py b/src/TheAntFarm/ui_the_ant_farm.py index a622753..2ace50d 100644 --- a/src/TheAntFarm/ui_the_ant_farm.py +++ b/src/TheAntFarm/ui_the_ant_farm.py @@ -13,6 +13,9 @@ from PySide2.QtWidgets import * from vispy_qt_widget import VispyCanvas +from combobox_filter_enter import ComboBoxFilterEnter +from qledlabel import QLedLabel +from qcamera_label import QCameraLabel import app_resources_rc @@ -842,11 +845,6 @@ def setupUi(self, MainWindow): self.gridLayout_5.addWidget(self.drill_tw, 0, 1, 1, 2, Qt.AlignHCenter|Qt.AlignVCenter) - self.drill_optimization_chb = QCheckBox(self.drill_page) - self.drill_optimization_chb.setObjectName(u"drill_optimization_chb") - - self.gridLayout_5.addWidget(self.drill_optimization_chb, 13, 2, 1, 1) - self.drill_cut_z_dsb = QDoubleSpinBox(self.drill_page) self.drill_cut_z_dsb.setObjectName(u"drill_cut_z_dsb") self.drill_cut_z_dsb.setDecimals(4) @@ -906,6 +904,14 @@ def setupUi(self, MainWindow): self.gridLayout_5.addWidget(self.drill_mirror_chb, 14, 2, 1, 1) + self.drill_algo_choice_cb = QComboBox(self.drill_page) + self.drill_algo_choice_cb.addItem("") + self.drill_algo_choice_cb.addItem("") + self.drill_algo_choice_cb.addItem("") + self.drill_algo_choice_cb.setObjectName(u"drill_algo_choice_cb") + + self.gridLayout_5.addWidget(self.drill_algo_choice_cb, 13, 2, 1, 1) + self.jobs_sw.addWidget(self.drill_page) self.nc_area_top_page = QWidget() self.nc_area_top_page.setObjectName(u"nc_area_top_page") @@ -1236,6 +1242,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_10 = QHBoxLayout() self.horizontalLayout_10.setObjectName(u"horizontalLayout_10") + self.horizontalLayout_10.setContentsMargins(-1, 10, -1, 10) self.upload_temp_tb = QToolButton(self.gcode_load) self.upload_temp_tb.setObjectName(u"upload_temp_tb") self.upload_temp_tb.setMinimumSize(QSize(50, 50)) @@ -1509,9 +1516,9 @@ def setupUi(self, MainWindow): self.controlsVerticalLayout.addWidget(self.line_3) - self.gridLayout_10 = QGridLayout() - self.gridLayout_10.setObjectName(u"gridLayout_10") - self.gridLayout_10.setContentsMargins(0, 0, 0, 0) + self.probeABLGridLayout = QGridLayout() + self.probeABLGridLayout.setObjectName(u"probeABLGridLayout") + self.probeABLGridLayout.setContentsMargins(0, 0, 0, 0) self.probe_pb = QPushButton(self.sender_tab) self.probe_pb.setObjectName(u"probe_pb") sizePolicy7.setHeightForWidth(self.probe_pb.sizePolicy().hasHeightForWidth()) @@ -1519,7 +1526,7 @@ def setupUi(self, MainWindow): self.probe_pb.setMinimumSize(QSize(0, 20)) self.probe_pb.setMaximumSize(QSize(16777215, 23)) - self.gridLayout_10.addWidget(self.probe_pb, 0, 0, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + self.probeABLGridLayout.addWidget(self.probe_pb, 0, 0, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) self.get_bbox_pb = QPushButton(self.sender_tab) self.get_bbox_pb.setObjectName(u"get_bbox_pb") @@ -1529,7 +1536,7 @@ def setupUi(self, MainWindow): self.get_bbox_pb.setMaximumSize(QSize(16777215, 23)) self.get_bbox_pb.setFont(font) - self.gridLayout_10.addWidget(self.get_bbox_pb, 0, 2, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + self.probeABLGridLayout.addWidget(self.get_bbox_pb, 0, 2, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) self.horizontalLayout_11 = QHBoxLayout() self.horizontalLayout_11.setObjectName(u"horizontalLayout_11") @@ -1557,71 +1564,71 @@ def setupUi(self, MainWindow): self.horizontalLayout_11.addWidget(self.abl_active_chb) - self.gridLayout_10.addLayout(self.horizontalLayout_11, 0, 1, 1, 1) + self.probeABLGridLayout.addLayout(self.horizontalLayout_11, 0, 1, 1, 1) - self.controlsVerticalLayout.addLayout(self.gridLayout_10) + self.controlsVerticalLayout.addLayout(self.probeABLGridLayout) - self.gridLayout_11 = QGridLayout() - self.gridLayout_11.setObjectName(u"gridLayout_11") - self.gridLayout_11.setVerticalSpacing(0) - self.label_6 = QLabel(self.sender_tab) - self.label_6.setObjectName(u"label_6") + self.stepsGridLayout = QGridLayout() + self.stepsGridLayout.setObjectName(u"stepsGridLayout") + self.stepsGridLayout.setVerticalSpacing(0) + self.min_l = QLabel(self.sender_tab) + self.min_l.setObjectName(u"min_l") sizePolicy9 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding) sizePolicy9.setHorizontalStretch(0) sizePolicy9.setVerticalStretch(0) - sizePolicy9.setHeightForWidth(self.label_6.sizePolicy().hasHeightForWidth()) - self.label_6.setSizePolicy(sizePolicy9) - self.label_6.setMinimumSize(QSize(0, 20)) - self.label_6.setMaximumSize(QSize(16777215, 23)) - self.label_6.setFont(font) - self.label_6.setAlignment(Qt.AlignCenter) - - self.gridLayout_11.addWidget(self.label_6, 0, 1, 1, 1) - - self.label_7 = QLabel(self.sender_tab) - self.label_7.setObjectName(u"label_7") - sizePolicy9.setHeightForWidth(self.label_7.sizePolicy().hasHeightForWidth()) - self.label_7.setSizePolicy(sizePolicy9) - self.label_7.setMinimumSize(QSize(0, 20)) - self.label_7.setMaximumSize(QSize(16777215, 23)) - self.label_7.setFont(font) - self.label_7.setAlignment(Qt.AlignCenter) - - self.gridLayout_11.addWidget(self.label_7, 0, 2, 1, 1) - - self.label_8 = QLabel(self.sender_tab) - self.label_8.setObjectName(u"label_8") - sizePolicy9.setHeightForWidth(self.label_8.sizePolicy().hasHeightForWidth()) - self.label_8.setSizePolicy(sizePolicy9) - self.label_8.setMinimumSize(QSize(0, 20)) - self.label_8.setMaximumSize(QSize(16777215, 23)) - self.label_8.setFont(font) - self.label_8.setAlignment(Qt.AlignCenter) - - self.gridLayout_11.addWidget(self.label_8, 0, 3, 1, 1) - - self.label_9 = QLabel(self.sender_tab) - self.label_9.setObjectName(u"label_9") - sizePolicy9.setHeightForWidth(self.label_9.sizePolicy().hasHeightForWidth()) - self.label_9.setSizePolicy(sizePolicy9) - self.label_9.setMinimumSize(QSize(0, 20)) - self.label_9.setMaximumSize(QSize(16777215, 23)) - self.label_9.setFont(font) - self.label_9.setAlignment(Qt.AlignCenter) - - self.gridLayout_11.addWidget(self.label_9, 0, 4, 1, 1) - - self.label_10 = QLabel(self.sender_tab) - self.label_10.setObjectName(u"label_10") - sizePolicy9.setHeightForWidth(self.label_10.sizePolicy().hasHeightForWidth()) - self.label_10.setSizePolicy(sizePolicy9) - self.label_10.setMinimumSize(QSize(0, 20)) - self.label_10.setMaximumSize(QSize(16777215, 23)) - self.label_10.setFont(font) - self.label_10.setAlignment(Qt.AlignCenter) - - self.gridLayout_11.addWidget(self.label_10, 1, 0, 1, 1) + sizePolicy9.setHeightForWidth(self.min_l.sizePolicy().hasHeightForWidth()) + self.min_l.setSizePolicy(sizePolicy9) + self.min_l.setMinimumSize(QSize(0, 20)) + self.min_l.setMaximumSize(QSize(16777215, 23)) + self.min_l.setFont(font) + self.min_l.setAlignment(Qt.AlignCenter) + + self.stepsGridLayout.addWidget(self.min_l, 0, 1, 1, 1) + + self.max_l = QLabel(self.sender_tab) + self.max_l.setObjectName(u"max_l") + sizePolicy9.setHeightForWidth(self.max_l.sizePolicy().hasHeightForWidth()) + self.max_l.setSizePolicy(sizePolicy9) + self.max_l.setMinimumSize(QSize(0, 20)) + self.max_l.setMaximumSize(QSize(16777215, 23)) + self.max_l.setFont(font) + self.max_l.setAlignment(Qt.AlignCenter) + + self.stepsGridLayout.addWidget(self.max_l, 0, 2, 1, 1) + + self.step_l = QLabel(self.sender_tab) + self.step_l.setObjectName(u"step_l") + sizePolicy9.setHeightForWidth(self.step_l.sizePolicy().hasHeightForWidth()) + self.step_l.setSizePolicy(sizePolicy9) + self.step_l.setMinimumSize(QSize(0, 20)) + self.step_l.setMaximumSize(QSize(16777215, 23)) + self.step_l.setFont(font) + self.step_l.setAlignment(Qt.AlignCenter) + + self.stepsGridLayout.addWidget(self.step_l, 0, 3, 1, 1) + + self.n_step_l = QLabel(self.sender_tab) + self.n_step_l.setObjectName(u"n_step_l") + sizePolicy9.setHeightForWidth(self.n_step_l.sizePolicy().hasHeightForWidth()) + self.n_step_l.setSizePolicy(sizePolicy9) + self.n_step_l.setMinimumSize(QSize(0, 20)) + self.n_step_l.setMaximumSize(QSize(16777215, 23)) + self.n_step_l.setFont(font) + self.n_step_l.setAlignment(Qt.AlignCenter) + + self.stepsGridLayout.addWidget(self.n_step_l, 0, 4, 1, 1) + + self.x_l = QLabel(self.sender_tab) + self.x_l.setObjectName(u"x_l") + sizePolicy9.setHeightForWidth(self.x_l.sizePolicy().hasHeightForWidth()) + self.x_l.setSizePolicy(sizePolicy9) + self.x_l.setMinimumSize(QSize(0, 20)) + self.x_l.setMaximumSize(QSize(16777215, 23)) + self.x_l.setFont(font) + self.x_l.setAlignment(Qt.AlignCenter) + + self.stepsGridLayout.addWidget(self.x_l, 1, 0, 1, 1) self.x_min_dsb = QDoubleSpinBox(self.sender_tab) self.x_min_dsb.setObjectName(u"x_min_dsb") @@ -1634,7 +1641,7 @@ def setupUi(self, MainWindow): self.x_min_dsb.setMinimum(-1000.000000000000000) self.x_min_dsb.setMaximum(1000.000000000000000) - self.gridLayout_11.addWidget(self.x_min_dsb, 1, 1, 1, 1) + self.stepsGridLayout.addWidget(self.x_min_dsb, 1, 1, 1, 1) self.x_max_dsb = QDoubleSpinBox(self.sender_tab) self.x_max_dsb.setObjectName(u"x_max_dsb") @@ -1647,7 +1654,7 @@ def setupUi(self, MainWindow): self.x_max_dsb.setMinimum(-1000.000000000000000) self.x_max_dsb.setMaximum(1000.000000000000000) - self.gridLayout_11.addWidget(self.x_max_dsb, 1, 2, 1, 1) + self.stepsGridLayout.addWidget(self.x_max_dsb, 1, 2, 1, 1) self.x_step_dsb = QDoubleSpinBox(self.sender_tab) self.x_step_dsb.setObjectName(u"x_step_dsb") @@ -1660,7 +1667,7 @@ def setupUi(self, MainWindow): self.x_step_dsb.setReadOnly(True) self.x_step_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) - self.gridLayout_11.addWidget(self.x_step_dsb, 1, 3, 1, 1) + self.stepsGridLayout.addWidget(self.x_step_dsb, 1, 3, 1, 1) self.x_num_step_sb = QSpinBox(self.sender_tab) self.x_num_step_sb.setObjectName(u"x_num_step_sb") @@ -1671,18 +1678,18 @@ def setupUi(self, MainWindow): self.x_num_step_sb.setAlignment(Qt.AlignCenter) self.x_num_step_sb.setMinimum(1) - self.gridLayout_11.addWidget(self.x_num_step_sb, 1, 4, 1, 1) + self.stepsGridLayout.addWidget(self.x_num_step_sb, 1, 4, 1, 1) - self.label_11 = QLabel(self.sender_tab) - self.label_11.setObjectName(u"label_11") - sizePolicy9.setHeightForWidth(self.label_11.sizePolicy().hasHeightForWidth()) - self.label_11.setSizePolicy(sizePolicy9) - self.label_11.setMinimumSize(QSize(0, 20)) - self.label_11.setMaximumSize(QSize(16777215, 23)) - self.label_11.setFont(font) - self.label_11.setAlignment(Qt.AlignCenter) + self.y_l = QLabel(self.sender_tab) + self.y_l.setObjectName(u"y_l") + sizePolicy9.setHeightForWidth(self.y_l.sizePolicy().hasHeightForWidth()) + self.y_l.setSizePolicy(sizePolicy9) + self.y_l.setMinimumSize(QSize(0, 20)) + self.y_l.setMaximumSize(QSize(16777215, 23)) + self.y_l.setFont(font) + self.y_l.setAlignment(Qt.AlignCenter) - self.gridLayout_11.addWidget(self.label_11, 2, 0, 1, 1) + self.stepsGridLayout.addWidget(self.y_l, 2, 0, 1, 1) self.y_min_dsb = QDoubleSpinBox(self.sender_tab) self.y_min_dsb.setObjectName(u"y_min_dsb") @@ -1695,7 +1702,7 @@ def setupUi(self, MainWindow): self.y_min_dsb.setMinimum(-1000.000000000000000) self.y_min_dsb.setMaximum(1000.000000000000000) - self.gridLayout_11.addWidget(self.y_min_dsb, 2, 1, 1, 1) + self.stepsGridLayout.addWidget(self.y_min_dsb, 2, 1, 1, 1) self.y_max_dsb = QDoubleSpinBox(self.sender_tab) self.y_max_dsb.setObjectName(u"y_max_dsb") @@ -1708,7 +1715,7 @@ def setupUi(self, MainWindow): self.y_max_dsb.setMinimum(-1000.000000000000000) self.y_max_dsb.setMaximum(1000.000000000000000) - self.gridLayout_11.addWidget(self.y_max_dsb, 2, 2, 1, 1) + self.stepsGridLayout.addWidget(self.y_max_dsb, 2, 2, 1, 1) self.y_step_dsb = QDoubleSpinBox(self.sender_tab) self.y_step_dsb.setObjectName(u"y_step_dsb") @@ -1721,7 +1728,7 @@ def setupUi(self, MainWindow): self.y_step_dsb.setReadOnly(True) self.y_step_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) - self.gridLayout_11.addWidget(self.y_step_dsb, 2, 3, 1, 1) + self.stepsGridLayout.addWidget(self.y_step_dsb, 2, 3, 1, 1) self.y_num_step_sb = QSpinBox(self.sender_tab) self.y_num_step_sb.setObjectName(u"y_num_step_sb") @@ -1732,18 +1739,18 @@ def setupUi(self, MainWindow): self.y_num_step_sb.setAlignment(Qt.AlignCenter) self.y_num_step_sb.setMinimum(1) - self.gridLayout_11.addWidget(self.y_num_step_sb, 2, 4, 1, 1) + self.stepsGridLayout.addWidget(self.y_num_step_sb, 2, 4, 1, 1) - self.label_12 = QLabel(self.sender_tab) - self.label_12.setObjectName(u"label_12") - sizePolicy9.setHeightForWidth(self.label_12.sizePolicy().hasHeightForWidth()) - self.label_12.setSizePolicy(sizePolicy9) - self.label_12.setMinimumSize(QSize(0, 20)) - self.label_12.setMaximumSize(QSize(16777215, 23)) - self.label_12.setFont(font) - self.label_12.setAlignment(Qt.AlignCenter) + self.z_l = QLabel(self.sender_tab) + self.z_l.setObjectName(u"z_l") + sizePolicy9.setHeightForWidth(self.z_l.sizePolicy().hasHeightForWidth()) + self.z_l.setSizePolicy(sizePolicy9) + self.z_l.setMinimumSize(QSize(0, 20)) + self.z_l.setMaximumSize(QSize(16777215, 23)) + self.z_l.setFont(font) + self.z_l.setAlignment(Qt.AlignCenter) - self.gridLayout_11.addWidget(self.label_12, 3, 0, 1, 1) + self.stepsGridLayout.addWidget(self.z_l, 3, 0, 1, 1) self.z_min_dsb = QDoubleSpinBox(self.sender_tab) self.z_min_dsb.setObjectName(u"z_min_dsb") @@ -1756,7 +1763,7 @@ def setupUi(self, MainWindow): self.z_min_dsb.setMinimum(-1000.000000000000000) self.z_min_dsb.setMaximum(1000.000000000000000) - self.gridLayout_11.addWidget(self.z_min_dsb, 3, 1, 1, 1) + self.stepsGridLayout.addWidget(self.z_min_dsb, 3, 1, 1, 1) self.z_max_dsb = QDoubleSpinBox(self.sender_tab) self.z_max_dsb.setObjectName(u"z_max_dsb") @@ -1769,10 +1776,10 @@ def setupUi(self, MainWindow): self.z_max_dsb.setMinimum(-1000.000000000000000) self.z_max_dsb.setMaximum(1000.000000000000000) - self.gridLayout_11.addWidget(self.z_max_dsb, 3, 2, 1, 1) + self.stepsGridLayout.addWidget(self.z_max_dsb, 3, 2, 1, 1) - self.controlsVerticalLayout.addLayout(self.gridLayout_11) + self.controlsVerticalLayout.addLayout(self.stepsGridLayout) self.line = QFrame(self.sender_tab) self.line.setObjectName(u"line") @@ -1781,11 +1788,11 @@ def setupUi(self, MainWindow): self.controlsVerticalLayout.addWidget(self.line) - self.jog_layout = QGridLayout() - self.jog_layout.setObjectName(u"jog_layout") - self.gridLayout_17 = QGridLayout() - self.gridLayout_17.setObjectName(u"gridLayout_17") - self.gridLayout_17.setSizeConstraint(QLayout.SetDefaultConstraint) + self.jogGridlayout = QGridLayout() + self.jogGridlayout.setObjectName(u"jogGridlayout") + self.zMoveGridLayout = QGridLayout() + self.zMoveGridLayout.setObjectName(u"zMoveGridLayout") + self.zMoveGridLayout.setSizeConstraint(QLayout.SetDefaultConstraint) self.z_plus_pb = QPushButton(self.sender_tab) self.z_plus_pb.setObjectName(u"z_plus_pb") sizePolicy3.setHeightForWidth(self.z_plus_pb.sizePolicy().hasHeightForWidth()) @@ -1796,7 +1803,7 @@ def setupUi(self, MainWindow): icon5.addFile(u":/resources/resources/icons/white_north_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) self.z_plus_pb.setIcon(icon5) - self.gridLayout_17.addWidget(self.z_plus_pb, 0, 0, 1, 1) + self.zMoveGridLayout.addWidget(self.z_plus_pb, 0, 0, 1, 1) self.z_minus_pb = QPushButton(self.sender_tab) self.z_minus_pb.setObjectName(u"z_minus_pb") @@ -1808,71 +1815,71 @@ def setupUi(self, MainWindow): icon6.addFile(u":/resources/resources/icons/white_south_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) self.z_minus_pb.setIcon(icon6) - self.gridLayout_17.addWidget(self.z_minus_pb, 1, 0, 1, 1) + self.zMoveGridLayout.addWidget(self.z_minus_pb, 1, 0, 1, 1) - self.jog_layout.addLayout(self.gridLayout_17, 2, 0, 1, 1) + self.jogGridlayout.addLayout(self.zMoveGridLayout, 2, 0, 1, 1) - self.gridLayoutDirections_3 = QGridLayout() - self.gridLayoutDirections_3.setObjectName(u"gridLayoutDirections_3") - self.gridLayoutDirections_3.setContentsMargins(0, 0, 0, 0) - self.xYMinusPlusButton = QToolButton(self.sender_tab) - self.xYMinusPlusButton.setObjectName(u"xYMinusPlusButton") - sizePolicy3.setHeightForWidth(self.xYMinusPlusButton.sizePolicy().hasHeightForWidth()) - self.xYMinusPlusButton.setSizePolicy(sizePolicy3) - self.xYMinusPlusButton.setMinimumSize(QSize(0, 22)) - self.xYMinusPlusButton.setMaximumSize(QSize(50, 16777215)) + self.xyMoveGridLayout = QGridLayout() + self.xyMoveGridLayout.setObjectName(u"xyMoveGridLayout") + self.xyMoveGridLayout.setContentsMargins(0, 0, 0, 0) + self.x_minus_y_plus_pb = QToolButton(self.sender_tab) + self.x_minus_y_plus_pb.setObjectName(u"x_minus_y_plus_pb") + sizePolicy3.setHeightForWidth(self.x_minus_y_plus_pb.sizePolicy().hasHeightForWidth()) + self.x_minus_y_plus_pb.setSizePolicy(sizePolicy3) + self.x_minus_y_plus_pb.setMinimumSize(QSize(0, 22)) + self.x_minus_y_plus_pb.setMaximumSize(QSize(50, 16777215)) icon7 = QIcon() icon7.addFile(u":/resources/resources/icons/white_north_west_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) - self.xYMinusPlusButton.setIcon(icon7) + self.x_minus_y_plus_pb.setIcon(icon7) - self.gridLayoutDirections_3.addWidget(self.xYMinusPlusButton, 0, 0, 1, 1) + self.xyMoveGridLayout.addWidget(self.x_minus_y_plus_pb, 0, 0, 1, 1) - self.xYPlusMinuButton = QToolButton(self.sender_tab) - self.xYPlusMinuButton.setObjectName(u"xYPlusMinuButton") - sizePolicy3.setHeightForWidth(self.xYPlusMinuButton.sizePolicy().hasHeightForWidth()) - self.xYPlusMinuButton.setSizePolicy(sizePolicy3) - self.xYPlusMinuButton.setMinimumSize(QSize(0, 22)) - self.xYPlusMinuButton.setMaximumSize(QSize(50, 16777215)) + self.x_plus_y_minus_pb = QToolButton(self.sender_tab) + self.x_plus_y_minus_pb.setObjectName(u"x_plus_y_minus_pb") + sizePolicy3.setHeightForWidth(self.x_plus_y_minus_pb.sizePolicy().hasHeightForWidth()) + self.x_plus_y_minus_pb.setSizePolicy(sizePolicy3) + self.x_plus_y_minus_pb.setMinimumSize(QSize(0, 22)) + self.x_plus_y_minus_pb.setMaximumSize(QSize(50, 16777215)) icon8 = QIcon() icon8.addFile(u":/resources/resources/icons/white_south_east_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) - self.xYPlusMinuButton.setIcon(icon8) + self.x_plus_y_minus_pb.setIcon(icon8) - self.gridLayoutDirections_3.addWidget(self.xYPlusMinuButton, 2, 2, 1, 1) + self.xyMoveGridLayout.addWidget(self.x_plus_y_minus_pb, 2, 2, 1, 1) - self.xMinusButton = QToolButton(self.sender_tab) - self.xMinusButton.setObjectName(u"xMinusButton") - sizePolicy3.setHeightForWidth(self.xMinusButton.sizePolicy().hasHeightForWidth()) - self.xMinusButton.setSizePolicy(sizePolicy3) - self.xMinusButton.setMinimumSize(QSize(0, 22)) - self.xMinusButton.setMaximumSize(QSize(50, 16777215)) + self.x_minus_pb = QToolButton(self.sender_tab) + self.x_minus_pb.setObjectName(u"x_minus_pb") + sizePolicy3.setHeightForWidth(self.x_minus_pb.sizePolicy().hasHeightForWidth()) + self.x_minus_pb.setSizePolicy(sizePolicy3) + self.x_minus_pb.setMinimumSize(QSize(0, 22)) + self.x_minus_pb.setMaximumSize(QSize(50, 16777215)) icon9 = QIcon() icon9.addFile(u":/resources/resources/icons/white_west_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) - self.xMinusButton.setIcon(icon9) + self.x_minus_pb.setIcon(icon9) - self.gridLayoutDirections_3.addWidget(self.xMinusButton, 1, 0, 1, 1) + self.xyMoveGridLayout.addWidget(self.x_minus_pb, 1, 0, 1, 1) - self.xYMinusButton = QToolButton(self.sender_tab) - self.xYMinusButton.setObjectName(u"xYMinusButton") - sizePolicy3.setHeightForWidth(self.xYMinusButton.sizePolicy().hasHeightForWidth()) - self.xYMinusButton.setSizePolicy(sizePolicy3) - self.xYMinusButton.setMinimumSize(QSize(0, 22)) - self.xYMinusButton.setMaximumSize(QSize(50, 16777215)) + self.x_minus_y_minus_pb = QToolButton(self.sender_tab) + self.x_minus_y_minus_pb.setObjectName(u"x_minus_y_minus_pb") + sizePolicy3.setHeightForWidth(self.x_minus_y_minus_pb.sizePolicy().hasHeightForWidth()) + self.x_minus_y_minus_pb.setSizePolicy(sizePolicy3) + self.x_minus_y_minus_pb.setMinimumSize(QSize(0, 22)) + self.x_minus_y_minus_pb.setMaximumSize(QSize(50, 16777215)) icon10 = QIcon() icon10.addFile(u":/resources/resources/icons/white_south_west_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) - self.xYMinusButton.setIcon(icon10) + self.x_minus_y_minus_pb.setIcon(icon10) - self.gridLayoutDirections_3.addWidget(self.xYMinusButton, 2, 0, 1, 1) + self.xyMoveGridLayout.addWidget(self.x_minus_y_minus_pb, 2, 0, 1, 1) - self.yPlusButton = QToolButton(self.sender_tab) - self.yPlusButton.setObjectName(u"yPlusButton") - sizePolicy3.setHeightForWidth(self.yPlusButton.sizePolicy().hasHeightForWidth()) - self.yPlusButton.setSizePolicy(sizePolicy3) - self.yPlusButton.setMinimumSize(QSize(0, 22)) - self.yPlusButton.setMaximumSize(QSize(50, 16777215)) - self.yPlusButton.setIcon(icon5) + self.y_plus_pb = QToolButton(self.sender_tab) + self.y_plus_pb.setObjectName(u"y_plus_pb") + sizePolicy3.setHeightForWidth(self.y_plus_pb.sizePolicy().hasHeightForWidth()) + self.y_plus_pb.setSizePolicy(sizePolicy3) + self.y_plus_pb.setMinimumSize(QSize(0, 22)) + self.y_plus_pb.setMaximumSize(QSize(50, 16777215)) + self.y_plus_pb.setIcon(icon5) - self.gridLayoutDirections_3.addWidget(self.yPlusButton, 0, 1, 1, 1) + self.xyMoveGridLayout.addWidget(self.y_plus_pb, 0, 1, 1, 1) self.center_tb = QToolButton(self.sender_tab) self.center_tb.setObjectName(u"center_tb") @@ -1884,47 +1891,47 @@ def setupUi(self, MainWindow): icon11.addFile(u":/resources/resources/icons/white_circle.svg", QSize(), QIcon.Normal, QIcon.Off) self.center_tb.setIcon(icon11) - self.gridLayoutDirections_3.addWidget(self.center_tb, 1, 1, 1, 1) + self.xyMoveGridLayout.addWidget(self.center_tb, 1, 1, 1, 1) - self.yMinusButton = QToolButton(self.sender_tab) - self.yMinusButton.setObjectName(u"yMinusButton") - sizePolicy3.setHeightForWidth(self.yMinusButton.sizePolicy().hasHeightForWidth()) - self.yMinusButton.setSizePolicy(sizePolicy3) - self.yMinusButton.setMinimumSize(QSize(0, 22)) - self.yMinusButton.setMaximumSize(QSize(50, 16777215)) - self.yMinusButton.setIcon(icon6) + self.y_minus_pb = QToolButton(self.sender_tab) + self.y_minus_pb.setObjectName(u"y_minus_pb") + sizePolicy3.setHeightForWidth(self.y_minus_pb.sizePolicy().hasHeightForWidth()) + self.y_minus_pb.setSizePolicy(sizePolicy3) + self.y_minus_pb.setMinimumSize(QSize(0, 22)) + self.y_minus_pb.setMaximumSize(QSize(50, 16777215)) + self.y_minus_pb.setIcon(icon6) - self.gridLayoutDirections_3.addWidget(self.yMinusButton, 2, 1, 1, 1) + self.xyMoveGridLayout.addWidget(self.y_minus_pb, 2, 1, 1, 1) - self.xYPlusButton = QToolButton(self.sender_tab) - self.xYPlusButton.setObjectName(u"xYPlusButton") - sizePolicy3.setHeightForWidth(self.xYPlusButton.sizePolicy().hasHeightForWidth()) - self.xYPlusButton.setSizePolicy(sizePolicy3) - self.xYPlusButton.setMinimumSize(QSize(0, 22)) - self.xYPlusButton.setMaximumSize(QSize(50, 16777215)) + self.x_plus_y_plus_pb = QToolButton(self.sender_tab) + self.x_plus_y_plus_pb.setObjectName(u"x_plus_y_plus_pb") + sizePolicy3.setHeightForWidth(self.x_plus_y_plus_pb.sizePolicy().hasHeightForWidth()) + self.x_plus_y_plus_pb.setSizePolicy(sizePolicy3) + self.x_plus_y_plus_pb.setMinimumSize(QSize(0, 22)) + self.x_plus_y_plus_pb.setMaximumSize(QSize(50, 16777215)) icon12 = QIcon() icon12.addFile(u":/resources/resources/icons/white_north_east_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) - self.xYPlusButton.setIcon(icon12) + self.x_plus_y_plus_pb.setIcon(icon12) - self.gridLayoutDirections_3.addWidget(self.xYPlusButton, 0, 2, 1, 1) + self.xyMoveGridLayout.addWidget(self.x_plus_y_plus_pb, 0, 2, 1, 1) - self.xPlusButton = QToolButton(self.sender_tab) - self.xPlusButton.setObjectName(u"xPlusButton") - sizePolicy3.setHeightForWidth(self.xPlusButton.sizePolicy().hasHeightForWidth()) - self.xPlusButton.setSizePolicy(sizePolicy3) - self.xPlusButton.setMinimumSize(QSize(0, 22)) - self.xPlusButton.setMaximumSize(QSize(50, 16777215)) + self.x_plus_pb = QToolButton(self.sender_tab) + self.x_plus_pb.setObjectName(u"x_plus_pb") + sizePolicy3.setHeightForWidth(self.x_plus_pb.sizePolicy().hasHeightForWidth()) + self.x_plus_pb.setSizePolicy(sizePolicy3) + self.x_plus_pb.setMinimumSize(QSize(0, 22)) + self.x_plus_pb.setMaximumSize(QSize(50, 16777215)) icon13 = QIcon() icon13.addFile(u":/resources/resources/icons/white_east_arrow.svg", QSize(), QIcon.Normal, QIcon.Off) - self.xPlusButton.setIcon(icon13) + self.x_plus_pb.setIcon(icon13) - self.gridLayoutDirections_3.addWidget(self.xPlusButton, 1, 2, 1, 1) + self.xyMoveGridLayout.addWidget(self.x_plus_pb, 1, 2, 1, 1) - self.jog_layout.addLayout(self.gridLayoutDirections_3, 0, 0, 1, 1) + self.jogGridlayout.addLayout(self.xyMoveGridLayout, 0, 0, 1, 1) - self.verticalLayout_15 = QVBoxLayout() - self.verticalLayout_15.setObjectName(u"verticalLayout_15") + self.zStepAdjustmentVerticalLayout = QVBoxLayout() + self.zStepAdjustmentVerticalLayout.setObjectName(u"zStepAdjustmentVerticalLayout") self.horizontalLayout_14 = QHBoxLayout() self.horizontalLayout_14.setObjectName(u"horizontalLayout_14") self.horizontalLayout_14.setSizeConstraint(QLayout.SetDefaultConstraint) @@ -1958,7 +1965,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_14.addWidget(self.z_step_cb, 0, Qt.AlignHCenter|Qt.AlignVCenter) - self.verticalLayout_15.addLayout(self.horizontalLayout_14) + self.zStepAdjustmentVerticalLayout.addLayout(self.horizontalLayout_14) self.gridLayout_18 = QGridLayout() self.gridLayout_18.setObjectName(u"gridLayout_18") @@ -2025,13 +2032,13 @@ def setupUi(self, MainWindow): self.gridLayout_18.addWidget(self.z_plus_1_pb, 0, 1, 1, 1) - self.verticalLayout_15.addLayout(self.gridLayout_18) + self.zStepAdjustmentVerticalLayout.addLayout(self.gridLayout_18) - self.jog_layout.addLayout(self.verticalLayout_15, 2, 1, 1, 1) + self.jogGridlayout.addLayout(self.zStepAdjustmentVerticalLayout, 2, 1, 1, 1) - self.verticalLayout_14 = QVBoxLayout() - self.verticalLayout_14.setObjectName(u"verticalLayout_14") + self.xyStepAdjustmentVerticalLayout = QVBoxLayout() + self.xyStepAdjustmentVerticalLayout.setObjectName(u"xyStepAdjustmentVerticalLayout") self.horizontalLayout_12 = QHBoxLayout() self.horizontalLayout_12.setObjectName(u"horizontalLayout_12") self.horizontalLayout_12.setSizeConstraint(QLayout.SetDefaultConstraint) @@ -2063,7 +2070,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_12.addWidget(self.xy_step_cb, 0, Qt.AlignHCenter|Qt.AlignVCenter) - self.verticalLayout_14.addLayout(self.horizontalLayout_12) + self.xyStepAdjustmentVerticalLayout.addLayout(self.horizontalLayout_12) self.gridLayout_16 = QGridLayout() self.gridLayout_16.setObjectName(u"gridLayout_16") @@ -2128,10 +2135,10 @@ def setupUi(self, MainWindow): self.gridLayout_16.addWidget(self.xy_minus_1_pb, 2, 1, 1, 1) - self.verticalLayout_14.addLayout(self.gridLayout_16) + self.xyStepAdjustmentVerticalLayout.addLayout(self.gridLayout_16) - self.jog_layout.addLayout(self.verticalLayout_14, 0, 1, 1, 1) + self.jogGridlayout.addLayout(self.xyStepAdjustmentVerticalLayout, 0, 1, 1, 1) self.line_2 = QFrame(self.sender_tab) self.line_2.setObjectName(u"line_2") @@ -2139,17 +2146,17 @@ def setupUi(self, MainWindow): self.line_2.setFrameShape(QFrame.HLine) self.line_2.setFrameShadow(QFrame.Sunken) - self.jog_layout.addWidget(self.line_2, 1, 1, 1, 1) + self.jogGridlayout.addWidget(self.line_2, 1, 1, 1, 1) self.line_5 = QFrame(self.sender_tab) self.line_5.setObjectName(u"line_5") self.line_5.setFrameShape(QFrame.HLine) self.line_5.setFrameShadow(QFrame.Sunken) - self.jog_layout.addWidget(self.line_5, 1, 0, 1, 1) + self.jogGridlayout.addWidget(self.line_5, 1, 0, 1, 1) - self.controlsVerticalLayout.addLayout(self.jog_layout) + self.controlsVerticalLayout.addLayout(self.jogGridlayout) self.terminalVerticalLayout = QVBoxLayout() self.terminalVerticalLayout.setObjectName(u"terminalVerticalLayout") @@ -2170,10 +2177,14 @@ def setupUi(self, MainWindow): self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") - self.send_te = QLineEdit(self.sender_tab) - self.send_te.setObjectName(u"send_te") + self.send_cb = ComboBoxFilterEnter(self.sender_tab) + self.send_cb.setObjectName(u"send_cb") + sizePolicy2.setHeightForWidth(self.send_cb.sizePolicy().hasHeightForWidth()) + self.send_cb.setSizePolicy(sizePolicy2) + self.send_cb.setAutoFillBackground(True) + self.send_cb.setEditable(True) - self.horizontalLayout_2.addWidget(self.send_te) + self.horizontalLayout_2.addWidget(self.send_cb) self.send_pb = QPushButton(self.sender_tab) self.send_pb.setObjectName(u"send_pb") @@ -2273,11 +2284,43 @@ def setupUi(self, MainWindow): self.verticalLayout.addWidget(self.controlCanvasWidget) - self.progressBar = QProgressBar(self.control_tab) - self.progressBar.setObjectName(u"progressBar") - self.progressBar.setValue(0) + self.horizontalLayout_22 = QHBoxLayout() + self.horizontalLayout_22.setObjectName(u"horizontalLayout_22") + self.progress_bar = QProgressBar(self.control_tab) + self.progress_bar.setObjectName(u"progress_bar") + self.progress_bar.setValue(0) + + self.horizontalLayout_22.addWidget(self.progress_bar) + + self.probe_led_la = QLedLabel(self.control_tab) + self.probe_led_la.setObjectName(u"probe_led_la") + sizePolicy3.setHeightForWidth(self.probe_led_la.sizePolicy().hasHeightForWidth()) + self.probe_led_la.setSizePolicy(sizePolicy3) + self.probe_led_la.setMinimumSize(QSize(30, 30)) + + self.horizontalLayout_22.addWidget(self.probe_led_la) + + self.abl_led_la = QLedLabel(self.control_tab) + self.abl_led_la.setObjectName(u"abl_led_la") + sizePolicy3.setHeightForWidth(self.abl_led_la.sizePolicy().hasHeightForWidth()) + self.abl_led_la.setSizePolicy(sizePolicy3) + self.abl_led_la.setMinimumSize(QSize(30, 30)) + + self.horizontalLayout_22.addWidget(self.abl_led_la) - self.verticalLayout.addWidget(self.progressBar) + self.apply_alignment_tb_2 = QToolButton(self.control_tab) + self.apply_alignment_tb_2.setObjectName(u"apply_alignment_tb_2") + self.apply_alignment_tb_2.setMinimumSize(QSize(30, 30)) + icon14 = QIcon() + icon14.addFile(u":/resources/resources/icons/black_apply_align.svg", QSize(), QIcon.Normal, QIcon.Off) + icon14.addFile(u":/resources/resources/icons/black_alignment_applied.svg", QSize(), QIcon.Normal, QIcon.On) + self.apply_alignment_tb_2.setIcon(icon14) + self.apply_alignment_tb_2.setCheckable(True) + + self.horizontalLayout_22.addWidget(self.apply_alignment_tb_2) + + + self.verticalLayout.addLayout(self.horizontalLayout_22) self.horizontalLayout_4.addLayout(self.verticalLayout) @@ -2295,12 +2338,12 @@ def setupUi(self, MainWindow): self.soft_reset_tb.setSizePolicy(sizePolicy6) self.soft_reset_tb.setMinimumSize(QSize(120, 25)) self.soft_reset_tb.setMaximumSize(QSize(120, 16777215)) - icon14 = QIcon() - icon14.addFile(u":/resources/resources/icons/white-refresh.svg", QSize(), QIcon.Normal, QIcon.Off) - icon14.addFile(u":/resources/resources/icons/white-refresh.svg", QSize(), QIcon.Normal, QIcon.On) - icon14.addFile(u":/resources/resources/icons/gray-refresh.svg", QSize(), QIcon.Disabled, QIcon.Off) - icon14.addFile(u":/resources/resources/icons/gray-refresh.svg", QSize(), QIcon.Disabled, QIcon.On) - self.soft_reset_tb.setIcon(icon14) + icon15 = QIcon() + icon15.addFile(u":/resources/resources/icons/white-refresh.svg", QSize(), QIcon.Normal, QIcon.Off) + icon15.addFile(u":/resources/resources/icons/white-refresh.svg", QSize(), QIcon.Normal, QIcon.On) + icon15.addFile(u":/resources/resources/icons/gray-refresh.svg", QSize(), QIcon.Disabled, QIcon.Off) + icon15.addFile(u":/resources/resources/icons/gray-refresh.svg", QSize(), QIcon.Disabled, QIcon.On) + self.soft_reset_tb.setIcon(icon15) self.soft_reset_tb.setIconSize(QSize(64, 64)) self.soft_reset_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) @@ -2421,11 +2464,11 @@ def setupUi(self, MainWindow): self.unlock_tb.setSizePolicy(sizePolicy6) self.unlock_tb.setMinimumSize(QSize(120, 80)) self.unlock_tb.setMaximumSize(QSize(120, 16777215)) - icon15 = QIcon() - icon15.addFile(u":/resources/resources/icons/white-unlock-padlock.svg", QSize(), QIcon.Normal, QIcon.Off) - icon15.addFile(u":/resources/resources/icons/gray-unlock-padlock.svg", QSize(), QIcon.Disabled, QIcon.Off) - icon15.addFile(u":/resources/resources/icons/gray-unlock-padlock.svg", QSize(), QIcon.Disabled, QIcon.On) - self.unlock_tb.setIcon(icon15) + icon16 = QIcon() + icon16.addFile(u":/resources/resources/icons/white-unlock-padlock.svg", QSize(), QIcon.Normal, QIcon.Off) + icon16.addFile(u":/resources/resources/icons/gray-unlock-padlock.svg", QSize(), QIcon.Disabled, QIcon.Off) + icon16.addFile(u":/resources/resources/icons/gray-unlock-padlock.svg", QSize(), QIcon.Disabled, QIcon.On) + self.unlock_tb.setIcon(icon16) self.unlock_tb.setIconSize(QSize(64, 64)) self.unlock_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) @@ -2437,11 +2480,11 @@ def setupUi(self, MainWindow): self.homing_tb.setSizePolicy(sizePolicy6) self.homing_tb.setMinimumSize(QSize(120, 80)) self.homing_tb.setMaximumSize(QSize(120, 16777215)) - icon16 = QIcon() - icon16.addFile(u":/resources/resources/icons/white-home.svg", QSize(), QIcon.Normal, QIcon.Off) - icon16.addFile(u":/resources/resources/icons/gray-home.svg", QSize(), QIcon.Disabled, QIcon.Off) - icon16.addFile(u":/resources/resources/icons/gray-home.svg", QSize(), QIcon.Disabled, QIcon.On) - self.homing_tb.setIcon(icon16) + icon17 = QIcon() + icon17.addFile(u":/resources/resources/icons/white-home.svg", QSize(), QIcon.Normal, QIcon.Off) + icon17.addFile(u":/resources/resources/icons/gray-home.svg", QSize(), QIcon.Disabled, QIcon.Off) + icon17.addFile(u":/resources/resources/icons/gray-home.svg", QSize(), QIcon.Disabled, QIcon.On) + self.homing_tb.setIcon(icon17) self.homing_tb.setIconSize(QSize(64, 64)) self.homing_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) @@ -2453,11 +2496,11 @@ def setupUi(self, MainWindow): self.play_tb.setSizePolicy(sizePolicy6) self.play_tb.setMinimumSize(QSize(120, 80)) self.play_tb.setMaximumSize(QSize(120, 16777215)) - icon17 = QIcon() - icon17.addFile(u":/resources/resources/icons/white-play-button-arrowhead.svg", QSize(), QIcon.Normal, QIcon.Off) - icon17.addFile(u":/resources/resources/icons/gray-play-button-arrowhead.svg", QSize(), QIcon.Disabled, QIcon.Off) - icon17.addFile(u":/resources/resources/icons/gray-play-button-arrowhead.svg", QSize(), QIcon.Disabled, QIcon.On) - self.play_tb.setIcon(icon17) + icon18 = QIcon() + icon18.addFile(u":/resources/resources/icons/white-play-button-arrowhead.svg", QSize(), QIcon.Normal, QIcon.Off) + icon18.addFile(u":/resources/resources/icons/gray-play-button-arrowhead.svg", QSize(), QIcon.Disabled, QIcon.Off) + icon18.addFile(u":/resources/resources/icons/gray-play-button-arrowhead.svg", QSize(), QIcon.Disabled, QIcon.On) + self.play_tb.setIcon(icon18) self.play_tb.setIconSize(QSize(64, 64)) self.play_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) @@ -2469,11 +2512,11 @@ def setupUi(self, MainWindow): self.pause_resume_tb.setSizePolicy(sizePolicy6) self.pause_resume_tb.setMinimumSize(QSize(120, 80)) self.pause_resume_tb.setMaximumSize(QSize(120, 16777215)) - icon18 = QIcon() - icon18.addFile(u":/resources/resources/icons/white-pause-multimedia-big-gross-symbol-lines.svg", QSize(), QIcon.Normal, QIcon.Off) - icon18.addFile(u":/resources/resources/icons/gray-pause-multimedia-big-gross-symbol-lines.svg", QSize(), QIcon.Disabled, QIcon.Off) - icon18.addFile(u":/resources/resources/icons/gray-pause-multimedia-big-gross-symbol-lines.svg", QSize(), QIcon.Disabled, QIcon.On) - self.pause_resume_tb.setIcon(icon18) + icon19 = QIcon() + icon19.addFile(u":/resources/resources/icons/white-pause-multimedia-big-gross-symbol-lines.svg", QSize(), QIcon.Normal, QIcon.Off) + icon19.addFile(u":/resources/resources/icons/gray-pause-multimedia-big-gross-symbol-lines.svg", QSize(), QIcon.Disabled, QIcon.Off) + icon19.addFile(u":/resources/resources/icons/gray-pause-multimedia-big-gross-symbol-lines.svg", QSize(), QIcon.Disabled, QIcon.On) + self.pause_resume_tb.setIcon(icon19) self.pause_resume_tb.setIconSize(QSize(64, 64)) self.pause_resume_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) @@ -2485,11 +2528,11 @@ def setupUi(self, MainWindow): self.stop_tb.setSizePolicy(sizePolicy6) self.stop_tb.setMinimumSize(QSize(120, 80)) self.stop_tb.setMaximumSize(QSize(120, 16777215)) - icon19 = QIcon() - icon19.addFile(u":/resources/resources/icons/white-stop-button-black-rounded-square.svg", QSize(), QIcon.Normal, QIcon.Off) - icon19.addFile(u":/resources/resources/icons/gray-stop-button-black-rounded-square.svg", QSize(), QIcon.Disabled, QIcon.Off) - icon19.addFile(u":/resources/resources/icons/gray-stop-button-black-rounded-square.svg", QSize(), QIcon.Disabled, QIcon.On) - self.stop_tb.setIcon(icon19) + icon20 = QIcon() + icon20.addFile(u":/resources/resources/icons/white-stop-button-black-rounded-square.svg", QSize(), QIcon.Normal, QIcon.Off) + icon20.addFile(u":/resources/resources/icons/gray-stop-button-black-rounded-square.svg", QSize(), QIcon.Disabled, QIcon.Off) + icon20.addFile(u":/resources/resources/icons/gray-stop-button-black-rounded-square.svg", QSize(), QIcon.Disabled, QIcon.On) + self.stop_tb.setIcon(icon20) self.stop_tb.setIconSize(QSize(64, 64)) self.stop_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) @@ -2501,11 +2544,11 @@ def setupUi(self, MainWindow): self.tool_change_tb.setSizePolicy(sizePolicy6) self.tool_change_tb.setMinimumSize(QSize(120, 80)) self.tool_change_tb.setMaximumSize(QSize(120, 16777215)) - icon20 = QIcon() - icon20.addFile(u":/resources/resources/icons/white-milling-machine.svg", QSize(), QIcon.Normal, QIcon.Off) - icon20.addFile(u":/resources/resources/icons/gray-milling-machine.svg", QSize(), QIcon.Disabled, QIcon.Off) - icon20.addFile(u":/resources/resources/icons/gray-milling-machine.svg", QSize(), QIcon.Disabled, QIcon.On) - self.tool_change_tb.setIcon(icon20) + icon21 = QIcon() + icon21.addFile(u":/resources/resources/icons/white-milling-machine.svg", QSize(), QIcon.Normal, QIcon.Off) + icon21.addFile(u":/resources/resources/icons/gray-milling-machine.svg", QSize(), QIcon.Disabled, QIcon.Off) + icon21.addFile(u":/resources/resources/icons/gray-milling-machine.svg", QSize(), QIcon.Disabled, QIcon.On) + self.tool_change_tb.setIcon(icon21) self.tool_change_tb.setIconSize(QSize(72, 72)) self.tool_change_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) @@ -2520,22 +2563,770 @@ def setupUi(self, MainWindow): self.align_tab.setFont(font) self.horizontalLayout_7 = QHBoxLayout(self.align_tab) self.horizontalLayout_7.setObjectName(u"horizontalLayout_7") - self.openGLWidget_2 = QOpenGLWidget(self.align_tab) - self.openGLWidget_2.setObjectName(u"openGLWidget_2") + self.horizontalLayout_17 = QHBoxLayout() + self.horizontalLayout_17.setObjectName(u"horizontalLayout_17") + self.horizontalLayout_18 = QHBoxLayout() + self.horizontalLayout_18.setObjectName(u"horizontalLayout_18") + self.verticalLayout_14 = QVBoxLayout() + self.verticalLayout_14.setObjectName(u"verticalLayout_14") + self.frame = QFrame(self.align_tab) + self.frame.setObjectName(u"frame") + self.frame.setFrameShape(QFrame.StyledPanel) + self.frame.setFrameShadow(QFrame.Raised) + self.verticalLayout_13 = QVBoxLayout(self.frame) + self.verticalLayout_13.setObjectName(u"verticalLayout_13") + self.camera_la = QCameraLabel(self.frame) + self.camera_la.setObjectName(u"camera_la") + sizePolicy13 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Expanding) + sizePolicy13.setHorizontalStretch(0) + sizePolicy13.setVerticalStretch(0) + sizePolicy13.setHeightForWidth(self.camera_la.sizePolicy().hasHeightForWidth()) + self.camera_la.setSizePolicy(sizePolicy13) + self.camera_la.setMinimumSize(QSize(200, 150)) + self.camera_la.setMaximumSize(QSize(480, 480)) + + self.verticalLayout_13.addWidget(self.camera_la) + + self.gridLayout_28 = QGridLayout() + self.gridLayout_28.setObjectName(u"gridLayout_28") + self.tool_or_camera_tb = QToolButton(self.frame) + self.tool_or_camera_tb.setObjectName(u"tool_or_camera_tb") + self.tool_or_camera_tb.setCheckable(True) + self.tool_or_camera_tb.setToolButtonStyle(Qt.ToolButtonTextOnly) + + self.gridLayout_28.addWidget(self.tool_or_camera_tb, 2, 1, 1, 1, Qt.AlignHCenter) + + self.camera_list_cb = QComboBox(self.frame) + self.camera_list_cb.setObjectName(u"camera_list_cb") + + self.gridLayout_28.addWidget(self.camera_list_cb, 0, 1, 1, 1) + + self.label_16 = QLabel(self.frame) + self.label_16.setObjectName(u"label_16") + + self.gridLayout_28.addWidget(self.label_16, 0, 0, 1, 1) + + self.camera_zoom_la = QLabel(self.frame) + self.camera_zoom_la.setObjectName(u"camera_zoom_la") + + self.gridLayout_28.addWidget(self.camera_zoom_la, 1, 0, 1, 1) + + self.camera_list_pb = QToolButton(self.frame) + self.camera_list_pb.setObjectName(u"camera_list_pb") + + self.gridLayout_28.addWidget(self.camera_list_pb, 0, 2, 1, 1) + + self.camera_zoom_cb = QComboBox(self.frame) + self.camera_zoom_cb.setObjectName(u"camera_zoom_cb") + + self.gridLayout_28.addWidget(self.camera_zoom_cb, 1, 1, 1, 1) + + + self.verticalLayout_13.addLayout(self.gridLayout_28) + + + self.verticalLayout_14.addWidget(self.frame) + + self.verticalSpacer_3 = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.verticalLayout_14.addItem(self.verticalSpacer_3) + + self.frame_2 = QFrame(self.align_tab) + self.frame_2.setObjectName(u"frame_2") + self.frame_2.setFrameShape(QFrame.StyledPanel) + self.frame_2.setFrameShadow(QFrame.Plain) + self.frame_2.setLineWidth(1) + self.frame_2.setMidLineWidth(1) + self.horizontalLayout_23 = QHBoxLayout(self.frame_2) + self.horizontalLayout_23.setObjectName(u"horizontalLayout_23") + self.gridLayoutDirections_2 = QGridLayout() + self.gridLayoutDirections_2.setObjectName(u"gridLayoutDirections_2") + self.gridLayoutDirections_2.setSizeConstraint(QLayout.SetFixedSize) + self.gridLayoutDirections_2.setContentsMargins(0, 0, 0, 0) + self.jog_layout_2 = QGridLayout() + self.jog_layout_2.setObjectName(u"jog_layout_2") + self.gridLayout_23 = QGridLayout() + self.gridLayout_23.setObjectName(u"gridLayout_23") + self.gridLayout_23.setSizeConstraint(QLayout.SetDefaultConstraint) + self.z_plus_pb_2 = QPushButton(self.frame_2) + self.z_plus_pb_2.setObjectName(u"z_plus_pb_2") + sizePolicy3.setHeightForWidth(self.z_plus_pb_2.sizePolicy().hasHeightForWidth()) + self.z_plus_pb_2.setSizePolicy(sizePolicy3) + self.z_plus_pb_2.setMinimumSize(QSize(0, 24)) + self.z_plus_pb_2.setMaximumSize(QSize(100, 16777215)) + self.z_plus_pb_2.setIcon(icon5) + + self.gridLayout_23.addWidget(self.z_plus_pb_2, 0, 0, 1, 1) + + self.z_minus_pb_2 = QPushButton(self.frame_2) + self.z_minus_pb_2.setObjectName(u"z_minus_pb_2") + sizePolicy3.setHeightForWidth(self.z_minus_pb_2.sizePolicy().hasHeightForWidth()) + self.z_minus_pb_2.setSizePolicy(sizePolicy3) + self.z_minus_pb_2.setMinimumSize(QSize(0, 24)) + self.z_minus_pb_2.setMaximumSize(QSize(100, 16777215)) + self.z_minus_pb_2.setIcon(icon6) + + self.gridLayout_23.addWidget(self.z_minus_pb_2, 1, 0, 1, 1) + + + self.jog_layout_2.addLayout(self.gridLayout_23, 2, 0, 1, 1) + + self.gridLayoutDirections_5 = QGridLayout() + self.gridLayoutDirections_5.setObjectName(u"gridLayoutDirections_5") + self.gridLayoutDirections_5.setContentsMargins(0, 0, 0, 0) + self.x_minus_y_plus_pb_2 = QToolButton(self.frame_2) + self.x_minus_y_plus_pb_2.setObjectName(u"x_minus_y_plus_pb_2") + sizePolicy3.setHeightForWidth(self.x_minus_y_plus_pb_2.sizePolicy().hasHeightForWidth()) + self.x_minus_y_plus_pb_2.setSizePolicy(sizePolicy3) + self.x_minus_y_plus_pb_2.setMinimumSize(QSize(0, 22)) + self.x_minus_y_plus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.x_minus_y_plus_pb_2.setIcon(icon7) + + self.gridLayoutDirections_5.addWidget(self.x_minus_y_plus_pb_2, 0, 0, 1, 1) + + self.x_plus_y_minus_pb_2 = QToolButton(self.frame_2) + self.x_plus_y_minus_pb_2.setObjectName(u"x_plus_y_minus_pb_2") + sizePolicy3.setHeightForWidth(self.x_plus_y_minus_pb_2.sizePolicy().hasHeightForWidth()) + self.x_plus_y_minus_pb_2.setSizePolicy(sizePolicy3) + self.x_plus_y_minus_pb_2.setMinimumSize(QSize(0, 22)) + self.x_plus_y_minus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.x_plus_y_minus_pb_2.setIcon(icon8) + + self.gridLayoutDirections_5.addWidget(self.x_plus_y_minus_pb_2, 2, 2, 1, 1) + + self.x_minus_pb_2 = QToolButton(self.frame_2) + self.x_minus_pb_2.setObjectName(u"x_minus_pb_2") + sizePolicy3.setHeightForWidth(self.x_minus_pb_2.sizePolicy().hasHeightForWidth()) + self.x_minus_pb_2.setSizePolicy(sizePolicy3) + self.x_minus_pb_2.setMinimumSize(QSize(0, 22)) + self.x_minus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.x_minus_pb_2.setIcon(icon9) + + self.gridLayoutDirections_5.addWidget(self.x_minus_pb_2, 1, 0, 1, 1) + + self.x_minus_y_minus_pb_2 = QToolButton(self.frame_2) + self.x_minus_y_minus_pb_2.setObjectName(u"x_minus_y_minus_pb_2") + sizePolicy3.setHeightForWidth(self.x_minus_y_minus_pb_2.sizePolicy().hasHeightForWidth()) + self.x_minus_y_minus_pb_2.setSizePolicy(sizePolicy3) + self.x_minus_y_minus_pb_2.setMinimumSize(QSize(0, 22)) + self.x_minus_y_minus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.x_minus_y_minus_pb_2.setIcon(icon10) + + self.gridLayoutDirections_5.addWidget(self.x_minus_y_minus_pb_2, 2, 0, 1, 1) + + self.y_plus_pb_2 = QToolButton(self.frame_2) + self.y_plus_pb_2.setObjectName(u"y_plus_pb_2") + sizePolicy3.setHeightForWidth(self.y_plus_pb_2.sizePolicy().hasHeightForWidth()) + self.y_plus_pb_2.setSizePolicy(sizePolicy3) + self.y_plus_pb_2.setMinimumSize(QSize(0, 22)) + self.y_plus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.y_plus_pb_2.setIcon(icon5) + + self.gridLayoutDirections_5.addWidget(self.y_plus_pb_2, 0, 1, 1, 1) + + self.center_tb_2 = QToolButton(self.frame_2) + self.center_tb_2.setObjectName(u"center_tb_2") + sizePolicy3.setHeightForWidth(self.center_tb_2.sizePolicy().hasHeightForWidth()) + self.center_tb_2.setSizePolicy(sizePolicy3) + self.center_tb_2.setMinimumSize(QSize(0, 22)) + self.center_tb_2.setMaximumSize(QSize(50, 16777215)) + self.center_tb_2.setIcon(icon11) + + self.gridLayoutDirections_5.addWidget(self.center_tb_2, 1, 1, 1, 1) + + self.y_minus_pb_2 = QToolButton(self.frame_2) + self.y_minus_pb_2.setObjectName(u"y_minus_pb_2") + sizePolicy3.setHeightForWidth(self.y_minus_pb_2.sizePolicy().hasHeightForWidth()) + self.y_minus_pb_2.setSizePolicy(sizePolicy3) + self.y_minus_pb_2.setMinimumSize(QSize(0, 22)) + self.y_minus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.y_minus_pb_2.setIcon(icon6) + + self.gridLayoutDirections_5.addWidget(self.y_minus_pb_2, 2, 1, 1, 1) + + self.x_plus_y_plus_pb_2 = QToolButton(self.frame_2) + self.x_plus_y_plus_pb_2.setObjectName(u"x_plus_y_plus_pb_2") + sizePolicy3.setHeightForWidth(self.x_plus_y_plus_pb_2.sizePolicy().hasHeightForWidth()) + self.x_plus_y_plus_pb_2.setSizePolicy(sizePolicy3) + self.x_plus_y_plus_pb_2.setMinimumSize(QSize(0, 22)) + self.x_plus_y_plus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.x_plus_y_plus_pb_2.setIcon(icon12) + + self.gridLayoutDirections_5.addWidget(self.x_plus_y_plus_pb_2, 0, 2, 1, 1) + + self.x_plus_pb_2 = QToolButton(self.frame_2) + self.x_plus_pb_2.setObjectName(u"x_plus_pb_2") + sizePolicy3.setHeightForWidth(self.x_plus_pb_2.sizePolicy().hasHeightForWidth()) + self.x_plus_pb_2.setSizePolicy(sizePolicy3) + self.x_plus_pb_2.setMinimumSize(QSize(0, 22)) + self.x_plus_pb_2.setMaximumSize(QSize(50, 16777215)) + self.x_plus_pb_2.setIcon(icon13) + + self.gridLayoutDirections_5.addWidget(self.x_plus_pb_2, 1, 2, 1, 1) + + + self.jog_layout_2.addLayout(self.gridLayoutDirections_5, 0, 0, 1, 1) + + self.verticalLayout_19 = QVBoxLayout() + self.verticalLayout_19.setObjectName(u"verticalLayout_19") + self.horizontalLayout_26 = QHBoxLayout() + self.horizontalLayout_26.setObjectName(u"horizontalLayout_26") + self.horizontalLayout_26.setSizeConstraint(QLayout.SetDefaultConstraint) + self.z_jog_l_4 = QLabel(self.frame_2) + self.z_jog_l_4.setObjectName(u"z_jog_l_4") + sizePolicy3.setHeightForWidth(self.z_jog_l_4.sizePolicy().hasHeightForWidth()) + self.z_jog_l_4.setSizePolicy(sizePolicy3) + self.z_jog_l_4.setMinimumSize(QSize(0, 20)) + self.z_jog_l_4.setMaximumSize(QSize(16777215, 23)) + self.z_jog_l_4.setFont(font) + self.z_jog_l_4.setAlignment(Qt.AlignCenter) + + self.horizontalLayout_26.addWidget(self.z_jog_l_4, 0, Qt.AlignHCenter|Qt.AlignVCenter) + + self.z_step_cb_2 = QComboBox(self.frame_2) + self.z_step_cb_2.addItem("") + self.z_step_cb_2.addItem("") + self.z_step_cb_2.addItem("") + self.z_step_cb_2.addItem("") + self.z_step_cb_2.addItem("") + self.z_step_cb_2.addItem("") + self.z_step_cb_2.addItem("") + self.z_step_cb_2.addItem("") + self.z_step_cb_2.setObjectName(u"z_step_cb_2") + sizePolicy3.setHeightForWidth(self.z_step_cb_2.sizePolicy().hasHeightForWidth()) + self.z_step_cb_2.setSizePolicy(sizePolicy3) + self.z_step_cb_2.setMinimumSize(QSize(75, 20)) + self.z_step_cb_2.setMaximumSize(QSize(75, 16777215)) + self.z_step_cb_2.setFont(font) + + self.horizontalLayout_26.addWidget(self.z_step_cb_2, 0, Qt.AlignHCenter|Qt.AlignVCenter) + + + self.verticalLayout_19.addLayout(self.horizontalLayout_26) + + self.gridLayout_25 = QGridLayout() + self.gridLayout_25.setObjectName(u"gridLayout_25") + self.z_step_val_dsb_2 = QDoubleSpinBox(self.frame_2) + self.z_step_val_dsb_2.setObjectName(u"z_step_val_dsb_2") + self.z_step_val_dsb_2.setMinimumSize(QSize(70, 20)) + self.z_step_val_dsb_2.setMaximumSize(QSize(70, 16777215)) + self.z_step_val_dsb_2.setFont(font) + self.z_step_val_dsb_2.setAlignment(Qt.AlignCenter) + self.z_step_val_dsb_2.setButtonSymbols(QAbstractSpinBox.NoButtons) + self.z_step_val_dsb_2.setMinimum(0.010000000000000) + self.z_step_val_dsb_2.setMaximum(1000.000000000000000) + self.z_step_val_dsb_2.setSingleStep(0.100000000000000) + self.z_step_val_dsb_2.setValue(0.100000000000000) + + self.gridLayout_25.addWidget(self.z_step_val_dsb_2, 1, 1, 1, 1) + + self.z_mul_10_pb_2 = QPushButton(self.frame_2) + self.z_mul_10_pb_2.setObjectName(u"z_mul_10_pb_2") + sizePolicy3.setHeightForWidth(self.z_mul_10_pb_2.sizePolicy().hasHeightForWidth()) + self.z_mul_10_pb_2.setSizePolicy(sizePolicy3) + self.z_mul_10_pb_2.setMinimumSize(QSize(0, 23)) + self.z_mul_10_pb_2.setMaximumSize(QSize(50, 16777215)) + self.z_mul_10_pb_2.setFont(font1) + self.z_mul_10_pb_2.setAutoRepeat(False) + + self.gridLayout_25.addWidget(self.z_mul_10_pb_2, 1, 2, 1, 1) + + self.z_div_10_pb_2 = QPushButton(self.frame_2) + self.z_div_10_pb_2.setObjectName(u"z_div_10_pb_2") + sizePolicy3.setHeightForWidth(self.z_div_10_pb_2.sizePolicy().hasHeightForWidth()) + self.z_div_10_pb_2.setSizePolicy(sizePolicy3) + self.z_div_10_pb_2.setMinimumSize(QSize(0, 23)) + self.z_div_10_pb_2.setMaximumSize(QSize(50, 16777215)) + self.z_div_10_pb_2.setFont(font) + self.z_div_10_pb_2.setAutoRepeat(False) + + self.gridLayout_25.addWidget(self.z_div_10_pb_2, 1, 0, 1, 1) + + self.z_minus_1_pb_2 = QPushButton(self.frame_2) + self.z_minus_1_pb_2.setObjectName(u"z_minus_1_pb_2") + sizePolicy3.setHeightForWidth(self.z_minus_1_pb_2.sizePolicy().hasHeightForWidth()) + self.z_minus_1_pb_2.setSizePolicy(sizePolicy3) + self.z_minus_1_pb_2.setMinimumSize(QSize(70, 23)) + self.z_minus_1_pb_2.setMaximumSize(QSize(70, 16777215)) + self.z_minus_1_pb_2.setFont(font) + self.z_minus_1_pb_2.setAutoRepeat(True) + + self.gridLayout_25.addWidget(self.z_minus_1_pb_2, 2, 1, 1, 1) + + self.z_plus_1_pb_2 = QPushButton(self.frame_2) + self.z_plus_1_pb_2.setObjectName(u"z_plus_1_pb_2") + sizePolicy3.setHeightForWidth(self.z_plus_1_pb_2.sizePolicy().hasHeightForWidth()) + self.z_plus_1_pb_2.setSizePolicy(sizePolicy3) + self.z_plus_1_pb_2.setMinimumSize(QSize(70, 23)) + self.z_plus_1_pb_2.setMaximumSize(QSize(70, 16777215)) + self.z_plus_1_pb_2.setFont(font) + self.z_plus_1_pb_2.setAutoRepeat(True) + + self.gridLayout_25.addWidget(self.z_plus_1_pb_2, 0, 1, 1, 1) + + + self.verticalLayout_19.addLayout(self.gridLayout_25) + + + self.jog_layout_2.addLayout(self.verticalLayout_19, 2, 1, 1, 1) + + self.verticalLayout_20 = QVBoxLayout() + self.verticalLayout_20.setObjectName(u"verticalLayout_20") + self.horizontalLayout_27 = QHBoxLayout() + self.horizontalLayout_27.setObjectName(u"horizontalLayout_27") + self.horizontalLayout_27.setSizeConstraint(QLayout.SetDefaultConstraint) + self.xy_jog_l_2 = QLabel(self.frame_2) + self.xy_jog_l_2.setObjectName(u"xy_jog_l_2") + sizePolicy3.setHeightForWidth(self.xy_jog_l_2.sizePolicy().hasHeightForWidth()) + self.xy_jog_l_2.setSizePolicy(sizePolicy3) + self.xy_jog_l_2.setMinimumSize(QSize(0, 0)) + self.xy_jog_l_2.setMaximumSize(QSize(16777215, 23)) + self.xy_jog_l_2.setAlignment(Qt.AlignCenter) + + self.horizontalLayout_27.addWidget(self.xy_jog_l_2, 0, Qt.AlignHCenter|Qt.AlignVCenter) + + self.xy_step_cb_2 = QComboBox(self.frame_2) + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.addItem("") + self.xy_step_cb_2.setObjectName(u"xy_step_cb_2") + sizePolicy3.setHeightForWidth(self.xy_step_cb_2.sizePolicy().hasHeightForWidth()) + self.xy_step_cb_2.setSizePolicy(sizePolicy3) + self.xy_step_cb_2.setMinimumSize(QSize(75, 0)) + self.xy_step_cb_2.setMaximumSize(QSize(75, 23)) + + self.horizontalLayout_27.addWidget(self.xy_step_cb_2, 0, Qt.AlignHCenter|Qt.AlignVCenter) + + + self.verticalLayout_20.addLayout(self.horizontalLayout_27) + + self.gridLayout_29 = QGridLayout() + self.gridLayout_29.setObjectName(u"gridLayout_29") + self.xy_plus_1_pb_2 = QPushButton(self.frame_2) + self.xy_plus_1_pb_2.setObjectName(u"xy_plus_1_pb_2") + sizePolicy3.setHeightForWidth(self.xy_plus_1_pb_2.sizePolicy().hasHeightForWidth()) + self.xy_plus_1_pb_2.setSizePolicy(sizePolicy3) + self.xy_plus_1_pb_2.setMinimumSize(QSize(70, 20)) + self.xy_plus_1_pb_2.setMaximumSize(QSize(70, 23)) + self.xy_plus_1_pb_2.setFont(font) + self.xy_plus_1_pb_2.setAutoRepeat(True) + + self.gridLayout_29.addWidget(self.xy_plus_1_pb_2, 0, 1, 1, 1) + + self.xy_div_10_pb_2 = QPushButton(self.frame_2) + self.xy_div_10_pb_2.setObjectName(u"xy_div_10_pb_2") + sizePolicy3.setHeightForWidth(self.xy_div_10_pb_2.sizePolicy().hasHeightForWidth()) + self.xy_div_10_pb_2.setSizePolicy(sizePolicy3) + self.xy_div_10_pb_2.setMinimumSize(QSize(50, 23)) + self.xy_div_10_pb_2.setMaximumSize(QSize(50, 23)) + self.xy_div_10_pb_2.setFont(font) + self.xy_div_10_pb_2.setAutoRepeat(False) + + self.gridLayout_29.addWidget(self.xy_div_10_pb_2, 1, 0, 1, 1) + + self.xy_step_val_dsb_2 = QDoubleSpinBox(self.frame_2) + self.xy_step_val_dsb_2.setObjectName(u"xy_step_val_dsb_2") + sizePolicy3.setHeightForWidth(self.xy_step_val_dsb_2.sizePolicy().hasHeightForWidth()) + self.xy_step_val_dsb_2.setSizePolicy(sizePolicy3) + self.xy_step_val_dsb_2.setMinimumSize(QSize(70, 23)) + self.xy_step_val_dsb_2.setMaximumSize(QSize(70, 23)) + self.xy_step_val_dsb_2.setFont(font) + self.xy_step_val_dsb_2.setAlignment(Qt.AlignCenter) + self.xy_step_val_dsb_2.setButtonSymbols(QAbstractSpinBox.NoButtons) + self.xy_step_val_dsb_2.setMinimum(0.010000000000000) + self.xy_step_val_dsb_2.setMaximum(1000.000000000000000) + self.xy_step_val_dsb_2.setSingleStep(0.100000000000000) + self.xy_step_val_dsb_2.setValue(0.100000000000000) + + self.gridLayout_29.addWidget(self.xy_step_val_dsb_2, 1, 1, 1, 1) + + self.xy_mul_10_pb_2 = QPushButton(self.frame_2) + self.xy_mul_10_pb_2.setObjectName(u"xy_mul_10_pb_2") + sizePolicy3.setHeightForWidth(self.xy_mul_10_pb_2.sizePolicy().hasHeightForWidth()) + self.xy_mul_10_pb_2.setSizePolicy(sizePolicy3) + self.xy_mul_10_pb_2.setMinimumSize(QSize(50, 23)) + self.xy_mul_10_pb_2.setMaximumSize(QSize(50, 23)) + self.xy_mul_10_pb_2.setFont(font1) + self.xy_mul_10_pb_2.setAutoRepeat(False) + + self.gridLayout_29.addWidget(self.xy_mul_10_pb_2, 1, 2, 1, 1) + + self.xy_minus_1_pb_2 = QPushButton(self.frame_2) + self.xy_minus_1_pb_2.setObjectName(u"xy_minus_1_pb_2") + sizePolicy3.setHeightForWidth(self.xy_minus_1_pb_2.sizePolicy().hasHeightForWidth()) + self.xy_minus_1_pb_2.setSizePolicy(sizePolicy3) + self.xy_minus_1_pb_2.setMinimumSize(QSize(70, 23)) + self.xy_minus_1_pb_2.setMaximumSize(QSize(70, 23)) + self.xy_minus_1_pb_2.setFont(font) + self.xy_minus_1_pb_2.setAutoRepeat(True) + + self.gridLayout_29.addWidget(self.xy_minus_1_pb_2, 2, 1, 1, 1) + + + self.verticalLayout_20.addLayout(self.gridLayout_29) + + + self.jog_layout_2.addLayout(self.verticalLayout_20, 0, 1, 1, 1) + + self.line_25 = QFrame(self.frame_2) + self.line_25.setObjectName(u"line_25") + self.line_25.setLineWidth(1) + self.line_25.setFrameShape(QFrame.HLine) + self.line_25.setFrameShadow(QFrame.Sunken) + + self.jog_layout_2.addWidget(self.line_25, 1, 1, 1, 1) + + self.line_26 = QFrame(self.frame_2) + self.line_26.setObjectName(u"line_26") + self.line_26.setFrameShape(QFrame.HLine) + self.line_26.setFrameShadow(QFrame.Sunken) + + self.jog_layout_2.addWidget(self.line_26, 1, 0, 1, 1) + + + self.gridLayoutDirections_2.addLayout(self.jog_layout_2, 1, 0, 1, 1) + + self.droGridLayout_alignment = QGridLayout() + self.droGridLayout_alignment.setObjectName(u"droGridLayout_alignment") + self.droGridLayout_alignment.setHorizontalSpacing(0) + self.droGridLayout_alignment.setVerticalSpacing(2) + self.droGridLayout_alignment.setContentsMargins(0, 0, 0, 0) + self.z_axis_l_2 = QLabel(self.frame_2) + self.z_axis_l_2.setObjectName(u"z_axis_l_2") + sizePolicy7.setHeightForWidth(self.z_axis_l_2.sizePolicy().hasHeightForWidth()) + self.z_axis_l_2.setSizePolicy(sizePolicy7) + self.z_axis_l_2.setMinimumSize(QSize(0, 12)) + self.z_axis_l_2.setMaximumSize(QSize(16777215, 13)) + self.z_axis_l_2.setFont(font) + self.z_axis_l_2.setLayoutDirection(Qt.LeftToRight) + self.z_axis_l_2.setFrameShape(QFrame.NoFrame) + self.z_axis_l_2.setFrameShadow(QFrame.Plain) + self.z_axis_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.z_axis_l_2, 0, 3, 1, 1, Qt.AlignHCenter) + + self.mpos_y_l_2 = QLabel(self.frame_2) + self.mpos_y_l_2.setObjectName(u"mpos_y_l_2") + sizePolicy7.setHeightForWidth(self.mpos_y_l_2.sizePolicy().hasHeightForWidth()) + self.mpos_y_l_2.setSizePolicy(sizePolicy7) + self.mpos_y_l_2.setMinimumSize(QSize(0, 12)) + self.mpos_y_l_2.setMaximumSize(QSize(16777215, 13)) + self.mpos_y_l_2.setLayoutDirection(Qt.LeftToRight) + self.mpos_y_l_2.setFrameShape(QFrame.NoFrame) + self.mpos_y_l_2.setFrameShadow(QFrame.Plain) + self.mpos_y_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.mpos_y_l_2, 1, 2, 1, 1, Qt.AlignHCenter) + + self.x_axis_l_2 = QLabel(self.frame_2) + self.x_axis_l_2.setObjectName(u"x_axis_l_2") + sizePolicy7.setHeightForWidth(self.x_axis_l_2.sizePolicy().hasHeightForWidth()) + self.x_axis_l_2.setSizePolicy(sizePolicy7) + self.x_axis_l_2.setMinimumSize(QSize(0, 12)) + self.x_axis_l_2.setMaximumSize(QSize(16777215, 13)) + self.x_axis_l_2.setFont(font) + self.x_axis_l_2.setLayoutDirection(Qt.LeftToRight) + self.x_axis_l_2.setFrameShape(QFrame.NoFrame) + self.x_axis_l_2.setFrameShadow(QFrame.Plain) + self.x_axis_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.x_axis_l_2, 0, 1, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + + self.mpos_z_l_2 = QLabel(self.frame_2) + self.mpos_z_l_2.setObjectName(u"mpos_z_l_2") + sizePolicy7.setHeightForWidth(self.mpos_z_l_2.sizePolicy().hasHeightForWidth()) + self.mpos_z_l_2.setSizePolicy(sizePolicy7) + self.mpos_z_l_2.setMinimumSize(QSize(0, 12)) + self.mpos_z_l_2.setMaximumSize(QSize(16777215, 13)) + self.mpos_z_l_2.setLayoutDirection(Qt.LeftToRight) + self.mpos_z_l_2.setFrameShape(QFrame.NoFrame) + self.mpos_z_l_2.setFrameShadow(QFrame.Plain) + self.mpos_z_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.mpos_z_l_2, 1, 3, 1, 1, Qt.AlignHCenter) + + self.mpos_x_l_2 = QLabel(self.frame_2) + self.mpos_x_l_2.setObjectName(u"mpos_x_l_2") + sizePolicy7.setHeightForWidth(self.mpos_x_l_2.sizePolicy().hasHeightForWidth()) + self.mpos_x_l_2.setSizePolicy(sizePolicy7) + self.mpos_x_l_2.setMinimumSize(QSize(0, 12)) + self.mpos_x_l_2.setMaximumSize(QSize(16777215, 13)) + self.mpos_x_l_2.setLayoutDirection(Qt.LeftToRight) + self.mpos_x_l_2.setFrameShape(QFrame.NoFrame) + self.mpos_x_l_2.setFrameShadow(QFrame.Plain) + self.mpos_x_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.mpos_x_l_2, 1, 1, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + + self.wpos_l_2 = QLabel(self.frame_2) + self.wpos_l_2.setObjectName(u"wpos_l_2") + sizePolicy7.setHeightForWidth(self.wpos_l_2.sizePolicy().hasHeightForWidth()) + self.wpos_l_2.setSizePolicy(sizePolicy7) + self.wpos_l_2.setMinimumSize(QSize(0, 12)) + self.wpos_l_2.setMaximumSize(QSize(16777215, 13)) + self.wpos_l_2.setFont(font) + self.wpos_l_2.setLayoutDirection(Qt.LeftToRight) + self.wpos_l_2.setFrameShape(QFrame.NoFrame) + self.wpos_l_2.setFrameShadow(QFrame.Plain) + self.wpos_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.wpos_l_2, 2, 0, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + + self.wpos_x_l_2 = QLabel(self.frame_2) + self.wpos_x_l_2.setObjectName(u"wpos_x_l_2") + sizePolicy7.setHeightForWidth(self.wpos_x_l_2.sizePolicy().hasHeightForWidth()) + self.wpos_x_l_2.setSizePolicy(sizePolicy7) + self.wpos_x_l_2.setMinimumSize(QSize(0, 12)) + self.wpos_x_l_2.setMaximumSize(QSize(16777215, 13)) + self.wpos_x_l_2.setLayoutDirection(Qt.LeftToRight) + self.wpos_x_l_2.setFrameShape(QFrame.NoFrame) + self.wpos_x_l_2.setFrameShadow(QFrame.Plain) + self.wpos_x_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.wpos_x_l_2, 2, 1, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + + self.mpos_l_2 = QLabel(self.frame_2) + self.mpos_l_2.setObjectName(u"mpos_l_2") + sizePolicy7.setHeightForWidth(self.mpos_l_2.sizePolicy().hasHeightForWidth()) + self.mpos_l_2.setSizePolicy(sizePolicy7) + self.mpos_l_2.setMinimumSize(QSize(0, 12)) + self.mpos_l_2.setMaximumSize(QSize(16777215, 13)) + self.mpos_l_2.setFont(font) + self.mpos_l_2.setLayoutDirection(Qt.LeftToRight) + self.mpos_l_2.setFrameShape(QFrame.NoFrame) + self.mpos_l_2.setFrameShadow(QFrame.Plain) + self.mpos_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.mpos_l_2, 1, 0, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + + self.wpos_z_l_2 = QLabel(self.frame_2) + self.wpos_z_l_2.setObjectName(u"wpos_z_l_2") + sizePolicy7.setHeightForWidth(self.wpos_z_l_2.sizePolicy().hasHeightForWidth()) + self.wpos_z_l_2.setSizePolicy(sizePolicy7) + self.wpos_z_l_2.setMinimumSize(QSize(0, 12)) + self.wpos_z_l_2.setMaximumSize(QSize(16777215, 13)) + self.wpos_z_l_2.setLayoutDirection(Qt.LeftToRight) + self.wpos_z_l_2.setFrameShape(QFrame.NoFrame) + self.wpos_z_l_2.setFrameShadow(QFrame.Plain) + self.wpos_z_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.wpos_z_l_2, 2, 3, 1, 1, Qt.AlignHCenter) + + self.axis_l_2 = QLabel(self.frame_2) + self.axis_l_2.setObjectName(u"axis_l_2") + sizePolicy7.setHeightForWidth(self.axis_l_2.sizePolicy().hasHeightForWidth()) + self.axis_l_2.setSizePolicy(sizePolicy7) + self.axis_l_2.setMinimumSize(QSize(0, 12)) + self.axis_l_2.setMaximumSize(QSize(16777215, 13)) + self.axis_l_2.setFont(font) + self.axis_l_2.setLayoutDirection(Qt.LeftToRight) + self.axis_l_2.setFrameShape(QFrame.NoFrame) + self.axis_l_2.setFrameShadow(QFrame.Plain) + self.axis_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.axis_l_2, 0, 0, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + + self.y_axis_l_2 = QLabel(self.frame_2) + self.y_axis_l_2.setObjectName(u"y_axis_l_2") + sizePolicy7.setHeightForWidth(self.y_axis_l_2.sizePolicy().hasHeightForWidth()) + self.y_axis_l_2.setSizePolicy(sizePolicy7) + self.y_axis_l_2.setMinimumSize(QSize(0, 12)) + self.y_axis_l_2.setMaximumSize(QSize(16777215, 13)) + self.y_axis_l_2.setFont(font) + self.y_axis_l_2.setLayoutDirection(Qt.LeftToRight) + self.y_axis_l_2.setFrameShape(QFrame.NoFrame) + self.y_axis_l_2.setFrameShadow(QFrame.Plain) + self.y_axis_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.y_axis_l_2, 0, 2, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + + self.wpos_y_l_2 = QLabel(self.frame_2) + self.wpos_y_l_2.setObjectName(u"wpos_y_l_2") + sizePolicy7.setHeightForWidth(self.wpos_y_l_2.sizePolicy().hasHeightForWidth()) + self.wpos_y_l_2.setSizePolicy(sizePolicy7) + self.wpos_y_l_2.setMinimumSize(QSize(0, 12)) + self.wpos_y_l_2.setMaximumSize(QSize(16777215, 13)) + self.wpos_y_l_2.setLayoutDirection(Qt.LeftToRight) + self.wpos_y_l_2.setFrameShape(QFrame.NoFrame) + self.wpos_y_l_2.setFrameShadow(QFrame.Plain) + self.wpos_y_l_2.setAlignment(Qt.AlignCenter) + + self.droGridLayout_alignment.addWidget(self.wpos_y_l_2, 2, 2, 1, 1, Qt.AlignHCenter) + + + self.gridLayoutDirections_2.addLayout(self.droGridLayout_alignment, 0, 0, 1, 1) + + + self.horizontalLayout_23.addLayout(self.gridLayoutDirections_2) + + + self.verticalLayout_14.addWidget(self.frame_2) + + self.verticalSpacer_9 = QSpacerItem(20, 26, QSizePolicy.Minimum, QSizePolicy.Fixed) + + self.verticalLayout_14.addItem(self.verticalSpacer_9) + + + self.horizontalLayout_18.addLayout(self.verticalLayout_14) + + self.verticalLayout_16 = QVBoxLayout() + self.verticalLayout_16.setObjectName(u"verticalLayout_16") + self.alignCanvasWidget = VispyCanvas(self.align_tab) + self.alignCanvasWidget.setObjectName(u"alignCanvasWidget") + + self.verticalLayout_16.addWidget(self.alignCanvasWidget) + + self.horizontalLayout_28 = QHBoxLayout() + self.horizontalLayout_28.setObjectName(u"horizontalLayout_28") + self.flip_horizontally_tb = QToolButton(self.align_tab) + self.flip_horizontally_tb.setObjectName(u"flip_horizontally_tb") + self.flip_horizontally_tb.setMinimumSize(QSize(0, 20)) + self.flip_horizontally_tb.setMaximumSize(QSize(16777215, 20)) + self.flip_horizontally_tb.setCheckable(True) + self.flip_horizontally_tb.setToolButtonStyle(Qt.ToolButtonTextOnly) + + self.horizontalLayout_28.addWidget(self.flip_horizontally_tb) + + self.flip_vertically_tb = QToolButton(self.align_tab) + self.flip_vertically_tb.setObjectName(u"flip_vertically_tb") + self.flip_vertically_tb.setMinimumSize(QSize(0, 20)) + self.flip_vertically_tb.setMaximumSize(QSize(16777215, 20)) + self.flip_vertically_tb.setCheckable(True) + self.flip_vertically_tb.setToolButtonStyle(Qt.ToolButtonTextOnly) + + self.horizontalLayout_28.addWidget(self.flip_vertically_tb) + + self.horizontalSpacer_14 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout_28.addItem(self.horizontalSpacer_14) + + self.load_align_layer_tb = QToolButton(self.align_tab) + self.load_align_layer_tb.setObjectName(u"load_align_layer_tb") + self.load_align_layer_tb.setMinimumSize(QSize(0, 20)) + self.load_align_layer_tb.setMaximumSize(QSize(16777215, 20)) + + self.horizontalLayout_28.addWidget(self.load_align_layer_tb) + + + self.verticalLayout_16.addLayout(self.horizontalLayout_28) + + self.verticalLayout_16.setStretch(0, 10) + + self.horizontalLayout_18.addLayout(self.verticalLayout_16) + + self.verticalLayout_21 = QVBoxLayout() + self.verticalLayout_21.setObjectName(u"verticalLayout_21") + self.verticalLayout_22 = QVBoxLayout() + self.verticalLayout_22.setObjectName(u"verticalLayout_22") + self.align_points_tw = QTableWidget(self.align_tab) + if (self.align_points_tw.columnCount() < 4): + self.align_points_tw.setColumnCount(4) + self.align_points_tw.setObjectName(u"align_points_tw") + sizePolicy.setHeightForWidth(self.align_points_tw.sizePolicy().hasHeightForWidth()) + self.align_points_tw.setSizePolicy(sizePolicy) + self.align_points_tw.setMinimumSize(QSize(200, 0)) + self.align_points_tw.setMaximumSize(QSize(500, 16777215)) + self.align_points_tw.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) + self.align_points_tw.setColumnCount(4) + self.align_points_tw.horizontalHeader().setCascadingSectionResizes(False) + self.align_points_tw.horizontalHeader().setDefaultSectionSize(100) - self.horizontalLayout_7.addWidget(self.openGLWidget_2) + self.verticalLayout_22.addWidget(self.align_points_tw, 0, Qt.AlignHCenter) - self.label_2 = QLabel(self.align_tab) - self.label_2.setObjectName(u"label_2") + self.horizontalLayout_29 = QHBoxLayout() + self.horizontalLayout_29.setObjectName(u"horizontalLayout_29") + self.add_point_tb = QToolButton(self.align_tab) + self.add_point_tb.setObjectName(u"add_point_tb") + self.add_point_tb.setMinimumSize(QSize(50, 50)) + font3 = QFont() + font3.setPointSize(14) + font3.setBold(True) + font3.setWeight(75) + self.add_point_tb.setFont(font3) + icon22 = QIcon() + icon22.addFile(u":/resources/resources/icons/gray-refresh.svg", QSize(), QIcon.Normal, QIcon.Off) + self.add_point_tb.setIcon(icon22) + self.add_point_tb.setToolButtonStyle(Qt.ToolButtonTextOnly) + + self.horizontalLayout_29.addWidget(self.add_point_tb) + + self.remove_point_tb = QToolButton(self.align_tab) + self.remove_point_tb.setObjectName(u"remove_point_tb") + sizePolicy3.setHeightForWidth(self.remove_point_tb.sizePolicy().hasHeightForWidth()) + self.remove_point_tb.setSizePolicy(sizePolicy3) + self.remove_point_tb.setMinimumSize(QSize(50, 50)) + self.remove_point_tb.setFont(font3) + self.remove_point_tb.setToolButtonStyle(Qt.ToolButtonTextOnly) + + self.horizontalLayout_29.addWidget(self.remove_point_tb) + + self.horizontalSpacer_13 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout_29.addItem(self.horizontalSpacer_13) + + self.apply_alignment_tb = QToolButton(self.align_tab) + self.apply_alignment_tb.setObjectName(u"apply_alignment_tb") + self.apply_alignment_tb.setMinimumSize(QSize(50, 50)) + self.apply_alignment_tb.setIcon(icon14) + self.apply_alignment_tb.setCheckable(True) + self.apply_alignment_tb.setToolButtonStyle(Qt.ToolButtonIconOnly) + + self.horizontalLayout_29.addWidget(self.apply_alignment_tb) + + + self.verticalLayout_22.addLayout(self.horizontalLayout_29) + + + self.verticalLayout_21.addLayout(self.verticalLayout_22) + + self.horizontalLayout_30 = QHBoxLayout() + self.horizontalLayout_30.setObjectName(u"horizontalLayout_30") + self.label_17 = QLabel(self.align_tab) + self.label_17.setObjectName(u"label_17") + sizePolicy3.setHeightForWidth(self.label_17.sizePolicy().hasHeightForWidth()) + self.label_17.setSizePolicy(sizePolicy3) + self.label_17.setMinimumSize(QSize(0, 20)) + self.label_17.setMaximumSize(QSize(16777215, 20)) + self.label_17.setAlignment(Qt.AlignCenter) + + self.horizontalLayout_30.addWidget(self.label_17, 0, Qt.AlignHCenter|Qt.AlignVCenter) + + self.horizontalSpacer_15 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout_30.addItem(self.horizontalSpacer_15) - self.horizontalLayout_7.addWidget(self.label_2) + self.label_18 = QLabel(self.align_tab) + self.label_18.setObjectName(u"label_18") + sizePolicy14 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + sizePolicy14.setHorizontalStretch(0) + sizePolicy14.setVerticalStretch(0) + sizePolicy14.setHeightForWidth(self.label_18.sizePolicy().hasHeightForWidth()) + self.label_18.setSizePolicy(sizePolicy14) + self.label_18.setMinimumSize(QSize(0, 20)) + self.label_18.setMaximumSize(QSize(16777215, 20)) + self.label_18.setAlignment(Qt.AlignCenter) - self.verticalSlider = QSlider(self.align_tab) - self.verticalSlider.setObjectName(u"verticalSlider") - self.verticalSlider.setMaximum(255) - self.verticalSlider.setOrientation(Qt.Vertical) + self.horizontalLayout_30.addWidget(self.label_18, 0, Qt.AlignHCenter|Qt.AlignVCenter) - self.horizontalLayout_7.addWidget(self.verticalSlider) + + self.verticalLayout_21.addLayout(self.horizontalLayout_30) + + + self.horizontalLayout_18.addLayout(self.verticalLayout_21) + + self.horizontalLayout_18.setStretch(0, 3) + self.horizontalLayout_18.setStretch(1, 10) + self.horizontalLayout_18.setStretch(2, 3) + + self.horizontalLayout_17.addLayout(self.horizontalLayout_18) + + + self.horizontalLayout_7.addLayout(self.horizontalLayout_17) self.main_tab_widget.addTab(self.align_tab, "") self.settings_tab = QWidget() @@ -2643,9 +3434,11 @@ def setupUi(self, MainWindow): self.layer_colors_section_la.setSizePolicy(sizePolicy3) self.layer_colors_section_la.setMinimumSize(QSize(210, 0)) self.layer_colors_section_la.setMaximumSize(QSize(300, 20)) - font3 = QFont() - font3.setPointSize(12) - self.layer_colors_section_la.setFont(font3) + font4 = QFont() + font4.setPointSize(12) + font4.setBold(True) + font4.setWeight(75) + self.layer_colors_section_la.setFont(font4) self.layer_colors_section_la.setAlignment(Qt.AlignCenter) self.gridLayout_9.addWidget(self.layer_colors_section_la, 1, 0, 1, 1) @@ -2666,144 +3459,279 @@ def setupUi(self, MainWindow): self.jobs_machine_settings_tab.setObjectName(u"jobs_machine_settings_tab") self.gridLayout_13 = QGridLayout(self.jobs_machine_settings_tab) self.gridLayout_13.setObjectName(u"gridLayout_13") - self.verticalLayout_4 = QVBoxLayout() - self.verticalLayout_4.setSpacing(2) - self.verticalLayout_4.setObjectName(u"verticalLayout_4") - self.verticalLayout_4.setSizeConstraint(QLayout.SetFixedSize) - self.line_15 = QFrame(self.jobs_machine_settings_tab) - self.line_15.setObjectName(u"line_15") - self.line_15.setFrameShape(QFrame.HLine) - self.line_15.setFrameShadow(QFrame.Sunken) + self.gridLayout_20 = QGridLayout() + self.gridLayout_20.setObjectName(u"gridLayout_20") + self.gridLayout_20.setSizeConstraint(QLayout.SetFixedSize) + self.x_axis_la = QLabel(self.jobs_machine_settings_tab) + self.x_axis_la.setObjectName(u"x_axis_la") + sizePolicy3.setHeightForWidth(self.x_axis_la.sizePolicy().hasHeightForWidth()) + self.x_axis_la.setSizePolicy(sizePolicy3) + self.x_axis_la.setMinimumSize(QSize(150, 20)) + self.x_axis_la.setMaximumSize(QSize(150, 20)) + self.x_axis_la.setFont(font) + self.x_axis_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.verticalLayout_4.addWidget(self.line_15) + self.gridLayout_20.addWidget(self.x_axis_la, 0, 1, 1, 1, Qt.AlignHCenter) - self.probe_settings_section_la = QLabel(self.jobs_machine_settings_tab) - self.probe_settings_section_la.setObjectName(u"probe_settings_section_la") - sizePolicy3.setHeightForWidth(self.probe_settings_section_la.sizePolicy().hasHeightForWidth()) - self.probe_settings_section_la.setSizePolicy(sizePolicy3) - self.probe_settings_section_la.setFont(font3) + self.x_la_2 = QLabel(self.jobs_machine_settings_tab) + self.x_la_2.setObjectName(u"x_la_2") + sizePolicy3.setHeightForWidth(self.x_la_2.sizePolicy().hasHeightForWidth()) + self.x_la_2.setSizePolicy(sizePolicy3) + self.x_la_2.setMinimumSize(QSize(150, 20)) + self.x_la_2.setMaximumSize(QSize(150, 20)) + self.x_la_2.setFont(font) + self.x_la_2.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.verticalLayout_4.addWidget(self.probe_settings_section_la, 0, Qt.AlignHCenter) + self.gridLayout_20.addWidget(self.x_la_2, 0, 2, 1, 1, Qt.AlignHCenter) - self.line_16 = QFrame(self.jobs_machine_settings_tab) - self.line_16.setObjectName(u"line_16") - self.line_16.setFrameShape(QFrame.HLine) - self.line_16.setFrameShadow(QFrame.Sunken) + self.mirroring_axis_la = QLabel(self.jobs_machine_settings_tab) + self.mirroring_axis_la.setObjectName(u"mirroring_axis_la") + sizePolicy3.setHeightForWidth(self.mirroring_axis_la.sizePolicy().hasHeightForWidth()) + self.mirroring_axis_la.setSizePolicy(sizePolicy3) + self.mirroring_axis_la.setMinimumSize(QSize(130, 0)) + self.mirroring_axis_la.setMaximumSize(QSize(130, 16777215)) + self.mirroring_axis_la.setFont(font) + self.mirroring_axis_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.verticalLayout_4.addWidget(self.line_16) + self.gridLayout_20.addWidget(self.mirroring_axis_la, 1, 0, 1, 1, Qt.AlignLeft|Qt.AlignVCenter) - self.gridLayout_21 = QGridLayout() - self.gridLayout_21.setObjectName(u"gridLayout_21") - self.gridLayout_21.setHorizontalSpacing(0) - self.gridLayout_21.setVerticalSpacing(2) - self.horizontalSpacer_10 = QSpacerItem(180, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) + self.x_mirror_rb = QRadioButton(self.jobs_machine_settings_tab) + self.x_mirror_rb.setObjectName(u"x_mirror_rb") + sizePolicy3.setHeightForWidth(self.x_mirror_rb.sizePolicy().hasHeightForWidth()) + self.x_mirror_rb.setSizePolicy(sizePolicy3) + self.x_mirror_rb.setMaximumSize(QSize(120, 20)) - self.gridLayout_21.addItem(self.horizontalSpacer_10, 0, 0, 1, 1) + self.gridLayout_20.addWidget(self.x_mirror_rb, 1, 1, 1, 1, Qt.AlignHCenter) - self.hold_on_probe_chb = QCheckBox(self.jobs_machine_settings_tab) - self.hold_on_probe_chb.setObjectName(u"hold_on_probe_chb") - sizePolicy3.setHeightForWidth(self.hold_on_probe_chb.sizePolicy().hasHeightForWidth()) - self.hold_on_probe_chb.setSizePolicy(sizePolicy3) - self.hold_on_probe_chb.setMinimumSize(QSize(150, 0)) - self.hold_on_probe_chb.setMaximumSize(QSize(150, 16777215)) + self.y_mirror_rb = QRadioButton(self.jobs_machine_settings_tab) + self.y_mirror_rb.setObjectName(u"y_mirror_rb") + sizePolicy3.setHeightForWidth(self.y_mirror_rb.sizePolicy().hasHeightForWidth()) + self.y_mirror_rb.setSizePolicy(sizePolicy3) + self.y_mirror_rb.setMaximumSize(QSize(120, 20)) - self.gridLayout_21.addWidget(self.hold_on_probe_chb, 0, 1, 1, 1, Qt.AlignHCenter) + self.gridLayout_20.addWidget(self.y_mirror_rb, 1, 2, 1, 1, Qt.AlignHCenter) - self.zeroing_after_probe_chb = QCheckBox(self.jobs_machine_settings_tab) - self.zeroing_after_probe_chb.setObjectName(u"zeroing_after_probe_chb") - sizePolicy3.setHeightForWidth(self.zeroing_after_probe_chb.sizePolicy().hasHeightForWidth()) - self.zeroing_after_probe_chb.setSizePolicy(sizePolicy3) - self.zeroing_after_probe_chb.setMinimumSize(QSize(150, 0)) - self.zeroing_after_probe_chb.setMaximumSize(QSize(150, 16777215)) + self.horizontalSpacer_9 = QSpacerItem(130, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) - self.gridLayout_21.addWidget(self.zeroing_after_probe_chb, 0, 2, 1, 1, Qt.AlignHCenter) + self.gridLayout_20.addItem(self.horizontalSpacer_9, 0, 0, 1, 1) - self.verticalLayout_4.addLayout(self.gridLayout_21) + self.gridLayout_13.addLayout(self.gridLayout_20, 3, 0, 1, 1) + self.probe_settings_section_la = QLabel(self.jobs_machine_settings_tab) + self.probe_settings_section_la.setObjectName(u"probe_settings_section_la") + sizePolicy3.setHeightForWidth(self.probe_settings_section_la.sizePolicy().hasHeightForWidth()) + self.probe_settings_section_la.setSizePolicy(sizePolicy3) + self.probe_settings_section_la.setFont(font4) - self.gridLayout_13.addLayout(self.verticalLayout_4, 6, 0, 1, 1) + self.gridLayout_13.addWidget(self.probe_settings_section_la, 7, 0, 1, 1, Qt.AlignHCenter) - self.line_9 = QFrame(self.jobs_machine_settings_tab) - self.line_9.setObjectName(u"line_9") - self.line_9.setFrameShape(QFrame.HLine) - self.line_9.setFrameShadow(QFrame.Sunken) + self.verticalSpacer_6 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.gridLayout_13.addWidget(self.line_9, 14, 0, 1, 1) + self.gridLayout_13.addItem(self.verticalSpacer_6, 10, 0, 1, 1) - self.line_13 = QFrame(self.jobs_machine_settings_tab) - self.line_13.setObjectName(u"line_13") - self.line_13.setFrameShape(QFrame.HLine) - self.line_13.setFrameShadow(QFrame.Sunken) + self.verticalSpacer_8 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.gridLayout_13.addWidget(self.line_13, 4, 0, 1, 1) + self.gridLayout_13.addItem(self.verticalSpacer_8, 21, 0, 1, 1) - self.verticalLayout_5 = QVBoxLayout() - self.verticalLayout_5.setSpacing(2) - self.verticalLayout_5.setObjectName(u"verticalLayout_5") - self.verticalLayout_5.setSizeConstraint(QLayout.SetFixedSize) - self.horizontalLayout_13 = QHBoxLayout() - self.horizontalLayout_13.setObjectName(u"horizontalLayout_13") - self.gridLayout_14 = QGridLayout() - self.gridLayout_14.setObjectName(u"gridLayout_14") - self.gridLayout_14.setSizeConstraint(QLayout.SetFixedSize) - self.gridLayout_14.setVerticalSpacing(2) - self.tool_probe_y_wpos_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) - self.tool_probe_y_wpos_dsb.setObjectName(u"tool_probe_y_wpos_dsb") - sizePolicy3.setHeightForWidth(self.tool_probe_y_wpos_dsb.sizePolicy().hasHeightForWidth()) - self.tool_probe_y_wpos_dsb.setSizePolicy(sizePolicy3) - self.tool_probe_y_wpos_dsb.setMinimumSize(QSize(80, 20)) - self.tool_probe_y_wpos_dsb.setMaximumSize(QSize(80, 16777215)) - self.tool_probe_y_wpos_dsb.setFont(font) - self.tool_probe_y_wpos_dsb.setAlignment(Qt.AlignCenter) - self.tool_probe_y_wpos_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) - self.tool_probe_y_wpos_dsb.setMinimum(-1000.000000000000000) - self.tool_probe_y_wpos_dsb.setMaximum(1000.000000000000000) - self.tool_probe_y_wpos_dsb.setSingleStep(0.100000000000000) + self.line_10 = QFrame(self.jobs_machine_settings_tab) + self.line_10.setObjectName(u"line_10") + self.line_10.setFrameShape(QFrame.HLine) + self.line_10.setFrameShadow(QFrame.Sunken) - self.gridLayout_14.addWidget(self.tool_probe_y_wpos_dsb, 2, 2, 1, 1) + self.gridLayout_13.addWidget(self.line_10, 19, 0, 1, 1) - self.tool_probe_y_mpos_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) - self.tool_probe_y_mpos_dsb.setObjectName(u"tool_probe_y_mpos_dsb") - sizePolicy3.setHeightForWidth(self.tool_probe_y_mpos_dsb.sizePolicy().hasHeightForWidth()) - self.tool_probe_y_mpos_dsb.setSizePolicy(sizePolicy3) - self.tool_probe_y_mpos_dsb.setMinimumSize(QSize(80, 20)) - self.tool_probe_y_mpos_dsb.setMaximumSize(QSize(80, 16777215)) - self.tool_probe_y_mpos_dsb.setFont(font) - self.tool_probe_y_mpos_dsb.setAlignment(Qt.AlignCenter) - self.tool_probe_y_mpos_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) - self.tool_probe_y_mpos_dsb.setMinimum(-1000.000000000000000) - self.tool_probe_y_mpos_dsb.setMaximum(1000.000000000000000) - self.tool_probe_y_mpos_dsb.setSingleStep(0.100000000000000) + self.tool_change_section_la = QLabel(self.jobs_machine_settings_tab) + self.tool_change_section_la.setObjectName(u"tool_change_section_la") + sizePolicy3.setHeightForWidth(self.tool_change_section_la.sizePolicy().hasHeightForWidth()) + self.tool_change_section_la.setSizePolicy(sizePolicy3) + self.tool_change_section_la.setFont(font4) - self.gridLayout_14.addWidget(self.tool_probe_y_mpos_dsb, 1, 2, 1, 1) + self.gridLayout_13.addWidget(self.tool_change_section_la, 12, 0, 1, 1, Qt.AlignHCenter) - self.x_la = QLabel(self.jobs_machine_settings_tab) - self.x_la.setObjectName(u"x_la") - sizePolicy3.setHeightForWidth(self.x_la.sizePolicy().hasHeightForWidth()) - self.x_la.setSizePolicy(sizePolicy3) - self.x_la.setMaximumSize(QSize(80, 50)) - self.x_la.setFont(font) - self.x_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.verticalSpacer_5 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.gridLayout_14.addWidget(self.x_la, 0, 1, 1, 1, Qt.AlignHCenter) + self.gridLayout_13.addItem(self.verticalSpacer_5, 5, 0, 1, 1) - self.y_la = QLabel(self.jobs_machine_settings_tab) - self.y_la.setObjectName(u"y_la") - sizePolicy3.setHeightForWidth(self.y_la.sizePolicy().hasHeightForWidth()) - self.y_la.setSizePolicy(sizePolicy3) - self.y_la.setMaximumSize(QSize(80, 50)) - self.y_la.setFont(font) - self.y_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.jobs_common_settings_section_la = QLabel(self.jobs_machine_settings_tab) + self.jobs_common_settings_section_la.setObjectName(u"jobs_common_settings_section_la") + sizePolicy3.setHeightForWidth(self.jobs_common_settings_section_la.sizePolicy().hasHeightForWidth()) + self.jobs_common_settings_section_la.setSizePolicy(sizePolicy3) + self.jobs_common_settings_section_la.setMinimumSize(QSize(210, 0)) + self.jobs_common_settings_section_la.setMaximumSize(QSize(300, 20)) + self.jobs_common_settings_section_la.setFont(font4) - self.gridLayout_14.addWidget(self.y_la, 0, 2, 1, 1, Qt.AlignHCenter) + self.gridLayout_13.addWidget(self.jobs_common_settings_section_la, 1, 0, 1, 1, Qt.AlignHCenter) - self.tool_probe_z_limit_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) - self.tool_probe_z_limit_dsb.setObjectName(u"tool_probe_z_limit_dsb") - sizePolicy3.setHeightForWidth(self.tool_probe_z_limit_dsb.sizePolicy().hasHeightForWidth()) - self.tool_probe_z_limit_dsb.setSizePolicy(sizePolicy3) - self.tool_probe_z_limit_dsb.setMinimumSize(QSize(80, 20)) - self.tool_probe_z_limit_dsb.setMaximumSize(QSize(80, 16777215)) + self.line_16 = QFrame(self.jobs_machine_settings_tab) + self.line_16.setObjectName(u"line_16") + self.line_16.setFrameShape(QFrame.HLine) + self.line_16.setFrameShadow(QFrame.Sunken) + + self.gridLayout_13.addWidget(self.line_16, 6, 0, 1, 1) + + self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.gridLayout_13.addItem(self.horizontalSpacer_4, 14, 1, 1, 1) + + self.gridLayout_19 = QGridLayout() + self.gridLayout_19.setObjectName(u"gridLayout_19") + self.gridLayout_19.setVerticalSpacing(2) + self.feedrate_z_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) + self.feedrate_z_dsb.setObjectName(u"feedrate_z_dsb") + self.feedrate_z_dsb.setMinimumSize(QSize(252, 0)) + self.feedrate_z_dsb.setMaximumSize(QSize(252, 16777215)) + self.feedrate_z_dsb.setFont(font) + self.feedrate_z_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.feedrate_z_dsb.setAlignment(Qt.AlignCenter) + self.feedrate_z_dsb.setButtonSymbols(QAbstractSpinBox.UpDownArrows) + self.feedrate_z_dsb.setMaximum(100000.000000000000000) + self.feedrate_z_dsb.setSingleStep(1.000000000000000) + + self.gridLayout_19.addWidget(self.feedrate_z_dsb, 1, 1, 1, 1) + + self.z_feedrate_la = QLabel(self.jobs_machine_settings_tab) + self.z_feedrate_la.setObjectName(u"z_feedrate_la") + sizePolicy14.setHeightForWidth(self.z_feedrate_la.sizePolicy().hasHeightForWidth()) + self.z_feedrate_la.setSizePolicy(sizePolicy14) + self.z_feedrate_la.setMinimumSize(QSize(130, 0)) + self.z_feedrate_la.setMaximumSize(QSize(130, 16777215)) + self.z_feedrate_la.setFont(font) + self.z_feedrate_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + + self.gridLayout_19.addWidget(self.z_feedrate_la, 1, 0, 1, 1) + + self.xy_feedrate_la = QLabel(self.jobs_machine_settings_tab) + self.xy_feedrate_la.setObjectName(u"xy_feedrate_la") + sizePolicy3.setHeightForWidth(self.xy_feedrate_la.sizePolicy().hasHeightForWidth()) + self.xy_feedrate_la.setSizePolicy(sizePolicy3) + self.xy_feedrate_la.setMinimumSize(QSize(130, 0)) + self.xy_feedrate_la.setMaximumSize(QSize(130, 16777215)) + self.xy_feedrate_la.setFont(font) + self.xy_feedrate_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + + self.gridLayout_19.addWidget(self.xy_feedrate_la, 0, 0, 1, 1) + + self.feedrate_xy_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) + self.feedrate_xy_dsb.setObjectName(u"feedrate_xy_dsb") + sizePolicy3.setHeightForWidth(self.feedrate_xy_dsb.sizePolicy().hasHeightForWidth()) + self.feedrate_xy_dsb.setSizePolicy(sizePolicy3) + self.feedrate_xy_dsb.setMinimumSize(QSize(252, 0)) + self.feedrate_xy_dsb.setMaximumSize(QSize(252, 16777215)) + self.feedrate_xy_dsb.setFont(font) + self.feedrate_xy_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.feedrate_xy_dsb.setAlignment(Qt.AlignCenter) + self.feedrate_xy_dsb.setButtonSymbols(QAbstractSpinBox.UpDownArrows) + self.feedrate_xy_dsb.setMaximum(100000.000000000000000) + self.feedrate_xy_dsb.setSingleStep(1.000000000000000) + + self.gridLayout_19.addWidget(self.feedrate_xy_dsb, 0, 1, 1, 1) + + self.feedrate_probe_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) + self.feedrate_probe_dsb.setObjectName(u"feedrate_probe_dsb") + self.feedrate_probe_dsb.setMinimumSize(QSize(252, 0)) + self.feedrate_probe_dsb.setMaximumSize(QSize(252, 16777215)) + self.feedrate_probe_dsb.setFont(font) + self.feedrate_probe_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.feedrate_probe_dsb.setAlignment(Qt.AlignCenter) + self.feedrate_probe_dsb.setButtonSymbols(QAbstractSpinBox.UpDownArrows) + self.feedrate_probe_dsb.setMaximum(100000.000000000000000) + self.feedrate_probe_dsb.setSingleStep(1.000000000000000) + + self.gridLayout_19.addWidget(self.feedrate_probe_dsb, 2, 1, 1, 1) + + self.probe_feedrate_la = QLabel(self.jobs_machine_settings_tab) + self.probe_feedrate_la.setObjectName(u"probe_feedrate_la") + sizePolicy3.setHeightForWidth(self.probe_feedrate_la.sizePolicy().hasHeightForWidth()) + self.probe_feedrate_la.setSizePolicy(sizePolicy3) + self.probe_feedrate_la.setMinimumSize(QSize(130, 0)) + self.probe_feedrate_la.setMaximumSize(QSize(130, 16777215)) + self.probe_feedrate_la.setFont(font) + self.probe_feedrate_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + + self.gridLayout_19.addWidget(self.probe_feedrate_la, 2, 0, 1, 1) + + self.horizontalSpacer_6 = QSpacerItem(200, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) + + self.gridLayout_19.addItem(self.horizontalSpacer_6, 0, 2, 1, 1) + + self.horizontalSpacer_7 = QSpacerItem(200, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) + + self.gridLayout_19.addItem(self.horizontalSpacer_7, 1, 2, 1, 1) + + self.horizontalSpacer_8 = QSpacerItem(200, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) + + self.gridLayout_19.addItem(self.horizontalSpacer_8, 2, 2, 1, 1) + + + self.gridLayout_13.addLayout(self.gridLayout_19, 20, 0, 1, 1) + + self.verticalLayout_5 = QVBoxLayout() + self.verticalLayout_5.setSpacing(2) + self.verticalLayout_5.setObjectName(u"verticalLayout_5") + self.verticalLayout_5.setSizeConstraint(QLayout.SetFixedSize) + self.horizontalLayout_13 = QHBoxLayout() + self.horizontalLayout_13.setObjectName(u"horizontalLayout_13") + self.gridLayout_14 = QGridLayout() + self.gridLayout_14.setObjectName(u"gridLayout_14") + self.gridLayout_14.setSizeConstraint(QLayout.SetDefaultConstraint) + self.gridLayout_14.setVerticalSpacing(2) + self.tool_probe_y_wpos_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) + self.tool_probe_y_wpos_dsb.setObjectName(u"tool_probe_y_wpos_dsb") + sizePolicy3.setHeightForWidth(self.tool_probe_y_wpos_dsb.sizePolicy().hasHeightForWidth()) + self.tool_probe_y_wpos_dsb.setSizePolicy(sizePolicy3) + self.tool_probe_y_wpos_dsb.setMinimumSize(QSize(80, 20)) + self.tool_probe_y_wpos_dsb.setMaximumSize(QSize(80, 16777215)) + self.tool_probe_y_wpos_dsb.setFont(font) + self.tool_probe_y_wpos_dsb.setAlignment(Qt.AlignCenter) + self.tool_probe_y_wpos_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) + self.tool_probe_y_wpos_dsb.setMinimum(-1000.000000000000000) + self.tool_probe_y_wpos_dsb.setMaximum(1000.000000000000000) + self.tool_probe_y_wpos_dsb.setSingleStep(0.100000000000000) + + self.gridLayout_14.addWidget(self.tool_probe_y_wpos_dsb, 2, 2, 1, 1) + + self.tool_probe_y_mpos_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) + self.tool_probe_y_mpos_dsb.setObjectName(u"tool_probe_y_mpos_dsb") + sizePolicy3.setHeightForWidth(self.tool_probe_y_mpos_dsb.sizePolicy().hasHeightForWidth()) + self.tool_probe_y_mpos_dsb.setSizePolicy(sizePolicy3) + self.tool_probe_y_mpos_dsb.setMinimumSize(QSize(80, 20)) + self.tool_probe_y_mpos_dsb.setMaximumSize(QSize(80, 16777215)) + self.tool_probe_y_mpos_dsb.setFont(font) + self.tool_probe_y_mpos_dsb.setAlignment(Qt.AlignCenter) + self.tool_probe_y_mpos_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) + self.tool_probe_y_mpos_dsb.setMinimum(-1000.000000000000000) + self.tool_probe_y_mpos_dsb.setMaximum(1000.000000000000000) + self.tool_probe_y_mpos_dsb.setSingleStep(0.100000000000000) + + self.gridLayout_14.addWidget(self.tool_probe_y_mpos_dsb, 1, 2, 1, 1) + + self.x_la = QLabel(self.jobs_machine_settings_tab) + self.x_la.setObjectName(u"x_la") + sizePolicy3.setHeightForWidth(self.x_la.sizePolicy().hasHeightForWidth()) + self.x_la.setSizePolicy(sizePolicy3) + self.x_la.setMaximumSize(QSize(80, 50)) + self.x_la.setFont(font) + self.x_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + + self.gridLayout_14.addWidget(self.x_la, 0, 1, 1, 1, Qt.AlignHCenter) + + self.y_la = QLabel(self.jobs_machine_settings_tab) + self.y_la.setObjectName(u"y_la") + sizePolicy3.setHeightForWidth(self.y_la.sizePolicy().hasHeightForWidth()) + self.y_la.setSizePolicy(sizePolicy3) + self.y_la.setMaximumSize(QSize(80, 50)) + self.y_la.setFont(font) + self.y_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + + self.gridLayout_14.addWidget(self.y_la, 0, 2, 1, 1, Qt.AlignHCenter) + + self.tool_probe_z_limit_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) + self.tool_probe_z_limit_dsb.setObjectName(u"tool_probe_z_limit_dsb") + sizePolicy3.setHeightForWidth(self.tool_probe_z_limit_dsb.sizePolicy().hasHeightForWidth()) + self.tool_probe_z_limit_dsb.setSizePolicy(sizePolicy3) + self.tool_probe_z_limit_dsb.setMinimumSize(QSize(80, 20)) + self.tool_probe_z_limit_dsb.setMaximumSize(QSize(80, 16777215)) self.tool_probe_z_limit_dsb.setFont(font) self.tool_probe_z_limit_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) self.tool_probe_z_limit_dsb.setAlignment(Qt.AlignCenter) @@ -2956,7 +3884,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_15.setObjectName(u"horizontalLayout_15") self.gridLayout_15 = QGridLayout() self.gridLayout_15.setObjectName(u"gridLayout_15") - self.gridLayout_15.setSizeConstraint(QLayout.SetFixedSize) + self.gridLayout_15.setSizeConstraint(QLayout.SetDefaultConstraint) self.tool_change_z_mpos_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) self.tool_change_z_mpos_dsb.setObjectName(u"tool_change_z_mpos_dsb") sizePolicy3.setHeightForWidth(self.tool_change_z_mpos_dsb.sizePolicy().hasHeightForWidth()) @@ -3034,245 +3962,264 @@ def setupUi(self, MainWindow): self.verticalLayout_5.addLayout(self.horizontalLayout_15) - self.gridLayout_13.addLayout(self.verticalLayout_5, 11, 0, 1, 1) + self.gridLayout_13.addLayout(self.verticalLayout_5, 14, 0, 1, 1) + + self.line_8 = QFrame(self.jobs_machine_settings_tab) + self.line_8.setObjectName(u"line_8") + self.line_8.setFrameShape(QFrame.HLine) + self.line_8.setFrameShadow(QFrame.Sunken) + + self.gridLayout_13.addWidget(self.line_8, 13, 0, 1, 1) + + self.line_15 = QFrame(self.jobs_machine_settings_tab) + self.line_15.setObjectName(u"line_15") + self.line_15.setFrameShape(QFrame.HLine) + self.line_15.setFrameShadow(QFrame.Sunken) + + self.gridLayout_13.addWidget(self.line_15, 8, 0, 1, 1) + + self.line_9 = QFrame(self.jobs_machine_settings_tab) + self.line_9.setObjectName(u"line_9") + self.line_9.setFrameShape(QFrame.HLine) + self.line_9.setFrameShadow(QFrame.Sunken) + + self.gridLayout_13.addWidget(self.line_9, 17, 0, 1, 1) self.line_7 = QFrame(self.jobs_machine_settings_tab) self.line_7.setObjectName(u"line_7") self.line_7.setFrameShape(QFrame.HLine) self.line_7.setFrameShadow(QFrame.Sunken) - self.gridLayout_13.addWidget(self.line_7, 12, 0, 1, 1) + self.gridLayout_13.addWidget(self.line_7, 15, 0, 1, 1) - self.gridLayout_20 = QGridLayout() - self.gridLayout_20.setObjectName(u"gridLayout_20") - self.gridLayout_20.setSizeConstraint(QLayout.SetFixedSize) - self.x_axis_la = QLabel(self.jobs_machine_settings_tab) - self.x_axis_la.setObjectName(u"x_axis_la") - sizePolicy3.setHeightForWidth(self.x_axis_la.sizePolicy().hasHeightForWidth()) - self.x_axis_la.setSizePolicy(sizePolicy3) - self.x_axis_la.setMinimumSize(QSize(150, 20)) - self.x_axis_la.setMaximumSize(QSize(150, 20)) - self.x_axis_la.setFont(font) - self.x_axis_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.verticalSpacer_4 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.gridLayout_20.addWidget(self.x_axis_la, 0, 1, 1, 1, Qt.AlignHCenter) + self.gridLayout_13.addItem(self.verticalSpacer_4, 16, 0, 1, 1) - self.x_la_2 = QLabel(self.jobs_machine_settings_tab) - self.x_la_2.setObjectName(u"x_la_2") - sizePolicy3.setHeightForWidth(self.x_la_2.sizePolicy().hasHeightForWidth()) - self.x_la_2.setSizePolicy(sizePolicy3) - self.x_la_2.setMinimumSize(QSize(150, 20)) - self.x_la_2.setMaximumSize(QSize(150, 20)) - self.x_la_2.setFont(font) - self.x_la_2.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.line_12 = QFrame(self.jobs_machine_settings_tab) + self.line_12.setObjectName(u"line_12") + self.line_12.setFrameShape(QFrame.HLine) + self.line_12.setFrameShadow(QFrame.Sunken) - self.gridLayout_20.addWidget(self.x_la_2, 0, 2, 1, 1, Qt.AlignHCenter) + self.gridLayout_13.addWidget(self.line_12, 0, 0, 1, 1) - self.mirroring_axis_la = QLabel(self.jobs_machine_settings_tab) - self.mirroring_axis_la.setObjectName(u"mirroring_axis_la") - sizePolicy3.setHeightForWidth(self.mirroring_axis_la.sizePolicy().hasHeightForWidth()) - self.mirroring_axis_la.setSizePolicy(sizePolicy3) - self.mirroring_axis_la.setMinimumSize(QSize(130, 0)) - self.mirroring_axis_la.setMaximumSize(QSize(130, 16777215)) - self.mirroring_axis_la.setFont(font) - self.mirroring_axis_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.verticalLayout_4 = QVBoxLayout() + self.verticalLayout_4.setSpacing(2) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") + self.verticalLayout_4.setSizeConstraint(QLayout.SetFixedSize) + self.gridLayout_21 = QGridLayout() + self.gridLayout_21.setObjectName(u"gridLayout_21") + self.gridLayout_21.setHorizontalSpacing(0) + self.gridLayout_21.setVerticalSpacing(2) + self.horizontalSpacer_10 = QSpacerItem(180, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) - self.gridLayout_20.addWidget(self.mirroring_axis_la, 1, 0, 1, 1, Qt.AlignLeft|Qt.AlignVCenter) + self.gridLayout_21.addItem(self.horizontalSpacer_10, 0, 0, 1, 1) - self.x_mirror_rb = QRadioButton(self.jobs_machine_settings_tab) - self.x_mirror_rb.setObjectName(u"x_mirror_rb") - sizePolicy3.setHeightForWidth(self.x_mirror_rb.sizePolicy().hasHeightForWidth()) - self.x_mirror_rb.setSizePolicy(sizePolicy3) - self.x_mirror_rb.setMaximumSize(QSize(120, 20)) + self.hold_on_probe_chb = QCheckBox(self.jobs_machine_settings_tab) + self.hold_on_probe_chb.setObjectName(u"hold_on_probe_chb") + sizePolicy3.setHeightForWidth(self.hold_on_probe_chb.sizePolicy().hasHeightForWidth()) + self.hold_on_probe_chb.setSizePolicy(sizePolicy3) + self.hold_on_probe_chb.setMinimumSize(QSize(150, 0)) + self.hold_on_probe_chb.setMaximumSize(QSize(150, 16777215)) - self.gridLayout_20.addWidget(self.x_mirror_rb, 1, 1, 1, 1, Qt.AlignHCenter) + self.gridLayout_21.addWidget(self.hold_on_probe_chb, 0, 1, 1, 1, Qt.AlignHCenter) - self.y_mirror_rb = QRadioButton(self.jobs_machine_settings_tab) - self.y_mirror_rb.setObjectName(u"y_mirror_rb") - sizePolicy3.setHeightForWidth(self.y_mirror_rb.sizePolicy().hasHeightForWidth()) - self.y_mirror_rb.setSizePolicy(sizePolicy3) - self.y_mirror_rb.setMaximumSize(QSize(120, 20)) + self.zeroing_after_probe_chb = QCheckBox(self.jobs_machine_settings_tab) + self.zeroing_after_probe_chb.setObjectName(u"zeroing_after_probe_chb") + sizePolicy3.setHeightForWidth(self.zeroing_after_probe_chb.sizePolicy().hasHeightForWidth()) + self.zeroing_after_probe_chb.setSizePolicy(sizePolicy3) + self.zeroing_after_probe_chb.setMinimumSize(QSize(150, 0)) + self.zeroing_after_probe_chb.setMaximumSize(QSize(150, 16777215)) - self.gridLayout_20.addWidget(self.y_mirror_rb, 1, 2, 1, 1, Qt.AlignHCenter) + self.gridLayout_21.addWidget(self.zeroing_after_probe_chb, 0, 2, 1, 1, Qt.AlignHCenter) - self.horizontalSpacer_9 = QSpacerItem(130, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) - self.gridLayout_20.addItem(self.horizontalSpacer_9, 0, 0, 1, 1) + self.verticalLayout_4.addLayout(self.gridLayout_21) - self.gridLayout_13.addLayout(self.gridLayout_20, 3, 0, 1, 1) + self.gridLayout_13.addLayout(self.verticalLayout_4, 9, 0, 1, 1) - self.line_12 = QFrame(self.jobs_machine_settings_tab) - self.line_12.setObjectName(u"line_12") - self.line_12.setFrameShape(QFrame.HLine) - self.line_12.setFrameShadow(QFrame.Sunken) + self.feedrates_section_la = QLabel(self.jobs_machine_settings_tab) + self.feedrates_section_la.setObjectName(u"feedrates_section_la") + self.feedrates_section_la.setFont(font4) - self.gridLayout_13.addWidget(self.line_12, 0, 0, 1, 1) + self.gridLayout_13.addWidget(self.feedrates_section_la, 18, 0, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) - self.gridLayout_19 = QGridLayout() - self.gridLayout_19.setObjectName(u"gridLayout_19") - self.gridLayout_19.setVerticalSpacing(2) - self.feedrate_z_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) - self.feedrate_z_dsb.setObjectName(u"feedrate_z_dsb") - self.feedrate_z_dsb.setMinimumSize(QSize(252, 0)) - self.feedrate_z_dsb.setMaximumSize(QSize(252, 16777215)) - self.feedrate_z_dsb.setFont(font) - self.feedrate_z_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.feedrate_z_dsb.setAlignment(Qt.AlignCenter) - self.feedrate_z_dsb.setButtonSymbols(QAbstractSpinBox.UpDownArrows) - self.feedrate_z_dsb.setMaximum(100000.000000000000000) - self.feedrate_z_dsb.setSingleStep(1.000000000000000) + self.line_11 = QFrame(self.jobs_machine_settings_tab) + self.line_11.setObjectName(u"line_11") + self.line_11.setFrameShape(QFrame.HLine) + self.line_11.setFrameShadow(QFrame.Sunken) - self.gridLayout_19.addWidget(self.feedrate_z_dsb, 1, 1, 1, 1) + self.gridLayout_13.addWidget(self.line_11, 2, 0, 1, 1) - self.z_feedrate_la = QLabel(self.jobs_machine_settings_tab) - self.z_feedrate_la.setObjectName(u"z_feedrate_la") - sizePolicy13 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) - sizePolicy13.setHorizontalStretch(0) - sizePolicy13.setVerticalStretch(0) - sizePolicy13.setHeightForWidth(self.z_feedrate_la.sizePolicy().hasHeightForWidth()) - self.z_feedrate_la.setSizePolicy(sizePolicy13) - self.z_feedrate_la.setMinimumSize(QSize(130, 0)) - self.z_feedrate_la.setMaximumSize(QSize(130, 16777215)) - self.z_feedrate_la.setFont(font) - self.z_feedrate_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.line_13 = QFrame(self.jobs_machine_settings_tab) + self.line_13.setObjectName(u"line_13") + self.line_13.setFrameShape(QFrame.HLine) + self.line_13.setFrameShadow(QFrame.Sunken) - self.gridLayout_19.addWidget(self.z_feedrate_la, 1, 0, 1, 1) + self.gridLayout_13.addWidget(self.line_13, 4, 0, 1, 1) - self.xy_feedrate_la = QLabel(self.jobs_machine_settings_tab) - self.xy_feedrate_la.setObjectName(u"xy_feedrate_la") - sizePolicy3.setHeightForWidth(self.xy_feedrate_la.sizePolicy().hasHeightForWidth()) - self.xy_feedrate_la.setSizePolicy(sizePolicy3) - self.xy_feedrate_la.setMinimumSize(QSize(130, 0)) - self.xy_feedrate_la.setMaximumSize(QSize(130, 16777215)) - self.xy_feedrate_la.setFont(font) - self.xy_feedrate_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.line_14 = QFrame(self.jobs_machine_settings_tab) + self.line_14.setObjectName(u"line_14") + self.line_14.setFrameShape(QFrame.HLine) + self.line_14.setFrameShadow(QFrame.Sunken) - self.gridLayout_19.addWidget(self.xy_feedrate_la, 0, 0, 1, 1) + self.gridLayout_13.addWidget(self.line_14, 11, 0, 1, 1) - self.feedrate_xy_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) - self.feedrate_xy_dsb.setObjectName(u"feedrate_xy_dsb") - sizePolicy3.setHeightForWidth(self.feedrate_xy_dsb.sizePolicy().hasHeightForWidth()) - self.feedrate_xy_dsb.setSizePolicy(sizePolicy3) - self.feedrate_xy_dsb.setMinimumSize(QSize(252, 0)) - self.feedrate_xy_dsb.setMaximumSize(QSize(252, 16777215)) - self.feedrate_xy_dsb.setFont(font) - self.feedrate_xy_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.feedrate_xy_dsb.setAlignment(Qt.AlignCenter) - self.feedrate_xy_dsb.setButtonSymbols(QAbstractSpinBox.UpDownArrows) - self.feedrate_xy_dsb.setMaximum(100000.000000000000000) - self.feedrate_xy_dsb.setSingleStep(1.000000000000000) + self.settings_sub_tab.addTab(self.jobs_machine_settings_tab, "") + self.alignment_settings_tab = QWidget() + self.alignment_settings_tab.setObjectName(u"alignment_settings_tab") + self.horizontalLayout_24 = QHBoxLayout(self.alignment_settings_tab) + self.horizontalLayout_24.setObjectName(u"horizontalLayout_24") + self.verticalLayout_15 = QVBoxLayout() + self.verticalLayout_15.setObjectName(u"verticalLayout_15") + self.line_21 = QFrame(self.alignment_settings_tab) + self.line_21.setObjectName(u"line_21") + self.line_21.setFrameShape(QFrame.HLine) + self.line_21.setFrameShadow(QFrame.Sunken) - self.gridLayout_19.addWidget(self.feedrate_xy_dsb, 0, 1, 1, 1) + self.verticalLayout_15.addWidget(self.line_21) - self.feedrate_probe_dsb = QDoubleSpinBox(self.jobs_machine_settings_tab) - self.feedrate_probe_dsb.setObjectName(u"feedrate_probe_dsb") - self.feedrate_probe_dsb.setMinimumSize(QSize(252, 0)) - self.feedrate_probe_dsb.setMaximumSize(QSize(252, 16777215)) - self.feedrate_probe_dsb.setFont(font) - self.feedrate_probe_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.feedrate_probe_dsb.setAlignment(Qt.AlignCenter) - self.feedrate_probe_dsb.setButtonSymbols(QAbstractSpinBox.UpDownArrows) - self.feedrate_probe_dsb.setMaximum(100000.000000000000000) - self.feedrate_probe_dsb.setSingleStep(1.000000000000000) + self.alignment_drill_section_la = QLabel(self.alignment_settings_tab) + self.alignment_drill_section_la.setObjectName(u"alignment_drill_section_la") + self.alignment_drill_section_la.setFont(font4) - self.gridLayout_19.addWidget(self.feedrate_probe_dsb, 2, 1, 1, 1) + self.verticalLayout_15.addWidget(self.alignment_drill_section_la, 0, Qt.AlignHCenter) - self.probe_feedrate_la = QLabel(self.jobs_machine_settings_tab) - self.probe_feedrate_la.setObjectName(u"probe_feedrate_la") - sizePolicy3.setHeightForWidth(self.probe_feedrate_la.sizePolicy().hasHeightForWidth()) - self.probe_feedrate_la.setSizePolicy(sizePolicy3) - self.probe_feedrate_la.setMinimumSize(QSize(130, 0)) - self.probe_feedrate_la.setMaximumSize(QSize(130, 16777215)) - self.probe_feedrate_la.setFont(font) - self.probe_feedrate_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.line_22 = QFrame(self.alignment_settings_tab) + self.line_22.setObjectName(u"line_22") + self.line_22.setFrameShape(QFrame.HLine) + self.line_22.setFrameShadow(QFrame.Sunken) - self.gridLayout_19.addWidget(self.probe_feedrate_la, 2, 0, 1, 1) + self.verticalLayout_15.addWidget(self.line_22) - self.horizontalSpacer_6 = QSpacerItem(200, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) + self.horizontalLayout_25 = QHBoxLayout() + self.horizontalLayout_25.setObjectName(u"horizontalLayout_25") + self.allignment_drill_diameter_la = QLabel(self.alignment_settings_tab) + self.allignment_drill_diameter_la.setObjectName(u"allignment_drill_diameter_la") + sizePolicy3.setHeightForWidth(self.allignment_drill_diameter_la.sizePolicy().hasHeightForWidth()) + self.allignment_drill_diameter_la.setSizePolicy(sizePolicy3) + self.allignment_drill_diameter_la.setMinimumSize(QSize(200, 0)) + self.allignment_drill_diameter_la.setMaximumSize(QSize(130, 16777215)) + self.allignment_drill_diameter_la.setFont(font) + self.allignment_drill_diameter_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.gridLayout_19.addItem(self.horizontalSpacer_6, 0, 2, 1, 1) + self.horizontalLayout_25.addWidget(self.allignment_drill_diameter_la) - self.horizontalSpacer_7 = QSpacerItem(200, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) + self.alignment_drill_diameter_dsb = QDoubleSpinBox(self.alignment_settings_tab) + self.alignment_drill_diameter_dsb.setObjectName(u"alignment_drill_diameter_dsb") + sizePolicy3.setHeightForWidth(self.alignment_drill_diameter_dsb.sizePolicy().hasHeightForWidth()) + self.alignment_drill_diameter_dsb.setSizePolicy(sizePolicy3) + self.alignment_drill_diameter_dsb.setMinimumSize(QSize(252, 0)) + self.alignment_drill_diameter_dsb.setMaximumSize(QSize(252, 16777215)) + self.alignment_drill_diameter_dsb.setFont(font) + self.alignment_drill_diameter_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.alignment_drill_diameter_dsb.setAlignment(Qt.AlignCenter) + self.alignment_drill_diameter_dsb.setButtonSymbols(QAbstractSpinBox.UpDownArrows) + self.alignment_drill_diameter_dsb.setMaximum(100000.000000000000000) + self.alignment_drill_diameter_dsb.setSingleStep(1.000000000000000) - self.gridLayout_19.addItem(self.horizontalSpacer_7, 1, 2, 1, 1) + self.horizontalLayout_25.addWidget(self.alignment_drill_diameter_dsb) - self.horizontalSpacer_8 = QSpacerItem(200, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) - self.gridLayout_19.addItem(self.horizontalSpacer_8, 2, 2, 1, 1) + self.verticalLayout_15.addLayout(self.horizontalLayout_25) + self.verticalSpacer_10 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.gridLayout_13.addLayout(self.gridLayout_19, 17, 0, 1, 1) + self.verticalLayout_15.addItem(self.verticalSpacer_10) - self.line_8 = QFrame(self.jobs_machine_settings_tab) - self.line_8.setObjectName(u"line_8") - self.line_8.setFrameShape(QFrame.HLine) - self.line_8.setFrameShadow(QFrame.Sunken) + self.line_23 = QFrame(self.alignment_settings_tab) + self.line_23.setObjectName(u"line_23") + self.line_23.setFrameShape(QFrame.HLine) + self.line_23.setFrameShadow(QFrame.Sunken) - self.gridLayout_13.addWidget(self.line_8, 10, 0, 1, 1) + self.verticalLayout_15.addWidget(self.line_23) - self.feedrates_section_la = QLabel(self.jobs_machine_settings_tab) - self.feedrates_section_la.setObjectName(u"feedrates_section_la") - self.feedrates_section_la.setFont(font3) + self.alignment_camera_tool_offset_section_la = QLabel(self.alignment_settings_tab) + self.alignment_camera_tool_offset_section_la.setObjectName(u"alignment_camera_tool_offset_section_la") + self.alignment_camera_tool_offset_section_la.setFont(font4) - self.gridLayout_13.addWidget(self.feedrates_section_la, 15, 0, 1, 1, Qt.AlignHCenter|Qt.AlignVCenter) + self.verticalLayout_15.addWidget(self.alignment_camera_tool_offset_section_la, 0, Qt.AlignHCenter) - self.line_10 = QFrame(self.jobs_machine_settings_tab) - self.line_10.setObjectName(u"line_10") - self.line_10.setFrameShape(QFrame.HLine) - self.line_10.setFrameShadow(QFrame.Sunken) + self.line_24 = QFrame(self.alignment_settings_tab) + self.line_24.setObjectName(u"line_24") + self.line_24.setFrameShape(QFrame.HLine) + self.line_24.setFrameShadow(QFrame.Sunken) - self.gridLayout_13.addWidget(self.line_10, 16, 0, 1, 1) + self.verticalLayout_15.addWidget(self.line_24) - self.jobs_common_settings_section_la = QLabel(self.jobs_machine_settings_tab) - self.jobs_common_settings_section_la.setObjectName(u"jobs_common_settings_section_la") - sizePolicy3.setHeightForWidth(self.jobs_common_settings_section_la.sizePolicy().hasHeightForWidth()) - self.jobs_common_settings_section_la.setSizePolicy(sizePolicy3) - self.jobs_common_settings_section_la.setMinimumSize(QSize(210, 0)) - self.jobs_common_settings_section_la.setMaximumSize(QSize(300, 20)) - self.jobs_common_settings_section_la.setFont(font3) + self.gridLayout_17 = QGridLayout() + self.gridLayout_17.setObjectName(u"gridLayout_17") + self.gridLayout_17.setSizeConstraint(QLayout.SetDefaultConstraint) + self.tool_camera_offset_la = QLabel(self.alignment_settings_tab) + self.tool_camera_offset_la.setObjectName(u"tool_camera_offset_la") + sizePolicy3.setHeightForWidth(self.tool_camera_offset_la.sizePolicy().hasHeightForWidth()) + self.tool_camera_offset_la.setSizePolicy(sizePolicy3) + self.tool_camera_offset_la.setMinimumSize(QSize(130, 20)) + self.tool_camera_offset_la.setMaximumSize(QSize(130, 16777215)) + self.tool_camera_offset_la.setFont(font) + self.tool_camera_offset_la.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.gridLayout_13.addWidget(self.jobs_common_settings_section_la, 1, 0, 1, 1, Qt.AlignHCenter) + self.gridLayout_17.addWidget(self.tool_camera_offset_la, 0, 0, 1, 1) - self.line_14 = QFrame(self.jobs_machine_settings_tab) - self.line_14.setObjectName(u"line_14") - self.line_14.setFrameShape(QFrame.HLine) - self.line_14.setFrameShadow(QFrame.Sunken) + self.y_tool_camera_offset_dsb = QDoubleSpinBox(self.alignment_settings_tab) + self.y_tool_camera_offset_dsb.setObjectName(u"y_tool_camera_offset_dsb") + sizePolicy3.setHeightForWidth(self.y_tool_camera_offset_dsb.sizePolicy().hasHeightForWidth()) + self.y_tool_camera_offset_dsb.setSizePolicy(sizePolicy3) + self.y_tool_camera_offset_dsb.setMinimumSize(QSize(80, 20)) + self.y_tool_camera_offset_dsb.setMaximumSize(QSize(80, 16777215)) + self.y_tool_camera_offset_dsb.setFont(font) + self.y_tool_camera_offset_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.y_tool_camera_offset_dsb.setAlignment(Qt.AlignCenter) + self.y_tool_camera_offset_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) + self.y_tool_camera_offset_dsb.setMinimum(-1000.000000000000000) + self.y_tool_camera_offset_dsb.setMaximum(1000.000000000000000) + self.y_tool_camera_offset_dsb.setSingleStep(0.100000000000000) - self.gridLayout_13.addWidget(self.line_14, 8, 0, 1, 1) + self.gridLayout_17.addWidget(self.y_tool_camera_offset_dsb, 0, 2, 1, 1) - self.verticalSpacer_4 = QSpacerItem(20, 10, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.get_tool_camera_offset_pb = QPushButton(self.alignment_settings_tab) + self.get_tool_camera_offset_pb.setObjectName(u"get_tool_camera_offset_pb") + sizePolicy3.setHeightForWidth(self.get_tool_camera_offset_pb.sizePolicy().hasHeightForWidth()) + self.get_tool_camera_offset_pb.setSizePolicy(sizePolicy3) + self.get_tool_camera_offset_pb.setMinimumSize(QSize(150, 20)) + self.get_tool_camera_offset_pb.setMaximumSize(QSize(180, 20)) + self.get_tool_camera_offset_pb.setFont(font) + self.get_tool_camera_offset_pb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) - self.gridLayout_13.addItem(self.verticalSpacer_4, 13, 0, 1, 1) + self.gridLayout_17.addWidget(self.get_tool_camera_offset_pb, 0, 4, 1, 1, Qt.AlignHCenter) - self.tool_change_section_la = QLabel(self.jobs_machine_settings_tab) - self.tool_change_section_la.setObjectName(u"tool_change_section_la") - sizePolicy3.setHeightForWidth(self.tool_change_section_la.sizePolicy().hasHeightForWidth()) - self.tool_change_section_la.setSizePolicy(sizePolicy3) - self.tool_change_section_la.setFont(font3) + self.x_tool_camera_offset_dsb = QDoubleSpinBox(self.alignment_settings_tab) + self.x_tool_camera_offset_dsb.setObjectName(u"x_tool_camera_offset_dsb") + sizePolicy3.setHeightForWidth(self.x_tool_camera_offset_dsb.sizePolicy().hasHeightForWidth()) + self.x_tool_camera_offset_dsb.setSizePolicy(sizePolicy3) + self.x_tool_camera_offset_dsb.setMinimumSize(QSize(80, 20)) + self.x_tool_camera_offset_dsb.setMaximumSize(QSize(80, 16777215)) + self.x_tool_camera_offset_dsb.setFont(font) + self.x_tool_camera_offset_dsb.setLocale(QLocale(QLocale.English, QLocale.UnitedKingdom)) + self.x_tool_camera_offset_dsb.setAlignment(Qt.AlignCenter) + self.x_tool_camera_offset_dsb.setButtonSymbols(QAbstractSpinBox.NoButtons) + self.x_tool_camera_offset_dsb.setMinimum(-1000.000000000000000) + self.x_tool_camera_offset_dsb.setMaximum(1000.000000000000000) + self.x_tool_camera_offset_dsb.setSingleStep(0.100000000000000) - self.gridLayout_13.addWidget(self.tool_change_section_la, 9, 0, 1, 1, Qt.AlignHCenter) + self.gridLayout_17.addWidget(self.x_tool_camera_offset_dsb, 0, 1, 1, 1) - self.line_11 = QFrame(self.jobs_machine_settings_tab) - self.line_11.setObjectName(u"line_11") - self.line_11.setFrameShape(QFrame.HLine) - self.line_11.setFrameShadow(QFrame.Sunken) - self.gridLayout_13.addWidget(self.line_11, 2, 0, 1, 1) + self.verticalLayout_15.addLayout(self.gridLayout_17) - self.horizontalSpacer_4 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.verticalSpacer_11 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.gridLayout_13.addItem(self.horizontalSpacer_4, 11, 1, 1, 1) + self.verticalLayout_15.addItem(self.verticalSpacer_11) - self.verticalSpacer_6 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) - self.gridLayout_13.addItem(self.verticalSpacer_6, 7, 0, 1, 1) + self.horizontalLayout_24.addLayout(self.verticalLayout_15) - self.verticalSpacer_5 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.horizontalSpacer_12 = QSpacerItem(623, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) - self.gridLayout_13.addItem(self.verticalSpacer_5, 5, 0, 1, 1) + self.horizontalLayout_24.addItem(self.horizontalSpacer_12) - self.settings_sub_tab.addTab(self.jobs_machine_settings_tab, "") + self.settings_sub_tab.addTab(self.alignment_settings_tab, "") self.verticalLayout_12.addWidget(self.settings_sub_tab) @@ -3412,7 +4359,6 @@ def setupUi(self, MainWindow): QWidget.setTabOrder(self.nc_bottom_xy_feed_rate_dsb, self.nc_bottom_z_feed_rate_dsb) QWidget.setTabOrder(self.nc_bottom_z_feed_rate_dsb, self.nc_bottom_generate_pb) QWidget.setTabOrder(self.nc_bottom_generate_pb, self.logging_plain_te) - QWidget.setTabOrder(self.logging_plain_te, self.verticalSlider) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuConsole.menuAction()) @@ -3432,13 +4378,15 @@ def setupUi(self, MainWindow): self.retranslateUi(MainWindow) - self.main_tab_widget.setCurrentIndex(0) - self.prepare_widget.setCurrentIndex(0) + self.main_tab_widget.setCurrentIndex(2) + self.prepare_widget.setCurrentIndex(1) self.jobs_sw.setCurrentIndex(0) - self.ctrl_tab_widget.setCurrentIndex(0) + self.ctrl_tab_widget.setCurrentIndex(1) self.z_step_cb.setCurrentIndex(3) self.xy_step_cb.setCurrentIndex(3) - self.settings_sub_tab.setCurrentIndex(0) + self.z_step_cb_2.setCurrentIndex(3) + self.xy_step_cb_2.setCurrentIndex(3) + self.settings_sub_tab.setCurrentIndex(2) QMetaObject.connectSlotsByName(MainWindow) @@ -3548,17 +4496,20 @@ def retranslateUi(self, MainWindow): self.drill_milling_tool_la.setText(QCoreApplication.translate("MainWindow", u"Milling Tool", None)) self.remove_drill_tool_tb.setText(QCoreApplication.translate("MainWindow", u"-", None)) self.drill_milling_tool_chb.setText("") - self.drill_optimization_la.setText(QCoreApplication.translate("MainWindow", u"Optimization", None)) + self.drill_optimization_la.setText(QCoreApplication.translate("MainWindow", u"Algorithm", None)) ___qtablewidgetitem = self.drill_tw.horizontalHeaderItem(0) ___qtablewidgetitem.setText(QCoreApplication.translate("MainWindow", u"Bit", None)); ___qtablewidgetitem1 = self.drill_tw.horizontalHeaderItem(1) ___qtablewidgetitem1.setText(QCoreApplication.translate("MainWindow", u"Diameter [mm]", None)); - self.drill_optimization_chb.setText("") self.drill_spindle_speed_la.setText(QCoreApplication.translate("MainWindow", u"Spindle Speed", None)) self.drill_milling_tool_diameter_la.setText(QCoreApplication.translate("MainWindow", u"Mill Tool Diameter [mm]", None)) self.drill_generate_job_pb.setText(QCoreApplication.translate("MainWindow", u"Generate Job", None)) self.drill_mirror_la.setText(QCoreApplication.translate("MainWindow", u"Mirror", None)) self.drill_mirror_chb.setText("") + self.drill_algo_choice_cb.setItemText(0, QCoreApplication.translate("MainWindow", u"Nearest Insertion (fast)", None)) + self.drill_algo_choice_cb.setItemText(1, QCoreApplication.translate("MainWindow", u"2-opt (optimal)", None)) + self.drill_algo_choice_cb.setItemText(2, QCoreApplication.translate("MainWindow", u"Genetic", None)) + self.nc_top_overlap_la.setText(QCoreApplication.translate("MainWindow", u"Overlap", None)) self.nc_top_cut_z_la.setText(QCoreApplication.translate("MainWindow", u"Cut Z [mm]", None)) self.nc_top_spindle_speed_la.setText(QCoreApplication.translate("MainWindow", u"Spindle Speed", None)) @@ -3622,24 +4573,24 @@ def retranslateUi(self, MainWindow): self.abl_active_chb.setToolTip(QCoreApplication.translate("MainWindow", u"Apply ABL if checked", None)) #endif // QT_CONFIG(tooltip) self.abl_active_chb.setText("") - self.label_6.setText(QCoreApplication.translate("MainWindow", u"Min", None)) - self.label_7.setText(QCoreApplication.translate("MainWindow", u"Max", None)) - self.label_8.setText(QCoreApplication.translate("MainWindow", u"Step", None)) - self.label_9.setText(QCoreApplication.translate("MainWindow", u"N", None)) - self.label_10.setText(QCoreApplication.translate("MainWindow", u"X", None)) - self.label_11.setText(QCoreApplication.translate("MainWindow", u"Y", None)) - self.label_12.setText(QCoreApplication.translate("MainWindow", u"Z", None)) + self.min_l.setText(QCoreApplication.translate("MainWindow", u"Min", None)) + self.max_l.setText(QCoreApplication.translate("MainWindow", u"Max", None)) + self.step_l.setText(QCoreApplication.translate("MainWindow", u"Step", None)) + self.n_step_l.setText(QCoreApplication.translate("MainWindow", u"N", None)) + self.x_l.setText(QCoreApplication.translate("MainWindow", u"X", None)) + self.y_l.setText(QCoreApplication.translate("MainWindow", u"Y", None)) + self.z_l.setText(QCoreApplication.translate("MainWindow", u"Z", None)) self.z_plus_pb.setText(QCoreApplication.translate("MainWindow", u"Z+", None)) self.z_minus_pb.setText(QCoreApplication.translate("MainWindow", u"Z-", None)) - self.xYMinusPlusButton.setText(QCoreApplication.translate("MainWindow", u"X- Y+", None)) - self.xYPlusMinuButton.setText(QCoreApplication.translate("MainWindow", u"X+ Y-", None)) - self.xMinusButton.setText(QCoreApplication.translate("MainWindow", u"X-", None)) - self.xYMinusButton.setText(QCoreApplication.translate("MainWindow", u"X- Y-", None)) - self.yPlusButton.setText(QCoreApplication.translate("MainWindow", u"Y+", None)) + self.x_minus_y_plus_pb.setText(QCoreApplication.translate("MainWindow", u"X- Y+", None)) + self.x_plus_y_minus_pb.setText(QCoreApplication.translate("MainWindow", u"X+ Y-", None)) + self.x_minus_pb.setText(QCoreApplication.translate("MainWindow", u"X-", None)) + self.x_minus_y_minus_pb.setText(QCoreApplication.translate("MainWindow", u"X- Y-", None)) + self.y_plus_pb.setText(QCoreApplication.translate("MainWindow", u"Y+", None)) self.center_tb.setText(QCoreApplication.translate("MainWindow", u"Center", None)) - self.yMinusButton.setText(QCoreApplication.translate("MainWindow", u"Y-", None)) - self.xYPlusButton.setText(QCoreApplication.translate("MainWindow", u"X+ Y+", None)) - self.xPlusButton.setText(QCoreApplication.translate("MainWindow", u"X+", None)) + self.y_minus_pb.setText(QCoreApplication.translate("MainWindow", u"Y-", None)) + self.x_plus_y_plus_pb.setText(QCoreApplication.translate("MainWindow", u"X+ Y+", None)) + self.x_plus_pb.setText(QCoreApplication.translate("MainWindow", u"X+", None)) self.z_jog_l_2.setText(QCoreApplication.translate("MainWindow", u"Z step [mm]", None)) self.z_step_cb.setItemText(0, QCoreApplication.translate("MainWindow", u"100.0", None)) self.z_step_cb.setItemText(1, QCoreApplication.translate("MainWindow", u"10.0", None)) @@ -3692,6 +4643,15 @@ def retranslateUi(self, MainWindow): #endif // QT_CONFIG(statustip) self.connect_pb.setText(QCoreApplication.translate("MainWindow", u"Connect", None)) self.ctrl_tab_widget.setTabText(self.ctrl_tab_widget.indexOf(self.sender_tab), QCoreApplication.translate("MainWindow", u"Sender", None)) +#if QT_CONFIG(tooltip) + self.probe_led_la.setToolTip(QCoreApplication.translate("MainWindow", u"Probe in idle", None)) +#endif // QT_CONFIG(tooltip) + self.probe_led_la.setText("") +#if QT_CONFIG(tooltip) + self.abl_led_la.setToolTip(QCoreApplication.translate("MainWindow", u"ABL not applied", None)) +#endif // QT_CONFIG(tooltip) + self.abl_led_la.setText("") + self.apply_alignment_tb_2.setText(QCoreApplication.translate("MainWindow", u"...", None)) #if QT_CONFIG(statustip) self.soft_reset_tb.setStatusTip(QCoreApplication.translate("MainWindow", u"Send a soft reset command to the machine.", None)) #endif // QT_CONFIG(statustip) @@ -3722,7 +4682,85 @@ def retranslateUi(self, MainWindow): #endif // QT_CONFIG(statustip) self.tool_change_tb.setText(QCoreApplication.translate("MainWindow", u"TOOL CHANGE", None)) self.main_tab_widget.setTabText(self.main_tab_widget.indexOf(self.control_tab), QCoreApplication.translate("MainWindow", u"CONTROL", None)) - self.label_2.setText("") + self.camera_la.setText("") + self.tool_or_camera_tb.setText(QCoreApplication.translate("MainWindow", u"TOOL POSITION", None)) + self.label_16.setText(QCoreApplication.translate("MainWindow", u"Camera Selection", None)) + self.camera_zoom_la.setText(QCoreApplication.translate("MainWindow", u"Zoom", None)) + self.camera_list_pb.setText(QCoreApplication.translate("MainWindow", u"...", None)) + self.z_plus_pb_2.setText(QCoreApplication.translate("MainWindow", u"Z+", None)) + self.z_minus_pb_2.setText(QCoreApplication.translate("MainWindow", u"Z-", None)) + self.x_minus_y_plus_pb_2.setText(QCoreApplication.translate("MainWindow", u"X- Y+", None)) + self.x_plus_y_minus_pb_2.setText(QCoreApplication.translate("MainWindow", u"X+ Y-", None)) + self.x_minus_pb_2.setText(QCoreApplication.translate("MainWindow", u"X-", None)) + self.x_minus_y_minus_pb_2.setText(QCoreApplication.translate("MainWindow", u"X- Y-", None)) + self.y_plus_pb_2.setText(QCoreApplication.translate("MainWindow", u"Y+", None)) + self.center_tb_2.setText(QCoreApplication.translate("MainWindow", u"Center", None)) + self.y_minus_pb_2.setText(QCoreApplication.translate("MainWindow", u"Y-", None)) + self.x_plus_y_plus_pb_2.setText(QCoreApplication.translate("MainWindow", u"X+ Y+", None)) + self.x_plus_pb_2.setText(QCoreApplication.translate("MainWindow", u"X+", None)) + self.z_jog_l_4.setText(QCoreApplication.translate("MainWindow", u"Z step [mm]", None)) + self.z_step_cb_2.setItemText(0, QCoreApplication.translate("MainWindow", u"100.0", None)) + self.z_step_cb_2.setItemText(1, QCoreApplication.translate("MainWindow", u"10.0", None)) + self.z_step_cb_2.setItemText(2, QCoreApplication.translate("MainWindow", u"5.0", None)) + self.z_step_cb_2.setItemText(3, QCoreApplication.translate("MainWindow", u"1.0", None)) + self.z_step_cb_2.setItemText(4, QCoreApplication.translate("MainWindow", u"0.5", None)) + self.z_step_cb_2.setItemText(5, QCoreApplication.translate("MainWindow", u"0.1", None)) + self.z_step_cb_2.setItemText(6, QCoreApplication.translate("MainWindow", u"0.05", None)) + self.z_step_cb_2.setItemText(7, QCoreApplication.translate("MainWindow", u"0.01", None)) + + self.z_mul_10_pb_2.setText(QCoreApplication.translate("MainWindow", u"x10", None)) + self.z_div_10_pb_2.setText(QCoreApplication.translate("MainWindow", u"\u00f710", None)) + self.z_minus_1_pb_2.setText(QCoreApplication.translate("MainWindow", u"-1.0", None)) + self.z_plus_1_pb_2.setText(QCoreApplication.translate("MainWindow", u"+1.0", None)) + self.xy_jog_l_2.setText(QCoreApplication.translate("MainWindow", u"XY step [mm]", None)) + self.xy_step_cb_2.setItemText(0, QCoreApplication.translate("MainWindow", u"100.0", None)) + self.xy_step_cb_2.setItemText(1, QCoreApplication.translate("MainWindow", u"10.0", None)) + self.xy_step_cb_2.setItemText(2, QCoreApplication.translate("MainWindow", u"5.0", None)) + self.xy_step_cb_2.setItemText(3, QCoreApplication.translate("MainWindow", u"1.0", None)) + self.xy_step_cb_2.setItemText(4, QCoreApplication.translate("MainWindow", u"0.5", None)) + self.xy_step_cb_2.setItemText(5, QCoreApplication.translate("MainWindow", u"0.1", None)) + self.xy_step_cb_2.setItemText(6, QCoreApplication.translate("MainWindow", u"0.05", None)) + self.xy_step_cb_2.setItemText(7, QCoreApplication.translate("MainWindow", u"0.01", None)) + + self.xy_plus_1_pb_2.setText(QCoreApplication.translate("MainWindow", u"+1.0", None)) + self.xy_div_10_pb_2.setText(QCoreApplication.translate("MainWindow", u"\u00f710", None)) + self.xy_mul_10_pb_2.setText(QCoreApplication.translate("MainWindow", u"x10", None)) + self.xy_minus_1_pb_2.setText(QCoreApplication.translate("MainWindow", u"-1.0", None)) + self.z_axis_l_2.setText(QCoreApplication.translate("MainWindow", u"Z", None)) + self.mpos_y_l_2.setText(QCoreApplication.translate("MainWindow", u"0.0", None)) + self.x_axis_l_2.setText(QCoreApplication.translate("MainWindow", u"X", None)) + self.mpos_z_l_2.setText(QCoreApplication.translate("MainWindow", u"0.0", None)) + self.mpos_x_l_2.setText(QCoreApplication.translate("MainWindow", u"0.0", None)) + self.wpos_l_2.setText(QCoreApplication.translate("MainWindow", u"WPos", None)) + self.wpos_x_l_2.setText(QCoreApplication.translate("MainWindow", u"0.0", None)) + self.mpos_l_2.setText(QCoreApplication.translate("MainWindow", u"MPos", None)) + self.wpos_z_l_2.setText(QCoreApplication.translate("MainWindow", u"0.0", None)) + self.axis_l_2.setText(QCoreApplication.translate("MainWindow", u"Axis:", None)) + self.y_axis_l_2.setText(QCoreApplication.translate("MainWindow", u"Y", None)) + self.wpos_y_l_2.setText(QCoreApplication.translate("MainWindow", u"0.0", None)) + self.flip_horizontally_tb.setText(QCoreApplication.translate("MainWindow", u"FLIP HOR", None)) + self.flip_vertically_tb.setText(QCoreApplication.translate("MainWindow", u"FLIP VER", None)) + self.load_align_layer_tb.setText(QCoreApplication.translate("MainWindow", u"...", None)) +#if QT_CONFIG(statustip) + self.add_point_tb.setStatusTip(QCoreApplication.translate("MainWindow", u"Reload gcode files generated.", None)) +#endif // QT_CONFIG(statustip) + self.add_point_tb.setText(QCoreApplication.translate("MainWindow", u"+", None)) +#if QT_CONFIG(statustip) + self.remove_point_tb.setStatusTip(QCoreApplication.translate("MainWindow", u"Load gcode files.", None)) +#endif // QT_CONFIG(statustip) + self.remove_point_tb.setText(QCoreApplication.translate("MainWindow", u"-", None)) +#if QT_CONFIG(shortcut) + self.remove_point_tb.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+G", None)) +#endif // QT_CONFIG(shortcut) +#if QT_CONFIG(tooltip) + self.apply_alignment_tb.setToolTip(QCoreApplication.translate("MainWindow", u"Apply Alignment", None)) +#endif // QT_CONFIG(tooltip) +#if QT_CONFIG(statustip) + self.apply_alignment_tb.setStatusTip(QCoreApplication.translate("MainWindow", u"Remove gcode files.", None)) +#endif // QT_CONFIG(statustip) + self.apply_alignment_tb.setText(QCoreApplication.translate("MainWindow", u"...", None)) + self.label_17.setText(QCoreApplication.translate("MainWindow", u"Error/STD_Deviation", None)) + self.label_18.setText(QCoreApplication.translate("MainWindow", u"No value available", None)) self.main_tab_widget.setTabText(self.main_tab_widget.indexOf(self.align_tab), QCoreApplication.translate("MainWindow", u"ALIGN", None)) self.top_layer_color_pb.setText(QCoreApplication.translate("MainWindow", u"TOP LAYER COLOR", None)) self.bottom_layer_color_pb.setText(QCoreApplication.translate("MainWindow", u"BOTTOM LAYER COLOR", None)) @@ -3738,9 +4776,17 @@ def retranslateUi(self, MainWindow): self.nc_bottom_layer_color_la.setText("") self.layer_colors_section_la.setText(QCoreApplication.translate("MainWindow", u"LAYER COLORS", None)) self.settings_sub_tab.setTabText(self.settings_sub_tab.indexOf(self.application_settings_tab), QCoreApplication.translate("MainWindow", u"Application Settings", None)) + self.x_axis_la.setText(QCoreApplication.translate("MainWindow", u"X (top-down mirror)", None)) + self.x_la_2.setText(QCoreApplication.translate("MainWindow", u"Y (left-right mirror)", None)) + self.mirroring_axis_la.setText(QCoreApplication.translate("MainWindow", u"Mirroring axis", None)) + self.x_mirror_rb.setText("") + self.y_mirror_rb.setText("") self.probe_settings_section_la.setText(QCoreApplication.translate("MainWindow", u"PROBE SETTINGS", None)) - self.hold_on_probe_chb.setText(QCoreApplication.translate("MainWindow", u"Hold On Probe", None)) - self.zeroing_after_probe_chb.setText(QCoreApplication.translate("MainWindow", u"Z=0 After Probe", None)) + self.tool_change_section_la.setText(QCoreApplication.translate("MainWindow", u"TOOL CHANGE", None)) + self.jobs_common_settings_section_la.setText(QCoreApplication.translate("MainWindow", u"JOBS COMMON SETTINGS", None)) + self.z_feedrate_la.setText(QCoreApplication.translate("MainWindow", u"Z FEEDRATE", None)) + self.xy_feedrate_la.setText(QCoreApplication.translate("MainWindow", u"XY FEEDRATE", None)) + self.probe_feedrate_la.setText(QCoreApplication.translate("MainWindow", u"PROBE FEEDRATE", None)) self.x_la.setText(QCoreApplication.translate("MainWindow", u"X", None)) self.y_la.setText(QCoreApplication.translate("MainWindow", u"Y", None)) self.z_la.setText(QCoreApplication.translate("MainWindow", u"Z", None)) @@ -3751,18 +4797,16 @@ def retranslateUi(self, MainWindow): self.get_tool_probe_pb.setText(QCoreApplication.translate("MainWindow", u"Get Tool Probe Position", None)) self.tool_change_la.setText(QCoreApplication.translate("MainWindow", u"Tool Change MPos", None)) self.get_tool_change_pb.setText(QCoreApplication.translate("MainWindow", u"Get Tool Change Position", None)) - self.x_axis_la.setText(QCoreApplication.translate("MainWindow", u"X (top-down mirror)", None)) - self.x_la_2.setText(QCoreApplication.translate("MainWindow", u"Y (left-right mirror)", None)) - self.mirroring_axis_la.setText(QCoreApplication.translate("MainWindow", u"Mirroring axis", None)) - self.x_mirror_rb.setText("") - self.y_mirror_rb.setText("") - self.z_feedrate_la.setText(QCoreApplication.translate("MainWindow", u"Z FEEDRATE", None)) - self.xy_feedrate_la.setText(QCoreApplication.translate("MainWindow", u"XY FEEDRATE", None)) - self.probe_feedrate_la.setText(QCoreApplication.translate("MainWindow", u"PROBE FEEDRATE", None)) + self.hold_on_probe_chb.setText(QCoreApplication.translate("MainWindow", u"Hold On Probe", None)) + self.zeroing_after_probe_chb.setText(QCoreApplication.translate("MainWindow", u"Z=0 After Probe", None)) self.feedrates_section_la.setText(QCoreApplication.translate("MainWindow", u"FEEDRATES [mm/min]", None)) - self.jobs_common_settings_section_la.setText(QCoreApplication.translate("MainWindow", u"JOBS COMMON SETTINGS", None)) - self.tool_change_section_la.setText(QCoreApplication.translate("MainWindow", u"TOOL CHANGE", None)) self.settings_sub_tab.setTabText(self.settings_sub_tab.indexOf(self.jobs_machine_settings_tab), QCoreApplication.translate("MainWindow", u"Jobs/Machine Settings", None)) + self.alignment_drill_section_la.setText(QCoreApplication.translate("MainWindow", u"ALIGNMENT DRILL SETTINGS", None)) + self.allignment_drill_diameter_la.setText(QCoreApplication.translate("MainWindow", u"Alignment Drill diameter [mm]", None)) + self.alignment_camera_tool_offset_section_la.setText(QCoreApplication.translate("MainWindow", u"CAMERA/TOOL OFFSET", None)) + self.tool_camera_offset_la.setText(QCoreApplication.translate("MainWindow", u"Tool-Camera Offset", None)) + self.get_tool_camera_offset_pb.setText(QCoreApplication.translate("MainWindow", u"Get Tool Camera Offset", None)) + self.settings_sub_tab.setTabText(self.settings_sub_tab.indexOf(self.alignment_settings_tab), QCoreApplication.translate("MainWindow", u"Alignment Settings", None)) self.restore_settings_preferences_pb.setText(QCoreApplication.translate("MainWindow", u"Restore Settings/Preferences", None)) self.save_settings_preferences_pb.setText(QCoreApplication.translate("MainWindow", u"Save Settings/Preferences", None)) self.main_tab_widget.setTabText(self.main_tab_widget.indexOf(self.settings_tab), QCoreApplication.translate("MainWindow", u"Settings/Preferences", None))